# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging import simplejson as json from django.conf import settings 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 import PaymentGatewayT from apps.web.common.transaction.pay import RefundRecordT, RechargeRecordT logger = logging.getLogger(__name__) class JDOpenRefundNotifier(RefundNotifier): def parse_request(self, request): # type:(WSGIRequest) -> dict _head = { 'accessKey': request.META['HTTP_ACCESSKEY'], 'version': request.META['HTTP_VERSION'], 'timestamp': request.META['HTTP_TIMESTAMP'], 'token': request.META['HTTP_TOKEN'] } _body = json.loads(request.body) # type: Dict logger.debug('received jdopen refund notify: body = {}; heads = {}'.format(_body, _head)) return { 'body': _body, 'head': _head } 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["body"]["refundStatus"] != "SUCCESS": refundOrder.fail( errorCode = self.payload["body"].get('failCode', ''), errorDesc = self.payload["body"].get('failReason', '')) return import arrow refund_finished_time = arrow.get( self.payload["body"]["refundDate"], 'YYYY-MM-DD HH:mm', tzinfo = settings.TIME_ZONE).naive # type: datetime.datetime matched = refundOrder.succeed( tradeRefundNo = str(self.payload["body"].get('bankRequestNum', '')), finishedTime = refund_finished_time) if not matched: return return post_pay(refundOrder, refund_finished_time) @property def refund_order_no(self): # type:() -> str return self.payload["body"]['refundRequestNum'] @property def errorResponse(self): # type:() -> str return "error" @property def successResponse(self): # type:() -> str return "ok" class JDOpenRefundPuller(RefundPuller): def pull(self, payGateWay, payOrder, post_pay): # type:(PaymentGatewayT, RechargeRecordT, callable) -> None try: result = payGateWay.api_refund_query(requestNum = payOrder.orderNo) refund_record_list = result['data']['refundRecordList'] for refund_record in refund_record_list: if refund_record['refundRequestNum'] != self._refundOrder.orderNo: logger.debug('order has another refund record'.format( payOrder.orderNo, self._refundOrder.orderNo)) continue else: if refund_record["status"] == "FAIL": self._refundOrder.fail(errorDesc = refund_record["failReason"]) elif refund_record["status"] == "SUCCESS": import arrow completeTime = arrow.get( refund_record['refundTime'], 'YYYY-MM-DD HH:mm:ss', tzinfo = settings.TIME_ZONE).naive matched = self._refundOrder.succeed( tradeRefundNo = refund_record['bankRequestNum'], finishedTime = completeTime) if not matched: return post_pay(self._refundOrder, completeTime) elif result["payStatus"] == "INIT": pass except Exception as e: logger.exception(e)