views.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # coding=utf-8
  2. import json
  3. import xmltodict
  4. from django.db import transaction
  5. from django.http import HttpResponse
  6. from apps.customer import customer_log
  7. from rest_framework.views import APIView
  8. from utils.wx.WXBizMsgCrypt import WXBizMsgCrypt
  9. from utils.exceptions import CustomError
  10. from utils import response_ok, response_error
  11. from utils.wechatpay import WechatPayNotify
  12. from apps.log.models import BizLog
  13. from apps.WechatTp.models import WechatTp
  14. from apps.WechatApplet.models import WechatApplet
  15. from apps.tenant.models import Tenant
  16. from apps.pay.models import Pay
  17. from apps.tenant.biz import TenantBiz
  18. from utils.xgj.xgj import XGJ
  19. from utils.permission import IsCustomerUser
  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 WechatNotifyView(APIView):
  83. def dispatch(self, request, *args, **kwargs):
  84. appid = kwargs['appid']
  85. applet = WechatApplet.getByAppid(appid)
  86. param = request.body.decode('utf-8')
  87. notify = WechatPayNotify(param, applet.tenant_key)
  88. try:
  89. data = notify.handle()
  90. if not data:
  91. raise CustomError(u'错误的请求!')
  92. result_code = data['result_code']
  93. if result_code != 'SUCCESS':
  94. raise CustomError(u'错误的请求!')
  95. no = data['out_trade_no']
  96. amount = int(data['total_fee']) * 100
  97. with transaction.atomic():
  98. pay = Pay.getByNo(no)
  99. pay.payConfirm(amount)
  100. customer_log(pay.customer, BizLog.INSERT, u'支付成功,no=%s' % no, param)
  101. except:
  102. return HttpResponse(WechatPayNotify.response_fail())
  103. return HttpResponse(WechatPayNotify.response_ok())
  104. class GetCompany(APIView):
  105. permission_classes = [IsCustomerUser, ]
  106. def get(self, request):
  107. appid = request.GET.get('appid')
  108. try:
  109. res = XGJ.get_company(appid)
  110. except Exception as e:
  111. return response_error(str(e))
  112. return response_ok(res)
  113. class GetMemberCard(APIView):
  114. permission_classes = [IsCustomerUser, ]
  115. def post(self, request):
  116. appid = request.POST.get('appid')
  117. company_id = request.POST.get('company_id')
  118. tel = request.POST.get('tel')
  119. number = request.POST.get('number')
  120. try:
  121. res = XGJ.get_member_card(appid, company_id, tel, number)
  122. except Exception as e:
  123. return response_error(str(e))
  124. return response_ok(res)
  125. class GetMemberInfo(APIView):
  126. permission_classes = [IsCustomerUser, ]
  127. def get(self, request):
  128. appid = request.GET.get('appid')
  129. customer = request.customer
  130. if not customer.member_id:
  131. raise CustomError(u'请先绑定会员卡')
  132. try:
  133. res = XGJ.get_member_info(appid, str(customer.member_id))
  134. except Exception as e:
  135. return response_error(str(e))
  136. return response_ok(res)
  137. class GetMemberPoints(APIView):
  138. permission_classes = [IsCustomerUser, ]
  139. def get(self, request):
  140. appid = request.GET.get('appid')
  141. page = request.GET.get('page')
  142. pageSize = request.GET.get('pageSize')
  143. customer = request.customer
  144. if not customer.member_id:
  145. raise CustomError(u'请先绑定会员卡')
  146. try:
  147. res = XGJ.get_member_points(appid, str(customer.member_id), page, pageSize)
  148. except Exception as e:
  149. return response_error(str(e))
  150. return response_ok(res)
  151. class GetMemberRecord(APIView):
  152. permission_classes = [IsCustomerUser, ]
  153. def get(self, request):
  154. appid = request.GET.get('appid')
  155. page = request.GET.get('page')
  156. pageSize = request.GET.get('pageSize')
  157. customer = request.customer
  158. if not customer.member_id:
  159. raise CustomError(u'请先绑定会员卡')
  160. try:
  161. res = XGJ.get_member_record(appid, str(customer.member_id), page, pageSize)
  162. except Exception as e:
  163. return response_error(str(e))
  164. return response_ok(res)
  165. class GetMemberBalance(APIView):
  166. permission_classes = [IsCustomerUser, ]
  167. def get(self, request):
  168. appid = request.GET.get('appid')
  169. customer = request.customer
  170. if not customer.member_id:
  171. raise CustomError(u'未绑定会员卡')
  172. try:
  173. res = XGJ.get_member_balance(appid, str(customer.member_id))
  174. except Exception as e:
  175. return response_error(str(e))
  176. return response_ok(res)