views.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. # coding=utf-8
  2. import json
  3. import xmltodict
  4. import traceback
  5. from django.db import transaction
  6. from django.http import HttpResponse
  7. from rest_framework.views import APIView
  8. from django.conf import settings
  9. from utils.wx.WXBizMsgCrypt import WXBizMsgCrypt
  10. from utils.exceptions import CustomError
  11. from utils import response_ok, response_error
  12. from utils.wechatpay import WechatPayNotify
  13. from apps.log.models import BizLog
  14. from apps.WechatTp.models import WechatTp
  15. from apps.WechatApplet.models import WechatApplet
  16. from alipay.aop.api.util.SignatureUtils import verify_with_rsa
  17. from apps.WeChatResponse import WechatPayNotify
  18. class CallbackAuthorize(APIView):
  19. '''验证票据(component_verify_ticket)在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL”
  20. 每隔 10 分钟以 POST 的方式推送 component_verify_ticket 接收 POST 请求后,只需直接返回字符串 success。
  21. 为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密'''
  22. def post(self, request):
  23. sMsgSignature = request.GET.get('msg_signature')
  24. sTimeStamp = request.GET.get('timestamp')
  25. sNonce = request.GET.get('nonce')
  26. sPostData = request.body.decode('utf-8')
  27. try:
  28. component = WechatTp.getDefault()
  29. if component:
  30. appid = component.getAppid()
  31. msg_crypt = WXBizMsgCrypt(component.getToken(), component.getEncodeKey(), appid)
  32. ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce)
  33. data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml']
  34. if data['AppId'] == appid:
  35. if data['InfoType'] == 'component_verify_ticket':
  36. component.refreshVerifyTicket(data['ComponentVerifyTicket'])
  37. elif data['InfoType'] == 'unauthorized':
  38. authorizer_appid = data['AuthorizerAppid']
  39. authorizer = WechatApplet.getByAppidAndComponentAppid(authorizer_appid, appid)
  40. if authorizer:
  41. authorizer.revoke()
  42. except:
  43. pass
  44. return HttpResponse('success')
  45. class CallbackEvent(APIView):
  46. '''消息与事件接收'''
  47. def post(self, request, appid):
  48. appid = appid
  49. sMsgSignature = request.GET.get('msg_signature')
  50. sTimeStamp = request.GET.get('timestamp')
  51. sNonce = request.GET.get('nonce')
  52. sPostData = request.body.decode('utf-8')
  53. try:
  54. tp = WechatTp.getDefault()
  55. msg_crypt = WXBizMsgCrypt(tp.getToken(), tp.getEncodeKey(), tp.getAppid())
  56. ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce)
  57. data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml']
  58. if data['MsgType'] == 'event':
  59. app = WechatApplet.getByAppid(appid)
  60. if data['Event'] == 'weapp_audit_success': # 代码审核通过
  61. app.weapp_audit_success()
  62. elif data['Event'] == 'weapp_audit_fail': # 代码审核不通过
  63. app.weapp_audit_fail(data['Reason'])
  64. elif data['Event'] == 'weapp_audit_delay': # 代码审核延后
  65. app.weapp_audit_delay(data['Reason'])
  66. except:
  67. pass
  68. return HttpResponse('success')
  69. class AlipayNotifyView(APIView):
  70. def check_pay(self, params):
  71. sign = params.pop('sign', None)
  72. params.pop('sign_type')
  73. params = sorted(params.items(), key=lambda e: e[0], reverse=False)
  74. message = "&".join(u"{}={}".format(k, v) for k, v in params).encode()
  75. try:
  76. status = verify_with_rsa(settings.ALIPAY_SETTING['alipay_public_key'].encode('utf-8').decode('utf-8'), message,sign)
  77. return status
  78. except:
  79. return False
  80. def post(self, request):
  81. params = request.POST.dict()
  82. if not self.check_pay(params):
  83. return HttpResponse('')
  84. no = request.POST.get('out_trade_no')
  85. app_id = request.POST.get('app_id')
  86. notify_type = request.POST.get('notify_type')
  87. trade_status = request.POST.get('trade_status')
  88. amount = request.POST.get('total_amount')
  89. if notify_type != 'trade_status_sync':
  90. return HttpResponse('')
  91. if app_id != settings.ALIPAY_SETTING['app_id']:
  92. return HttpResponse('')
  93. try:
  94. with transaction.atomic():
  95. pay = Pay.getByNo(no)
  96. if trade_status == 'TRADE_CLOSED':
  97. pay.payClosed()
  98. BizLog.objects.addnew(None,pay.user, BizLog.INSERT, u'支付取消,pay_no=%s' % no,params)
  99. if trade_status == 'TRADE_SUCCESS' or trade_status == 'TRADE_FINISHED':
  100. pay.paySuccess(float(amount))
  101. BizLog.objects.addnew(None,pay.user, BizLog.INSERT, u'支付宝支付成功,pay_no=%s' % no,params)
  102. except:
  103. import traceback
  104. traceback.print_exc()
  105. return HttpResponse('')
  106. return HttpResponse('success')
  107. class WechatNotifyView(APIView):
  108. def dispatch(self, request, *args, **kwargs):
  109. param = request.body
  110. notify = WechatPayNotify(param)
  111. try:
  112. data = notify.handle()
  113. if not data:
  114. raise CustomError(u'错误的请求!')
  115. result_code = data['result_code']
  116. if result_code != 'SUCCESS':
  117. raise CustomError(u'错误的请求!')
  118. no = data['out_trade_no']
  119. amount = float(data['total_fee']) / 100.0
  120. with transaction.atomic():
  121. pay = Pay.getByNo(no)
  122. pay.paySuccess(amount)
  123. BizLog.objects.addnew(None, pay.user, BizLog.INSERT, u'微信支付成功,pay_no=%s' % no, param)
  124. except Exception as e:
  125. traceback.print_exc()
  126. return HttpResponse(WechatPayNotify.response_fail())
  127. return HttpResponse(WechatPayNotify.response_ok())