python统一支付接口
Python实现的微信支付方式总结三种方式本文实例讲述了python实现的微信支付方式。分享给大家供大家参考,具体如下:
一、准备环境
1、要有微信公众号,商户平台账号
https://pay.weixin.qq.com/wiki/doc/api/index.html
2、支持的支付方式有
3、备案域名
选择扫码支付,如果使用模式二则不需要域名,只需要可访问的ip地址就行。
4、建一个django项目。
一、扫码支付
点击“扫码支付”按官方文档配置好回调url(具体如何配置看官网)
先从公众号上获取app_id,app_secrect,从商户平台上获取mch_id,api_key
1、使用模式一生成支付二维码
这个二维码是没有时间限制的。
create_qrcode.html
创建二维码页面
|
<!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
|
#微信支付配置 # ========支付相关配置信息=========== 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
|
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。商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接