123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import xmltodict
- from mongoengine import DoesNotExist
- from typing import TYPE_CHECKING, Optional
- from apps.web.common.transaction.refund import RefundNotifier, RefundPuller
- from apps.web.core.models import WechatPayApp
- from library.wechatbase.exceptions import WeChatPayException
- from library.wechatpy.pay import WeChatPay
- from apps.web.user.models import RefundMoneyRecord, RechargeRecord
- if TYPE_CHECKING:
- from django.core.handlers.wsgi import WSGIRequest
- from apps.web.core.payment import PaymentGatewayT
- from apps.web.common.transaction.pay import RechargeRecordT, RefundRecordT
- class WechatRefundNotifier(RefundNotifier):
- def parse_request(self, request): # type:(WSGIRequest) -> dict
- payload = xmltodict.parse(request.body)['xml'] # type: dict
- # xml 解析之后获取第一步的数据 找到wechat app
- app = WechatPayApp.objects.get(appid = payload["appid"], mchid = payload['mch_id']) # type: WechatPayApp
- req_info = WeChatPay(appid = app.appid, api_key = app.apikey, mch_id = app.mchid).decrypt(payload["req_info"])
- # 所有信息打包成一个字典返回
- payload.update(req_info)
- return payload
- def verify_payload(self, payload): # type:(dict) -> bool
- """ 忽略对签名串的校验 """
- return True
- def handle_refund_order(self, refundOrder, post_pay): # type:(RefundRecordT, callable) -> None
- if not self.payload:
- refundOrder.fail(errorDesc = u'通知参数错误')
- return
- if self.payload["return_code"] != "SUCCESS":
- refundOrder.fail(errorDesc = self.payload["return_msg"])
- return
- if self.payload["refund_status"] == "SUCCESS":
- payFinishTime = self.payload["success_time"]
- datetimeRefund = datetime.datetime.strptime(payFinishTime, "%Y-%m-%d %H:%M:%S")
- matched = refundOrder.succeed(tradeRefundNo = self.payload["refund_id"], finishedTime = datetimeRefund)
- if not matched:
- return
- return post_pay(refundOrder, datetimeRefund)
- if self.payload["refund_status"] == "REFUNDCLOSE":
- refundOrder.closed(tradeRefundNo=self.payload["refund_id"], errorDesc = self.payload["return_msg"])
- return
- refundOrder.fail(errorDesc = self.payload["return_msg"])
- @property
- def refund_order_no(self): # type:() -> str
- return self.payload['out_refund_no']
- @property
- def errorResponse(self): # type:() -> str
- from apps.web.core.payment.wechat import WechatPaymentGateway
- return WechatPaymentGateway.reply("", False)
- @property
- def successResponse(self): # type:() -> str
- from apps.web.core.payment.wechat import WechatPaymentGateway
- return WechatPaymentGateway.reply("", True)
- class WechatRefundPuller(RefundPuller):
- def pull(self, payGateWay, payOrder, post_pay): # type:(PaymentGatewayT, RechargeRecordT, callable) -> None
- try:
- result = payGateWay.api_refund_query(out_refund_no = self._refundOrder.orderNo)
- except WeChatPayException:
- # 接口性质的失败 不做任何处理
- return
- # 找出退款单号
- offset = None
- for _k, _v in result.items():
- if _v == self._refundOrder.orderNo:
- offset = _k.rsplit("_", 1)[1]
- if not offset:
- return
- refundStatus = result["refund_status_{}".format(offset)]
- if refundStatus == "SUCCESS":
- refundTime = result["refund_success_time_{}".format(offset)]
- datetimeRefund = datetime.datetime.strptime(refundTime, "%Y-%m-%d %H:%M:%S")
- matched = self._refundOrder.succeed(result["refund_id_{}".format(offset)], finishedTime = datetimeRefund)
- if not matched:
- return
- post_pay(self._refundOrder, datetimeRefund)
- elif refundStatus == "REFUNDCLOSE":
- self._refundOrder.closed(
- result["refund_id_{}".format(offset)],
- result["err_code"], result["err_code_des"]
- )
- elif refundStatus == "PROCESSING":
- if not (self._refundOrder.is_processing or self._refundOrder.is_closed or self._refundOrder.is_success):
- self._refundOrder.processing()
- elif refundStatus == "CHANGE":
- self._refundOrder.fail(result["err_code"], result["err_code_des"])
- else:
- pass
- return
|