views.py 6.7 KB

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