|
@@ -0,0 +1,181 @@
|
|
|
+# -*- encoding: utf-8 -*-
|
|
|
+"""
|
|
|
+@File : UnicomComboPayNotifyController.py
|
|
|
+@Time : 2022/6/29 14:31
|
|
|
+@Author : stephen
|
|
|
+@Email : zhangdongming@asj6.wecom.work
|
|
|
+@Software: PyCharm
|
|
|
+"""
|
|
|
+import logging
|
|
|
+import time
|
|
|
+from urllib.parse import parse_qs, unquote
|
|
|
+
|
|
|
+from django.db import transaction
|
|
|
+from django.http import HttpResponse
|
|
|
+from django.views import View
|
|
|
+
|
|
|
+from Model.models import Order_Model, UnicomDeviceInfo, UnicomComboOrderInfo
|
|
|
+from Object.AliPayObject import AliPayObject
|
|
|
+from Object.RedisObject import RedisObject
|
|
|
+from Object.WechatPayObject import WechatPayObject
|
|
|
+from Service.CommonService import CommonService
|
|
|
+
|
|
|
+
|
|
|
+class UnicomComboPayNotifyView(View):
|
|
|
+
|
|
|
+ def get(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.GET, request, operation)
|
|
|
+
|
|
|
+ def post(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.POST, request, operation)
|
|
|
+
|
|
|
+ def validation(self, request_dict, request, operation):
|
|
|
+ if operation == 'ali-notify':
|
|
|
+ return self.alipay_notify(request_dict)
|
|
|
+ elif operation == 'wechat-notify':
|
|
|
+ return self.wechat_notify(request)
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def alipay_notify(cls, request_dict):
|
|
|
+ """
|
|
|
+ 支付宝网页支付异步回调通知
|
|
|
+ 参考文档 https://opendocs.alipay.com/open/203/105286
|
|
|
+ @param request_dict: 请求参数
|
|
|
+ @return: success or fail
|
|
|
+ """
|
|
|
+ logger = logging.getLogger('info')
|
|
|
+ logger.info('联通套餐支付---支付宝支付回调')
|
|
|
+ order_id = ''
|
|
|
+ redisObj = RedisObject()
|
|
|
+ notify_key = 'ansjer:unicom:alipay:{}:str'
|
|
|
+ try:
|
|
|
+ re_data = request_dict.dict()
|
|
|
+ passback_params = re_data['passback_params']
|
|
|
+ params = dict([(k, v[0]) for k, v in parse_qs(unquote(passback_params)).items()])
|
|
|
+ lang = params['lang']
|
|
|
+ logger.info('支付宝异步回调参数:{},携带参数{}', re_data, lang)
|
|
|
+ signature = re_data['sign']
|
|
|
+ re_data.pop('sign')
|
|
|
+ order_id = re_data['out_trade_no']
|
|
|
+
|
|
|
+ # redis加锁,防止订单重复 命令在指定的 key 不存在时,为 key 设置指定的值。存在则返回0
|
|
|
+ isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
|
|
|
+ # 过期时间60秒
|
|
|
+ redisObj.CONN.expire(notify_key.format(order_id), 60)
|
|
|
+ if not isLock:
|
|
|
+ return HttpResponse('fail')
|
|
|
+
|
|
|
+ order_qs = Order_Model.objects.filter(orderID=order_id)
|
|
|
+ if not order_qs.exists():
|
|
|
+ logger.info('系统订单不存在:{}'.format(order_id))
|
|
|
+ return HttpResponse('fail')
|
|
|
+ order_qs = order_qs.filter(status=0)
|
|
|
+ if not order_qs.exists():
|
|
|
+ logger.info('订单已支付或退款{}'.format(order_id))
|
|
|
+ return HttpResponse('success')
|
|
|
+ aliPayObj = AliPayObject()
|
|
|
+ alipay = aliPayObj.conf()
|
|
|
+ # 异步回调验签
|
|
|
+ success = alipay.verify(re_data, signature)
|
|
|
+ if not success or re_data["trade_status"] not in ("TRADE_SUCCESS", "TRADE_FINISHED"):
|
|
|
+ return HttpResponse('fail')
|
|
|
+ return cls.order_pay_notify(order_id, re_data["trade_no"], notify_key.format(order_id), order_qs, redisObj)
|
|
|
+ except Exception as e:
|
|
|
+ logger.info('联通套餐订单支付宝支付回调异常:{}'.format(repr(e)))
|
|
|
+ redisObj.del_data(key=notify_key.format(order_id))
|
|
|
+ return HttpResponse('fail')
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def wechat_notify(cls, request):
|
|
|
+ logger = logging.getLogger('info')
|
|
|
+ logger.info('联通套餐支付---微信支付回调')
|
|
|
+ order_id = ''
|
|
|
+ redisObj = RedisObject()
|
|
|
+ notify_key = 'ansjer:unicom:wxpay:{}:str'
|
|
|
+ pay = WechatPayObject()
|
|
|
+ try:
|
|
|
+ re_data = pay.weixinpay_call_back(request.body)
|
|
|
+ attach = re_data["attach"]
|
|
|
+ parmap = dict([(k, v[0]) for k, v in parse_qs(unquote(attach)).items()])
|
|
|
+ lang = parmap['lang']
|
|
|
+ logger.info('微信异步回调参数:{},携带参数{}', re_data, lang)
|
|
|
+ trade_status = re_data['result_code'] # 业务结果 SUCCESS/FAIL
|
|
|
+ order_id = re_data['out_trade_no'] # 商户订单号
|
|
|
+ order_qs = Order_Model.objects.filter(orderID=order_id)
|
|
|
+ if not order_qs.exists():
|
|
|
+ return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
|
|
|
+ order_qs = order_qs.filter(status=0)
|
|
|
+ if not order_qs.exists():
|
|
|
+ logger.info('订单已支付或退款{}'.format(order_id))
|
|
|
+ return cls.wx_return_code()
|
|
|
+
|
|
|
+ if trade_status != 'SUCCESS':
|
|
|
+ logger.info('微信支付回调Fail')
|
|
|
+ order_qs.update(status=10)
|
|
|
+ return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
|
|
|
+ check_sign = pay.get_notifypay(re_data)
|
|
|
+ if not check_sign:
|
|
|
+ logger.info('微信支付回调签名失败')
|
|
|
+ return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '签名失败'}))
|
|
|
+
|
|
|
+ # redis加锁,防止订单重复
|
|
|
+ redisObj = RedisObject()
|
|
|
+ isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
|
|
|
+ redisObj.CONN.expire(notify_key.format(order_id), 60)
|
|
|
+ if not isLock:
|
|
|
+ return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
|
|
|
+
|
|
|
+ return cls.order_pay_notify(order_id, re_data["transaction_id"], notify_key.format(order_id), order_qs,
|
|
|
+ redisObj, True)
|
|
|
+ except Exception as e:
|
|
|
+ redisObj.del_data(key=notify_key.format(order_id))
|
|
|
+ return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': repr(e)}))
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def wx_return_code():
|
|
|
+ return HttpResponse("<xml>\
|
|
|
+ <return_code><![CDATA[SUCCESS]]></return_code>\
|
|
|
+ <return_msg><![CDATA[OK]]></return_msg>\
|
|
|
+ </xml>")
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def order_pay_notify(cls, order_id, trade_no, request_key, order_qs, redisObj, is_wechat_pay=False):
|
|
|
+ """
|
|
|
+ 订单支付通知
|
|
|
+ @param trade_no: 第三方交易流水号
|
|
|
+ @param order_id:订单编号
|
|
|
+ @param request_key:访问缓存key
|
|
|
+ @param order_qs:订单对象
|
|
|
+ @param redisObj:缓存对象
|
|
|
+ @param is_wechat_pay:是否微信支付
|
|
|
+ @return: success or fail
|
|
|
+ """
|
|
|
+ logger = logging.getLogger('info')
|
|
|
+ now_time = int(time.time())
|
|
|
+ with transaction.atomic():
|
|
|
+ # 支付宝交易凭证号。
|
|
|
+ order_qs = order_qs.values('UID', 'unify_combo_id', 'userID_id', 'order_type')
|
|
|
+ device_uid = order_qs[0]['UID']
|
|
|
+ combo_id = order_qs[0]['unify_combo_id']
|
|
|
+ serial_no = CommonService.query_serial_with_uid(device_uid)
|
|
|
+ unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values('iccid')
|
|
|
+ if unicom_device_info_qs.exists():
|
|
|
+ iccid = unicom_device_info_qs[0]['iccid']
|
|
|
+ combo_order_data = {'iccid': iccid, 'status': 0, 'order_id': order_id, 'combo_id': int(combo_id),
|
|
|
+ 'user_id': order_qs[0]['userID_id'], 'updated_time': now_time,
|
|
|
+ 'created_time': now_time}
|
|
|
+ UnicomComboOrderInfo.objects.create(**combo_order_data)
|
|
|
+ order_qs.update(trade_no=trade_no, status=1, payTime=now_time, updTime=now_time)
|
|
|
+ logger.info('购买联通套餐成功,序列号为:{}'.format(serial_no))
|
|
|
+ redisObj.del_data(key=request_key)
|
|
|
+ if is_wechat_pay:
|
|
|
+ return HttpResponse("<xml>\
|
|
|
+ <return_code><![CDATA[SUCCESS]]></return_code>\
|
|
|
+ <return_msg><![CDATA[OK]]></return_msg>\
|
|
|
+ </xml>")
|
|
|
+ else:
|
|
|
+ return HttpResponse('success')
|