微信app支付python版

微信app支付python版

首先看一下微信支付的流程图,微信开放平台链接:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3
在这里插入图片描述
流程:
1.用户选择商品下单,会传数据给后台,请求生成支付订单
2.后台接受到数据后,做整理签名,然后访问微信服务端生成预付单号,返回给后台
3.后台接受到预付单号后,再把所有的数据(加上预付单号)整理以下,签名,然后给前端,这样就可以支付了
4.异步回调通知先不写

接下来写代码

# 微信支付随机生成字符串
def createNoncestr(length=32):
    """产生随机字符串,不长于32位"""
    chars = "abcdefghijklmnopqrstuvwxyz0123456789"
    strs = []
    for x in range(length):
        strs.append(chars[random.randrange(0, len(chars))])
    return "".join(strs)
    
#排序 , 更改格式
def get_sign_contents(all_params):
    sign_content = ""
    for (k, v) in sorted(all_params.items()):
        value = v
        if not isinstance(value, str):
            value = json.dumps(value, ensure_ascii=False)
        sign_content += ("&" + k + "=" + value)
    sign_content = sign_content[1:]
    return sign_content

# 微信md5加密
def MD5(str):
    md5 = hashlib.md5()
    md5.update(str.encode('utf-8'))
    return md5.hexdigest()


#微信支付代码   我只把必须填的数据加到了字典里,如果有需要再自行添加
    def weixinpay( recordid(单号), subject(商品标题), total_amount(金额)):
    	#第一次签名用
        model = {}
    	#第二次签名用
        prepay = {}
        weixinkey = '''你的微信密钥'''
        #微信服务端,访问它会返回预付单号
        url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
        # 应用id
        model['appid'] = '你的应用id'
        # 商户id
        model['mch_id'] = '你的商户id'
        # 生成的随机数32位
        model['nonce_str'] = createNoncestr()
        # 商品描述,前端传给你的商品标题
        model['body'] = subject
        # 签名类型
        model['sign_type'] = 'MD5'
        # 商户订单号
        model['out_trade_no'] = recordid
        # 总金额,微信金额单位为分,所以需要乘100
        model['total_fee'] = str(int(float(total_amount) * 100))
        # 终端ip
        model['spbill_create_ip'] = '123.12.12.123'
        # 通知地址,异步回调的地址
        model['notify_url'] = '你的服务器地址'
        # 交易类型
        model['trade_type'] = 'APP'
        #把model字典格式改成微信需要的格式
        models = get_sign_contents(model)
        #把你的微信密钥加上
        models = models + '&key=' + weixinkey
        #把排序号的数据做签名,md5加密
        sign = (MD5(models)).upper()
        #签名完后加到model字典里
        model['sign'] = sign
        #改成xml格式
        xml = "<xml>"
        for k, v in model.items():
            if type(v) == int:
                v = str(v)
            xml += '<' + k + '>' + v + '</' + k + '>'
        xml += "</xml>"
        #然后用post请求,去获取预付单号
        response = requests.post(url, xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
        #获取下来更改格式
        msg = response.text.encode('ISO-8859-1').decode('utf-8')
        #把xml格式改为字典格式,需要第三方库,自行下载
        xmlresp = xmltodict.parse(msg)
        #如果两次判断都正确,说明请求到了预付单号
        if xmlresp['xml']['return_code'] == 'SUCCESS':
            if xmlresp['xml']['result_code'] == 'SUCCESS':
                #然后把数据添加到prepay字典里
                prepay['prepayid'] = xmlresp['xml']['prepay_id']
                prepay['appid'] = xmlresp['xml']['appid']
                prepay['partnerid'] = xmlresp['xml']['mch_id']
                #生成随机字符串
                prepay['noncestr'] = createNoncestr()
                prepay['timestamp'] = str(int(time.time()))
                prepay['package'] = 'Sign=WXPay'
                #再一次排序
                prepays = get_sign_contents(prepay)
                modelss = prepays + '&key=' + weixinkey
                #再一次加密
                sign = MD5(modelss).upper()
                #把签名加到字典里
                prepay['sign'] = sign
                prepay['code'] = '00'
                prepay['msg'] = '获取成功'
                #返回数据
                return prepay
            else:
                prepay['code'] = '01'
                prepay['msg'] = '获取失败'
                return prepay
        else:
            prepay['code'] = '01'
            prepay['msg'] = '获取失败'
            return prepay
以上是我微信app支付总结,如果哪里有错误请指正,我也是刚学python的小白,欢迎一起学习交流qq:1281410804
### 使用 Python 实现微信 JSAPI 支付集成 #### 准备工作 为了成功实现微信JSAPI支付,需先完成一系列准备工作。这包括但不限于获取必要的证书文件、设置商户平台上的回调地址以及确保服务器能够接收来自微信的通知。 - 商户号 (mch_id) - API 密钥 (__key__) - 应用ID (appid) 这些信息将在后续的接口调用中被频繁使用[^1]。 #### 统一下单请求 在发起支付前,需要通过统一下单接口获得预支付交易会话标识(prepay_id),这是构建前端所需参数的基础之一。下面是一个简单的例子来展示如何发送这个请求: ```python import requests from urllib.parse import quote_plus class WxPay(object): __url_unified_order = "https://api.mch.weixin.qq.com/pay/unifiedorder" @classmethod def unified_order(cls, body, out_trade_no, total_fee, spbill_create_ip, notify_url, trade_type='JSAPI', openid=None): params = { 'appid': APP_ID, 'mch_id': MCH_ID, 'nonce_str': cls._generate_nonce(), 'body': body, 'out_trade_no': out_trade_no, 'total_fee': str(total_fee), 'spbill_create_ip': spbill_create_ip, 'notify_url': notify_url, 'trade_type': trade_type, 'openid': openid # 如果是JSAPI模式,则必填 } xml_data = '<xml>{}</xml>'.format(''.join(['<{0}>{1}</{0}>'.format(k, v) for k, v in params.items()])) headers = {'Content-Type': 'application/xml'} response = requests.post(url=cls.__url_unified_order, data=xml_data.encode(), headers=headers) result_xml = response.content.decode() return cls.xml_to_dict(result_xml) @staticmethod def _generate_nonce(length=32): """生成随机字符串""" chars = string.ascii_letters + string.digits return ''.join(random.choice(chars) for _ in range(length)) ``` 上述代码片段展示了如何向微信支付后台提交订单详情并返回处理后的XML响应转换成字典形式的结果[^3]。 #### 获取 jsapi 参数 一旦获得了 `prepay_id` ,就可以利用它以及其他必要字段去准备传递给客户端的小程序端所需的支付参数集。这里给出了一种方法用于组装这些数据项,并最终得到可用于唤起支付界面的数据结构: ```python def get_jsapi_params(self, prepay_id): timestamp = int(time.time()) nonce_str = self._generate_nonce() package = f'prepay_id={quote_plus(prepay_id)}' sign_type = 'MD5' pay_sign_dict = { 'appId': APP_ID, 'timeStamp': str(timestamp), 'nonceStr': nonce_str, 'package': package, 'signType': sign_type } pay_sign = self.get_sign_str(pay_sign_dict).upper() final_params = {**pay_sign_dict, **{'paySign': pay_sign}} del final_params['appId'] # appId 不参与签名 return final_params ``` 这段逻辑实现了从服务端计算出所有必需的信息以便于小程序侧可以顺利启动支付流程。 #### 签名算法 对于任何涉及敏感操作的过程来说,安全都是至关重要的考量因素;因此,在整个过程中多次提及到了签名机制的重要性。以下是创建 MD5 类型哈希值的方法示例: ```python @staticmethod def get_sign_str(sign_dict: dict): data = '' sort_keys = sorted(sign_dict.keys()) # 对键按字母顺序排序 for key in sort_keys[:-1]: value = sign_dict[key] if isinstance(value, bool): value = str(int(value)).lower() elif not isinstance(value, str): value = str(value) data += '{}={}{}'.format(key, value, '&') last_key = list(sign_dict)[-1] data += '{}={}'.format(last_key, sign_dict[last_key]) data += '&key={}'.format(WX_PAY_KEY) md5_hasher = hashlib.md5() md5_hasher.update(data.encode(encoding="utf8")) hexdigest = md5_hasher.hexdigest().upper() return hexdigest ``` 该函数负责按照特定规则拼接待加密串,并应用 MD5 加密方式得出最终的签名结果[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值