alipay.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. from typing import TYPE_CHECKING, Dict
  6. from apps.web.common.transaction.refund import RefundNotifier, RefundPuller
  7. if TYPE_CHECKING:
  8. from django.core.handlers.wsgi import WSGIRequest
  9. from apps.web.core.payment.type_checking import PaymentGatewayT
  10. from apps.web.common.transaction.pay import RefundRecordT
  11. logger = logging.getLogger(__name__)
  12. class AliRefundNotifier(RefundNotifier):
  13. def parse_request(self, request): # type:(WSGIRequest) -> Dict
  14. return request.POST.dict() # type: Dict
  15. @property
  16. def refund_order_filter(self): # type:() -> dict
  17. return {'orderNo': self.payload['out_biz_no']}
  18. def handle_refund_order(self, refundOrder, refund_post_callable): # type:(RefundRecordT, callable) -> None
  19. """
  20. 只有成功的退款 才会走异步的回调
  21. """
  22. matched = refundOrder.succeed(
  23. finishedTime = datetime.datetime.strptime(self.payload["gmt_refund"][: 19], "%Y-%m-%d %H:%M:%S"))
  24. if not matched:
  25. return
  26. return refund_post_callable(refundOrder, True)
  27. @property
  28. def errorResponse(self): # type:() -> str
  29. return "error"
  30. @property
  31. def successResponse(self): # type:() -> str
  32. return "success"
  33. def verify_payload(self, payload): # type:(dict) -> bool
  34. return True
  35. class AliRefundPuller(RefundPuller):
  36. def pull(self, refund_post_callable, **kwargs): # type:(callable, dict) -> bool
  37. rechargeOrder = self._refundOrder.pay_sub_order
  38. payGateway = self._refundOrder.my_payment_gateway # type: PaymentGatewayT
  39. result = payGateway.api_refund_query(
  40. out_refund_no = self._refundOrder.orderNo, out_trade_no = rechargeOrder.orderNo)
  41. if result["code"] != "10000":
  42. # 接口错误是无法判断成功还是失败的, 这个情况下不能继续往下处理
  43. logger.info(
  44. "RefundPuller {} pull refund order {}, result code = {}, msg = {}".format(
  45. self.__class__.__name__, self._refundOrder, result["code"], result["msg"]))
  46. return True
  47. if "refund_status" not in result or result['refund_status'] != 'REFUND_SUCCESS':
  48. # 未返回该字段表示退款请求未收到或者退款失败, 可以重试
  49. self._refundOrder.fail(errorCode = 'FAIL', errorDesc = 'FAIL')
  50. return False
  51. else:
  52. # 对于支付宝来说,查询的时候通知的时间并没有显示出来,就用查询的时间代替
  53. matched = self._refundOrder.succeed(
  54. finishedTime = datetime.datetime.strptime(result["gmt_refund_pay"], "%Y-%m-%d %H:%M:%S"))
  55. if matched:
  56. refund_post_callable(self._refundOrder, True)
  57. return True