123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- # 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 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,Pay
- from apps.tenant.biz import TenantBiz
- 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 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 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
- notify = WechatPayNotify(param)
- 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(None, 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())
|