# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging from typing import TYPE_CHECKING, Dict from apps.web.common.transaction.refund import RefundNotifier, RefundPuller if TYPE_CHECKING: from django.core.handlers.wsgi import WSGIRequest from apps.web.core.payment.type_checking import PaymentGatewayT from apps.web.common.transaction.pay import RefundRecordT logger = logging.getLogger(__name__) class AliRefundNotifier(RefundNotifier): def parse_request(self, request): # type:(WSGIRequest) -> Dict return request.POST.dict() # type: Dict @property def refund_order_filter(self): # type:() -> dict return {'orderNo': self.payload['out_biz_no']} def handle_refund_order(self, refundOrder, refund_post_callable): # type:(RefundRecordT, callable) -> None """ 只有成功的退款 才会走异步的回调 """ matched = refundOrder.succeed( finishedTime = datetime.datetime.strptime(self.payload["gmt_refund"][: 19], "%Y-%m-%d %H:%M:%S")) if not matched: return return refund_post_callable(refundOrder, True) @property def errorResponse(self): # type:() -> str return "error" @property def successResponse(self): # type:() -> str return "success" def verify_payload(self, payload): # type:(dict) -> bool return True class AliRefundPuller(RefundPuller): def pull(self, refund_post_callable, **kwargs): # type:(callable, dict) -> bool rechargeOrder = self._refundOrder.pay_sub_order payGateway = self._refundOrder.my_payment_gateway # type: PaymentGatewayT result = payGateway.api_refund_query( out_refund_no = self._refundOrder.orderNo, out_trade_no = rechargeOrder.orderNo) if result["code"] != "10000": # 接口错误是无法判断成功还是失败的, 这个情况下不能继续往下处理 logger.info( "RefundPuller {} pull refund order {}, result code = {}, msg = {}".format( self.__class__.__name__, self._refundOrder, result["code"], result["msg"])) return True if "refund_status" not in result or result['refund_status'] != 'REFUND_SUCCESS': # 未返回该字段表示退款请求未收到或者退款失败, 可以重试 self._refundOrder.fail(errorCode = 'FAIL', errorDesc = 'FAIL') return False else: # 对于支付宝来说,查询的时候通知的时间并没有显示出来,就用查询的时间代替 matched = self._refundOrder.succeed( finishedTime = datetime.datetime.strptime(result["gmt_refund_pay"], "%Y-%m-%d %H:%M:%S")) if matched: refund_post_callable(self._refundOrder, True) return True