# coding=utf-8 import json import xmltodict from django.db import transaction from django.http import HttpResponse from apps.customer import customer_log from rest_framework.views import APIView from utils.wx.WXBizMsgCrypt import WXBizMsgCrypt from utils.exceptions import CustomError from utils import response_ok, response_error from utils.wechatpay import WechatPayNotify from apps.log.models import BizLog from apps.WechatTp.models import WechatTp from apps.WechatApplet.models import WechatApplet from apps.tenant.models import Tenant from apps.pay.models import Pay from apps.tenant.biz import TenantBiz from utils.xgj.xgj import XGJ from utils.permission import IsCustomerUser class CallbackAuthorize(APIView): '''验证票据(component_verify_ticket)在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL” 每隔 10 分钟以 POST 的方式推送 component_verify_ticket 接收 POST 请求后,只需直接返回字符串 success。 为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密''' def post(self, request): sMsgSignature = request.GET.get('msg_signature') sTimeStamp = request.GET.get('timestamp') sNonce = request.GET.get('nonce') sPostData = request.body.decode('utf-8') try: component = WechatTp.getDefault() if component: appid = component.getAppid() msg_crypt = WXBizMsgCrypt(component.getToken(), component.getEncodeKey(), appid) ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce) data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml'] if data['AppId'] == appid: if data['InfoType'] == 'component_verify_ticket': component.refreshVerifyTicket(data['ComponentVerifyTicket']) elif data['InfoType'] == 'unauthorized': authorizer_appid = data['AuthorizerAppid'] authorizer = WechatApplet.getByAppidAndComponentAppid(authorizer_appid, appid) if authorizer: authorizer.revoke() except: pass return HttpResponse('success') class RedirectAuthorize(APIView): '''小程序绑定授权回调''' def get(self, request, pk): try: with transaction.atomic(): tenant = Tenant.objects.select_for_update().filter(id=pk).first() app = TenantBiz.bindWechatApplet(tenant, request.GET.get('auth_code')) BizLog.objects.addnew(None, None, BizLog.INSERT, u'租户绑定小程序, id=%d' % app.id) except Exception as e: return response_error(str(e)) return response_ok() class CallbackEvent(APIView): '''消息与事件接收''' def post(self, request, appid): appid = appid sMsgSignature = request.GET.get('msg_signature') sTimeStamp = request.GET.get('timestamp') sNonce = request.GET.get('nonce') sPostData = request.body.decode('utf-8') try: tp = WechatTp.getDefault() msg_crypt = WXBizMsgCrypt(tp.getToken(), tp.getEncodeKey(), tp.getAppid()) ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce) data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml'] if data['MsgType'] == 'event': app = WechatApplet.getByAppid(appid) if data['Event'] == 'weapp_audit_success': # 代码审核通过 app.weapp_audit_success() elif data['Event'] == 'weapp_audit_fail': # 代码审核不通过 app.weapp_audit_fail(data['Reason']) elif data['Event'] == 'weapp_audit_delay': # 代码审核延后 app.weapp_audit_delay(data['Reason']) except: pass return HttpResponse('success') class WechatNotifyView(APIView): def dispatch(self, request, *args, **kwargs): appid = kwargs['appid'] applet = WechatApplet.getByAppid(appid) param = request.body.decode('utf-8') notify = WechatPayNotify(param, applet.tenant_key) try: data = notify.handle() if not data: raise CustomError(u'错误的请求!') result_code = data['result_code'] if result_code != 'SUCCESS': raise CustomError(u'错误的请求!') no = data['out_trade_no'] amount = int(data['total_fee']) * 100 with transaction.atomic(): pay = Pay.getByNo(no) pay.payConfirm(amount) customer_log(pay.customer, BizLog.INSERT, u'支付成功,no=%s' % no, param) except: return HttpResponse(WechatPayNotify.response_fail()) return HttpResponse(WechatPayNotify.response_ok()) class GetCompany(APIView): permission_classes = [IsCustomerUser, ] def get(self, request): appid = request.GET.get('appid') try: res = XGJ.get_company(appid) except Exception as e: return response_error(str(e)) return response_ok(res) class GetMemberCard(APIView): permission_classes = [IsCustomerUser, ] def post(self, request): appid = request.POST.get('appid') company_id = request.POST.get('company_id') tel = request.POST.get('tel') number = request.POST.get('number') try: res = XGJ.get_member_card(appid, company_id, tel, number) except Exception as e: return response_error(str(e)) return response_ok(res) class GetMemberInfo(APIView): permission_classes = [IsCustomerUser, ] def get(self, request): appid = request.GET.get('appid') customer = request.customer if not customer.member_id: raise CustomError(u'请先绑定会员卡') try: res = XGJ.get_member_info(appid, str(customer.member_id)) except Exception as e: return response_error(str(e)) return response_ok(res) class GetMemberPoints(APIView): permission_classes = [IsCustomerUser, ] def get(self, request): appid = request.GET.get('appid') page = request.GET.get('page') pageSize = request.GET.get('pageSize') customer = request.customer if not customer.member_id: raise CustomError(u'请先绑定会员卡') try: res = XGJ.get_member_points(appid, str(customer.member_id), page, pageSize) except Exception as e: return response_error(str(e)) return response_ok(res) class GetMemberRecord(APIView): permission_classes = [IsCustomerUser, ] def get(self, request): appid = request.GET.get('appid') page = request.GET.get('page') pageSize = request.GET.get('pageSize') customer = request.customer if not customer.member_id: raise CustomError(u'请先绑定会员卡') try: res = XGJ.get_member_record(appid, str(customer.member_id), page, pageSize) except Exception as e: return response_error(str(e)) return response_ok(res) class GetMemberBalance(APIView): permission_classes = [IsCustomerUser, ] def get(self, request): appid = request.GET.get('appid') customer = request.customer if not customer.member_id: raise CustomError(u'未绑定会员卡') try: res = XGJ.get_member_balance(appid, str(customer.member_id)) except Exception as e: return response_error(str(e)) return response_ok(res)