当前位置:脚本大全 > > 正文

python统一支付接口(Python实现的微信支付方式总结三种方式)

时间:2021-10-18 11:19:15类别:脚本大全

python统一支付接口

Python实现的微信支付方式总结三种方式

本文实例讲述了python实现的微信支付方式。分享给大家供大家参考,具体如下:

一、准备环境

1、要有微信公众号,商户平台账号

https://pay.weixin.qq.com/wiki/doc/api/index.html

2、支持的支付方式有

python统一支付接口(Python实现的微信支付方式总结三种方式)

3、备案域名

选择扫码支付,如果使用模式二则不需要域名,只需要可访问的ip地址就行。

4、建一个django项目。

一、扫码支付

点击“扫码支付”按官方文档配置好回调url(具体如何配置看官网)
先从公众号上获取app_idapp_secrect,从商户平台上获取mch_idapi_key

1、使用模式一生成支付二维码

这个二维码是没有时间限制的。

create_qrcode.html

创建二维码页面

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • <!doctype html>
  • <html lang="en">
  • <head>
  •   <meta charset="utf-8">
  •   <title>生成扫码支付二维码</title>
  • </head>
  • <body>
  • <form method="post" action="/wxpay/qrcode/" >
  • 输入手机号:<input name="phone"/>
  • <input id="submit" type="submit" value="生成二维码">
  •   <br>
  •   {% if img_url %}
  •     <img src="{{ img_url }}" style="width: 200px;height: 200px"/>
  •   {% endif %}
  • <br>
  • {{ url }}
  • </form>
  • </body>
  • </html>
  • pay_settings.py

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • #微信支付配置
  • # ========支付相关配置信息===========
  • import random
  • import time
  • import hashlib
  • from random import random
  • import qrcode
  • from bs4 import beautifulsoup
  • app_id = "xxx" # 你公众账号上的appid
  • mch_id = "xxx" # 你的商户号
  • api_key = "xxx" # 微信商户平台(pay.weixin.qq.com) -->账户设置 -->api安全 -->密钥设置,设置完成后把密钥复制到这里
  • app_secrect = "xxx"
  • ufdoder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder" # 该url是微信下单api
  • notify_url = "http://xxx/" # 微信支付结果回调接口,需要改为你的服务器上处理结果回调的方法路径
  • create_ip = 'xxx' # 你服务器的ip
  • def random_str(randomlength=8):
  •   """
  •   生成随机字符串
  •   :param randomlength: 字符串长度
  •   :return:
  •   """
  •   str = ''
  •   chars = 'aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz0123456789'
  •   length = len(chars) - 1
  •   random = random()
  •   for i in range(randomlength):
  •     str+=chars[random.randint(0, length)]
  •   return str
  • def order_num(phone):
  •   """
  •   生成扫码付款订单号
  •   :param phone: 手机号
  •   :return:
  •   """
  •   local_time = time.strftime('%y%m%d%h%m%s', time.localtime(time.time()))
  •   result = phone + 't' + local_time + random_str(5)
  •   return result
  • def get_sign(data_dict, key):
  •   # 签名函数,参数为签名的数据和密钥
  •   params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=false) # 参数字典倒排序为列表
  •   params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
  •   # 组织参数字符串并在末尾添加商户交易密钥
  •   md5 = hashlib.md5() # 使用md5加密模式
  •   md5.update(params_str.encode('utf-8')) # 将参数字符串传入
  •   sign = md5.hexdigest().upper() # 完成加密并转为大写
  •   return sign
  • def trans_dict_to_xml(data_dict): # 定义字典转xml的函数
  •   data_xml = []
  •   for k in sorted(data_dict.keys()): # 遍历字典排序后的key
  •     v = data_dict.get(k) # 取出字典中key对应的value
  •     if k == 'detail' and not v.startswith('<![cdata['): # 添加xml标记
  •       v = '<![cdata[{}]]>'.format(v)
  •     data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
  •   return '<xml>{}</xml>'.format(''.join(data_xml)).encode('utf-8') # 返回xml,并转成utf-8,解决中文的问题
  • def trans_xml_to_dict(data_xml):
  •   soup = beautifulsoup(data_xml, features='xml')
  •   xml = soup.find('xml') # 解析xml
  •   if not xml:
  •     return {}
  •   data_dict = dict([(item.name, item.text) for item in xml.find_all()])
  •   return data_dict
  • def wx_pay_unifiedorde(detail):
  •   """
  •   访问微信支付统一下单接口
  •   :param detail:
  •   :return:
  •   """
  •   detail['sign'] = get_sign(detail, api_key)
  •   # print(detail)
  •   xml = trans_dict_to_xml(detail) # 转换字典为xml
  •   response = requests.request('post', ufdoder_url, data=xml) # 以post方式向微信公众平台服务器发起请求
  •   # data_dict = trans_xml_to_dict(response.content) # 将请求返回的数据转为字典
  •   return response.content
  • def pay_fail(err_msg):
  •   """
  •   微信支付失败
  •   :param err_msg: 失败原因
  •   :return:
  •   """
  •   data_dict = {'return_msg': err_msg, 'return_code': 'fail'}
  •   return trans_dict_to_xml(data_dict)
  • def create_qrcode(phone,url):
  •   """
  •   生成扫码支付二维码
  •   :param phone: 手机号
  •   :param url: 支付路由
  •   :return:
  •   """
  •   img = qrcode.make(url) # 创建支付二维码片
  •   # 你存放二维码的地址
  •   img_url = r'media/qrcode' + '/' + phone + '.jpg" alt="python统一支付接口(Python实现的微信支付方式总结三种方式)" border="0" />
  •   img.save(img_url)
  •   return img_url
  • views.py

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • from django.shortcuts import render
  • from django.http import httpresponse
  • from django.views import view
  • from django.views.decorators.csrf import csrf_exempt
  • from pay_settings.py import *
  • class wxpay_qrccode(view):
  •   """
  •   生成微信支付二维码
  •   """
  •   def get(self, request, *args, **kwargs):
  •     return render(request, 'create_qrcode.html')
  •   def post(self, request, *args, **kwargs):
  •     """
  •     # 生成可扫码支付的二维码
  •     :param request:
  •     :param args:
  •     :param kwargs:
  •     :return:
  •     """
  •     phone = request.data.get('phone', none)
  •     if not phone:
  •       return httpresponse('手机号获取失败')
  •     paydict = {
  •       'appid': app_id,
  •       'mch_id': mch_id,
  •       'nonce_str': random_str(phone),
  •       'product_id': phone, # 商品id,可自定义
  •       'time_stamp': int(time.time()),
  •     }
  •     paydict['sign'] = get_sign(paydict, api_key)
  •     url = "weixin://wxpay/bizpayurl?appid=%s&mch_id=%s&nonce_str=%s&product_id=%s&time_stamp=%s&sign=%s" \
  •        % (paydict['appid'], paydict['mch_id'], paydict['nonce_str'], paydict['product_id'], paydict['time_stamp'], paydict['sign'])
  •     # 可以直接在微信中点击该url,如果有错误,微信会弹出提示框,如果是扫码,如果失败,什么提示都没有,不利于调试
  •     print(url)
  •     # 创建二维码
  •     img_url = create_qrcode(url)
  •     return render(request, 'create_qrcode.html', context={'img_url': img_url})
  • @method_decorator(csrf_exempt, name='dispatch')
  • class wxpay_modelone_pay(view):
  •   """
  •   使用微信扫一扫扫描二维码,微信系统会自动回调此路由,post请求
  •   """
  •   def post(self, request, *args, **kwargs):
  •     """
  •     扫描二维码后,微信系统回调的地址处理
  •     微信传来的参数格式经trans_xml_to_dict()转成字典
  •     {'openid': 'xxx',
  •      'is_subscribe': 'y',
  •      'mch_id': 'xxx',
  •      'nonce_str': 'xxx',
  •      'sign': 'xxx',
  •      'product_id': 'xxx',
  •      'appid': 'xxx'}
  •     :param request:
  •     :param args:
  •     :param kwargs:
  •     :return:
  •     """
  •     data_dict = trans_xml_to_dict(request.body) # 回调数据转字典
  •     sign = data_dict.pop('sign') # 取出签名
  •     key = api_key # 商户交易密钥
  •     back_sign = get_sign(data_dict, key) # 计算签名
  •     if sign == back_sign: # 验证签名是否与回调签名相同
  •       total_fee = 1 # 付款金额,单位是分,必须是整数
  •       params = {
  •         'appid': app_id, # appid
  •         'mch_id': mch_id, # 商户号
  •         'nonce_str': random_str(16), # 随机字符串
  •         'out_trade_no': order_num(data_dict['product_id']), # 订单编号
  •         'total_fee': total_fee, # 订单总金额
  •         'spbill_create_ip': create_ip, # 发送请求服务器的ip地址
  •         'notify_url': notify_url,
  •         'body': 'xxx公司'# 商品描述
  •         'detail': 'xxx商品', # 商品详情
  •         'trade_type': 'native', # 扫码支付类型
  •       }
  •       # 调用微信统一下单支付接口url
  •       notify_result = wx_pay_unifiedorde(params)
  •       #print(trans_xml_to_dict(notify_result))
  •       return httpresponse(notify_result)
  •     return httpresponse(pay_fail('交易信息有误,请重新扫码'))
  • 2、使用模式二生成支付二维码

    这个二维码是有时间限制的。

    模式二与模式一相比,流程更为简单,不依赖设置的回调支付url。商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接

    上一篇下一篇

    猜您喜欢

    热门推荐