# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging import simplejson as json from typing import TYPE_CHECKING, Dict from apps.web.common.transaction.refund import RefundNotifier, RefundPuller from apps.web.core.models import JDAggrePayApp from library.jd import JDAggrePay from library.jd.exceptions import JDPayException if TYPE_CHECKING: from django.core.handlers.wsgi import WSGIRequest from apps.web.core.payment import PaymentGatewayT from apps.web.common.transaction.pay import RefundRecordT, RechargeRecordT logger = logging.getLogger(__name__) class JDAggreRefundNotifier(RefundNotifier): def __init__(self, request, record_cls_factory): self.orginal = json.loads(request.body) # type: Dict logger.debug('received jdaggre refund notify(encrypt): {}'.format(str(self.orginal))) super(JDAggreRefundNotifier, self).__init__(request=request, refund_order_getter=record_cls_factory) def parse_request(self, request): # type:(WSGIRequest) -> dict app = JDAggrePayApp.objects(merchant_no = self.orginal['merchantNo']).first() # type: JDAggrePayApp client = JDAggrePay(app.merchant_no, app.desKey, app.saltMd5Key, app.debug) # type: JDAggrePay return client.decrypt_response(self.orginal) def verify_payload(self, payload): # type:(dict) -> bool """ 京东聚合的退款返回参数中,没有明确要求对于参数做篡改校验 """ return True @property def refund_order_no(self): # type:() -> str return self.payload['outRefundNo'] def handle_refund_order(self, refundOrder, post_pay): # type:(RefundRecordT, callable) -> None if self.payload["resultCode"] != "SUCCESS": # 接口失败 refundOrder.fail(errorCode = self.payload["errCode"], errorDesc = self.payload["errCodeDes"]) return if self.payload["payStatus"] == "FINISH": # 业务状态成功 payFinishTime = self.payload["payFinishTime"] datetimeRefund = datetime.datetime.strptime(payFinishTime, "%Y%m%d%H%M%S") matched = refundOrder.succeed(tradeRefundNo = self.payload["tradeRefundNo"], finishedTime = datetimeRefund) if not matched: return return post_pay(refundOrder, datetimeRefund) if self.payload["payStatus"] == "CLOSE": # 退款单被关闭 refundOrder.closed( tradeRefundNo = self.payload["tradeRefundNo"], errorCode = self.payload["errCode"], errorDesc = self.payload["errCodeDes"]) return # 剩下的情况就是resultCode == SUCCESS 但是 payStatus != [FINISH, CLOSE] 在文档中没有描述 做个防止机制 refundOrder.fail(errorCode = self.payload["errCode"], errorDesc = self.payload["errCodeDes"]) @property def errorResponse(self): # type:() -> str return "error" @property def successResponse(self): # type:() -> str return "ok" class JDAggreRefundPuller(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 JDPayException: return if result["resultCode"] != "SUCCESS": self._refundOrder.fail(errorCode = result["errCode"], errorDesc = result["errCodeDes"]) elif result["payStatus"] == "FINISH": payFinishTime = result["payFinishTime"] datetimeRefund = datetime.datetime.strptime(payFinishTime, "%Y%m%d%H%M%S") matched = self._refundOrder.succeed(result["payRequestPiNo"], finishedTime = datetimeRefund) if not matched: return post_pay(self._refundOrder, datetimeRefund) elif result["payStatus"] == "CLOSE": self._refundOrder.closed(result["payRequestPiNo"], errorCode = result["errCode"], errorDesc = result["errCodeDes"]) elif result["payStatus"] == "PROCESSING": pass else: pass