# coding=utf-8 import json import xmltodict import traceback from django.db import transaction from django.http import HttpResponse from rest_framework.views import APIView from django.conf import settings from utils.wx.WXBizMsgCrypt import WXBizMsgCrypt from utils.exceptions import CustomError from apps.order.models import Pay from utils.wechatpay import WechatPayNotify from utils import response_error, response_ok from apps.log.models import BizLog from apps.WechatTp.models import WechatTp from apps.WechatApplet.models import WechatApplet from alipay.aop.api.util.SignatureUtils import verify_with_rsa # from apps.WeChatResponse import WechatPayNotify 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 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 AlipayNotifyView(APIView): def check_pay(self, params): sign = params.pop('sign', None) params.pop('sign_type') params = sorted(params.items(), key=lambda e: e[0], reverse=False) message = "&".join(u"{}={}".format(k, v) for k, v in params).encode() try: status = verify_with_rsa(settings.ALIPAY_SETTING['alipay_public_key'].encode('utf-8').decode('utf-8'), message,sign) return status except: return False def post(self, request): params = request.POST.dict() if not self.check_pay(params): return HttpResponse('') no = request.POST.get('out_trade_no') app_id = request.POST.get('app_id') notify_type = request.POST.get('notify_type') trade_status = request.POST.get('trade_status') amount = request.POST.get('total_amount') if notify_type != 'trade_status_sync': return HttpResponse('') if app_id != settings.ALIPAY_SETTING['app_id']: return HttpResponse('') try: with transaction.atomic(): pay = Pay.getByNo(no) if trade_status == 'TRADE_CLOSED': pay.payClosed() BizLog.objects.addnew(None,pay.user, BizLog.INSERT, u'支付取消,pay_no=%s' % no,params) if trade_status == 'TRADE_SUCCESS' or trade_status == 'TRADE_FINISHED': pay.paySuccess(float(amount)) BizLog.objects.addnew(None,pay.user, BizLog.INSERT, u'支付宝支付成功,pay_no=%s' % no,params) except: import traceback traceback.print_exc() return HttpResponse('') return HttpResponse('success') class WechatNotifyView(APIView): def dispatch(self, request, *args, **kwargs): param = request.body appid = kwargs['appid'] applet = WechatApplet.getByAppid(appid) # param = request.body.decode('utf-8') notify = WechatPayNotify(param, applet.agent_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 = float(data['total_fee']) / 100.0 with transaction.atomic(): pay = Pay.getByNo(no) pay.paySuccess(amount) BizLog.objects.addnew(pay.user, BizLog.INSERT, u'微信支付成功,pay_no=%s' % no, param) except Exception as e: traceback.print_exc() return HttpResponse(WechatPayNotify.response_fail()) return HttpResponse(WechatPayNotify.response_ok())