Files
Django/products/views/alipay_czjilu_notify.py

118 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""支付宝 Czjilu 类充值统一异步回调视图。
所有基于 Czjilu 表的支付宝支付(押金/积分/会员/商家充值/考核/罚款)
共用一个回调入口,按 Czjilu.leixing 路由到对应履约函数。
"""
import logging
import traceback
from django.http import HttpResponse
from django.views import View
from products.models import Czjilu
from products.czjilu_types import (
CZJILU_LEIXING_HUIYUAN, CZJILU_LEIXING_YAJIN, CZJILU_LEIXING_JIFEN,
CZJILU_LEIXING_SHANGJIA, CZJILU_LEIXING_KAOHE, CZJILU_LEIXING_FAKUAN,
)
logger = logging.getLogger(__name__)
class AlipayCzjiluNotifyView(View):
"""支付宝 Czjilu 充值统一回调:验签 + 按 leixing 路由履约。
路径:/shangpin/alipay-czjilu-notify/
不需要 JWT 认证,由支付宝服务器调用。
"""
def post(self, request):
try:
# 注意:必须用 .dict() 而不是 dict()
# dict(request.POST) 返回 {key: [value_list]}(值是列表)
# request.POST.dict() 返回 {key: value}(值是字符串),符合验签需求
params = request.POST.dict() if request.POST else {}
if not params:
logger.warning('[ALIPAY_CZJILU_NOTIFY] 收到空数据')
return HttpResponse('fail', content_type='text/plain')
out_trade_no = params.get('out_trade_no', '')
trade_no = params.get('trade_no', '')
trade_status = params.get('trade_status', '')
total_amount = params.get('total_amount', '')
logger.info(
'[ALIPAY_CZJILU_NOTIFY] out_trade_no=%s, trade_no=%s, trade_status=%s, total_amount=%s',
out_trade_no, trade_no, trade_status, total_amount,
)
# 验签
from jituan.services.alipay_pay import verify_notify_params, club_id_from_czjilu
notify_club_id = club_id_from_czjilu(out_trade_no)
if not verify_notify_params(params, notify_club_id):
logger.warning('[ALIPAY_CZJILU_NOTIFY] 验签失败: out_trade_no=%s', out_trade_no)
return HttpResponse('fail', content_type='text/plain')
# 仅处理交易成功状态
if trade_status not in ('TRADE_SUCCESS', 'TRADE_FINISHED'):
logger.info('[ALIPAY_CZJILU_NOTIFY] 非成功状态 %s: %s', trade_status, out_trade_no)
return HttpResponse('success', content_type='text/plain')
# 查询充值单
order = Czjilu.query.filter(dingdan_id=out_trade_no).first()
if not order:
logger.error('[ALIPAY_CZJILU_NOTIFY] 充值单不存在: %s', out_trade_no)
return HttpResponse('fail', content_type='text/plain')
# 已支付:补记收支后直接返回成功(幂等)
if order.zhuangtai == 3:
logger.info('[ALIPAY_CZJILU_NOTIFY] 订单已支付,幂等返回: %s', out_trade_no)
return HttpResponse('success', content_type='text/plain')
if order.zhuangtai != 9:
logger.warning(
'[ALIPAY_CZJILU_NOTIFY] 订单状态异常: %s, zhuangtai=%s',
out_trade_no, order.zhuangtai,
)
return HttpResponse('success', content_type='text/plain')
# 按 leixing 路由到对应履约函数
paid_amount = total_amount or order.jine
leixing = order.leixing
try:
if leixing == CZJILU_LEIXING_HUIYUAN:
from jituan.services.member_recharge import fulfill_member_recharge
fulfill_member_recharge(out_trade_no, paid_amount_yuan=paid_amount, source='callback')
elif leixing == CZJILU_LEIXING_YAJIN:
from jituan.services.czjilu_fulfill import fulfill_yajin_recharge
fulfill_yajin_recharge(out_trade_no, paid_amount_yuan=paid_amount)
elif leixing == CZJILU_LEIXING_JIFEN:
from jituan.services.czjilu_fulfill import fulfill_jifen_recharge
fulfill_jifen_recharge(out_trade_no, paid_amount_yuan=paid_amount)
elif leixing == CZJILU_LEIXING_SHANGJIA:
from jituan.services.czjilu_fulfill import fulfill_shangjia
fulfill_shangjia(out_trade_no, paid_amount_yuan=paid_amount)
elif leixing == CZJILU_LEIXING_KAOHE:
from jituan.services.czjilu_fulfill import fulfill_kaohe
fulfill_kaohe(out_trade_no, paid_amount_yuan=paid_amount)
elif leixing == CZJILU_LEIXING_FAKUAN:
from jituan.services.czjilu_fulfill import fulfill_fakuan
fulfill_fakuan(out_trade_no, paid_amount_yuan=paid_amount)
else:
logger.error('[ALIPAY_CZJILU_NOTIFY] 未知 leixing=%s: %s', leixing, out_trade_no)
return HttpResponse('fail', content_type='text/plain')
except Exception as fulfill_exc:
logger.error(
'[ALIPAY_CZJILU_NOTIFY] 履约异常 out_trade_no=%s leixing=%s: %s',
out_trade_no, leixing, fulfill_exc, exc_info=True,
)
# 履约异常返回 fail让支付宝重试
return HttpResponse('fail', content_type='text/plain')
logger.info('[ALIPAY_CZJILU_NOTIFY] 履约完成: %s, leixing=%s', out_trade_no, leixing)
return HttpResponse('success', content_type='text/plain')
except Exception as e:
logger.error('[ALIPAY_CZJILU_NOTIFY] 回调处理异常: %s', str(e))
logger.error(traceback.format_exc())
return HttpResponse('fail', content_type='text/plain')