Django 接入微信支付之小程序&JSAPI支付

1、统一下单接口
# 生成随机字符串的方法
def get_nonce_str():
    base_str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    random_str = ''.join(random.sample(base_str, 32))
    return random_str
# 微信统一支付接口
import hashlib
import hmac
class WeChatPay(object):
    def __init__(self, order_id, body, total_fee, nonce_str, openid, spbill_create_ip='8.8.8.8'):
        """
        :param order_id: 订单编号 32字符内
        :param body: 订单信息
        :param total_fee: 订单金额 #单位为分
        :param nonce_str: 32位内随机字符串
        :param spbill_create_ip: 客户端请求IP地址
        :param openid: 客户openid
        appid = '微信appid'
        AppSecret = '微信AppSecret'
        mch_id = '微信商户id'
        api_key = '微信支付密钥'
        spbill_create_ip = '8.8.8.8' # 用户请求地址 终端IP 调用微信支付API的机器IP
        """
        self.api_key = 'your api_key'
        self.params = {
            'appid': 'uour appid',
            'mch_id': 'your mch_id',
            'nonce_str': nonce_str,
            'openid': openid,
            'body': str(body),
            'out_trade_no': str(order_id),
            'total_fee': str(int(total_fee)),
            'spbill_create_ip': spbill_create_ip,
            'trade_type': 'JSAPI',
            'notify_url': 'https://test.paycheck.com',#你的支付回调地址
        }

        self.WxPay_request_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'  # 微信请求url
        self.error = None

    def key_value_url(self, value):
        """
        将将键值对转为 key1=value1&key2=value2
        """
        string_sign = ''
        for k in sorted(value.keys()):
            string_sign += "{0}={1}&".format(k, value[k])
        print('键值对:',string_sign)
        return string_sign

    def get_sign(self, params):
        """
        生成sign 签名
        """
        stringA = self.key_value_url(params)
        stringSignTemp = stringA + 'key=' + self.api_key  # APIKEY, API密钥,需要在商户后台设置
        print('最终键值对:',stringSignTemp)
        # sign = hashlib.md5(stringSignTemp.encode('utf-8')).hexdigest().upper()
        sign = hashlib.md5(stringSignTemp.encode('utf-8')).hexdigest().upper()
        # k = hashlib.sha256()
        # k.update(sign.encode())
        # j = hmac.new(sign.encode(), digestmod=hashlib.sha256)
        # print(j.hexdigest().upper())
        # print(k.hexdigest().upper())
        # sign = j.hexdigest().upper()
        print('生成签名sign:',sign)
        params['sign'] = sign

    def get_req_xml(self):
        """拼接XML
        """
        self.get_sign(self.params)
        xml = "<xml>"
        for k in sorted(self.params.keys()):
            xml += '<{0}>{1}</{0}>'.format(k, self.params[k])
        xml += "</xml>"
        print('得到XML:',xml)
        return xml.encode('utf-8')

    def get_prepay_id(self):
        """
        请求获取prepay_id
        """
        import requests
        from xml.etree import ElementTree as et
        xml = self.get_req_xml()
        # unifiedorderXML = requests.post('https://api.mch.weixin.qq.com/pay/unifiedorder', data=xml)
        unifiedorderXML = requests.post(self.WxPay_request_url, data=xml)
        unifiedorderXML.encoding ='utf-8'
        unifiedorderXML = unifiedorderXML.text
        print('统一下单接口的返回数据:',unifiedorderXML)
        # tree = et.parse(unifiedorderXML)
        # root = tree.getroot()
        root = et.fromstring(unifiedorderXML)
        if root.find("result_code").text != 'SUCCESS':
            self.error = u"连接微信出错啦!"
            print(self.error)
        prepay_id = root.find("prepay_id").text
        self.params['prepay_id'] = prepay_id
        # self.params['package'] = 'Sign=WXPay' # APP支付场景
        self.params['package'] = 'prepay_id=%s'%prepay_id   # JSAPI支付场景
        self.params['timestamp'] = str(int(time.time()))
        self.params['signType'] = 'MD5'

    def re_finall(self):
        """得到prepay_id后再次签名,返回给终端参数
        """
        self.get_prepay_id()
        if self.error:
            print('有错误发生')
            return 

        sign_again_params = {
            'appId': self.params['appid'],
            'timeStamp': self.params['timestamp'],
            'nonceStr': self.params['nonce_str'],
            'package': self.params['package'],
            'signType': self.params['signType']
        }
        self.get_sign(sign_again_params)
        self.params['sign'] = sign_again_params['sign']

        # 移除其他不需要返回参数
        print('最后一步:', self.params)
        parms_keys = []
        for i in self.params.keys():
            parms_keys.append(i)
        for i in parms_keys:
            if i not in ['appid', 'mch_id', 'nonce_str', 'timestamp', 'sign', 'package', 'signType']:
                self.params.pop(i)
        print('传给前端的parms:', self.params)
        return self.params
2、支付回调接口
# 启用该回调方法
# CBV 模式的支付回调地址
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def wx_notify_url(request):
    '''
    微信支付回调接口
    无需登录便可访问
    无需参数
    '''
    try:
        print('请求方法:',request.method)
        return_xml = """<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"""
        webData = request.body
        print('回调返回信息:',webData)
        if bool(webData):
            xmlData = ET.fromstring(webData)
            if xmlData.find('return_code').text != 'SUCCESS':
                print('回调出现错误')
                return HttpResponse(return_xml,content_type='application/xml;charset=utf-8')
            else:
                if xmlData.find('result_code').text != 'SUCCESS':
                    print('支付失败!')
                    return HttpResponse(return_xml,content_type='application/xml;charset=utf-8')
                else:
                    order_num = xmlData.find('out_trade_no').text
                    print('支付成功返回的订单编号:',order_num)
                    return HttpResponse(return_xml,content_type='application/xml;charset=utf-8')
        return HttpResponse(return_xml,content_type='application/xml;charset=utf-8')
    except Exception as e:
        print(e)
        print({"message": "网络错误:%s"%str(e), "errorCode": 1, "data": {}})
        return_xml = """<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"""
        return HttpResponse(return_xml,content_type='application/xml;charset=utf-8')
    
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haeasringnar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值