一.微信小程序支付
真的,在接到这个任务的时候,本以为很简单,不就是普通的浏览器复制粘贴,最不济找下gpt给生成一下,但是到实际开发就不同了,不是后端出问题就是前端,搜资料,上百度上google,基本每一个人讲的都不一样,不是这问题就是那问题,特别是微信官方,自己接口的逻辑也不整清楚,就算是报错,参数错误连个提示也没有,而且用python写后端的少之又少,我只是想说,python-flask写接口简直不要太好用,java真的太胖了,这里的胖就是指的是,像小程序这种逻辑和体量并不大的项目来说,python作为后端就是不是太好用
二.前期准备(你必须会的,要准备的)
2.1你必须会的
uniapp开发小程序的前端
这个国内的资源还是蛮全的,一搜一大把,先搜《uniapp开发第一个小程序hello word》一天搞点到入门
python-flask开发小程序的后端
这个更多,先搜《python-flask如何开发后端接口》
2.2要准备的
appid:不用多说,小程序的appid mch_id:商家号,先搜《微信支付》,点击进去,一通申请,一通绑定到小程序 今天篇文章主要是讲代码开发的,需要讲讲怎么绑定的可以评论,专门来讲讲怎么绑定怎么申请或者 文章最后会写怎么联系我 key:商家支付密钥 没了,没了,就这三个,基本就是登录注册,得到这些玩意
三.开始第一步
首先你有个可以获取openid的接口,可以就是我们python-flask里面写就ok了
先看看整体
import flask from flask import request, jsonify, send_file from gevent import pywsgi from flask_cors import CORS import requests import json from datetime import datetime import hashlib import string import random import xmltodict import time import threading #你的代码区开始 #你的代码区结束 if __name__ == '__main__': server2 = pywsgi.WSGIServer(('0.0.0.0', 7004), server) server2.serve_forever()
我们就往开发到结束来进行讲解
首先还是你要有一个获取openid的接口
@server.route('/api/GetOpenid') def GetOpenidYSGJ(): # 获取用户的code,从而获取用户的唯一标识openid code = request.args.get('code') res = {} if code!="": response = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid=xxxxxxxxxx&secret=1c56f6b24ad40c468879ae3bae6bcd5b&js_code='+code+'&grant_type=authorization_code') resdata=json.loads(response.text) try: if resdata['openid'] != "": res['openid'] = resdata['openid'] return res else: res['openid'] = "0" return res except: res['openid'] = "0" return res else: res['openid']="0" return res
看懂了晒,前端访问这个接口/api/GetOpenid,传入code,code开发小程序的都是wx.login()或者uniapp开发的,uni.logo()就能获取code,code以获取就获取到openid了
开始第二步
首先创建4个方法
1.获取随机字符串generate_nonce_str()
2.获取签名generate_sign((data, key),
3.将字典转换为xml格式dict_to_xml(data)
4.将xml格式的数据转换为字典xml_to_dict(xml_data)
分别是
def generate_nonce_str(length=32): chars = string.ascii_letters + string.digits return ''.join(random.choice(chars) for _ in range(length)) def generate_sign(data, key): sorted_keys = sorted(data.keys()) stringA = '&'.join([f"{key}={data[key]}" for key in sorted_keys]) stringSignTemp = f"{stringA}&key={key}".encode('utf-8') sign = hashlib.md5(stringSignTemp).hexdigest().upper() return sign def dict_to_xml(data): """ 将字典转换为xml格式 """ xml_data = [""] for k, v in data.items(): xml_data.append(f"<{k}>{v}{k}>") xml_data.append(" ") return "".join(xml_data) def xml_to_dict(xml_data): """ 将xml格式的数据转换为字典 """ xml_dict = {} soup = BeautifulSoup(xml_data, 'xml') for item in soup.find_all(): xml_dict[item.name] = item.text return xml_dict
创建微信支付接口请求unifiedorder
@server.route('/api/unifiedorder', methods=['POST']) def unifiedorder(): # 获取请求中的订单信息 data = request.json # 获取当前时间戳 client_ip = request.headers.get('X-Forwarded-For', request.headers.get('X-Real-IP', request.remote_addr)) #获取随机字符串的方法 sss=generate_nonce_str() # 构造统一下单请求参数 params = { 'appid': '你的小程序appid', 'mch_id': '商品号', 'nonce_str': sss, 'body': data['body'], 'out_trade_no': data['out_trade_no'], 'total_fee': data['total_fee'], 'spbill_create_ip': client_ip, 'notify_url': 'https://xxxxxxxxxx/wallpaper/api/your_notify_url', # 异步通知地址 'trade_type': 'JSAPI', # 小程序支付 'openid': data['openid'], # 用户在小程序中的openid } # 生成签名 sign = generate_sign(params, '微信商户的密钥V2的') params['sign'] = sign param = {'root': params} xml = xmltodict.unparse(param) # 将参数转换为 XML 格式 xml_data = dict_to_xml(params) # 发送请求到微信支付服务器 response = requests.post('https://api.mch.weixin.qq.com/pay/unifiedorder', data=xml.encode('utf-8'),headers={'Content-Type': 'text/xml'}) # 解析微信支付服务器的响应 result = xmltodict.parse(response.content.decode('utf-8')) # 封装返回结果 # 从微信支付服务器返回的结果中提取用于验证签名的部分参数 result_params = { 'appId': '小程序的appid', 'timeStamp': str(int(time.time())), 'nonceStr': generate_nonce_str(), 'package': "prepay_id="+result['xml']['prepay_id'], 'signType': 'MD5', } result_params['paySign'] = generate_sign(result_params, '微信商户的密钥V2的') return json.dumps(result_params)
开始第三步,回调地址
创建python回调地址接口
@server.route('/api/your_notify_url', methods=['POST']) def handle_payment_notification(): # 处理微信支付结果异步通知的逻辑 data = request.data # 在这里处理通知数据,验证签名等操作 print("有用户充值啦") # 解析微信支付服务器的响应 result = xmltodict.parse(data.decode('utf-8')) print(result) #获取openid openid=result['xml']['openid'] #获取充值了多少 cash_fee=result['xml']['cash_fee'] # 状态 result_code = result['xml']['result_code'] # 状态2 return_code = result['xml']['return_code'] # 订单号 transaction_id = result['xml']['transaction_id'] if result_code=="SUCCESS" and return_code=="SUCCESS": # 进行你的数据处理 print(openid) print(cash_fee) print(type(cash_fee)) # 返回成功响应给微信支付服务器 # 构建回复内容 response_data = {"code":"SUCCESS","message":"ok"} return 'SUCCESS',200
开始第四步,前端调用
我这里用的前端是uniapp
创建按钮进行请求
就是一个简单的创建按钮,然后绑定事件,举例绑定的事件是chongzhi()
具体事件代码就是
generateUniqueOrderNumber() { // 这里可以使用你的逻辑生成唯一订单号 return 'your_order_' + new Date().getTime(); }, chongzhi(amount){ const lll=this; try{ // 假设以下参数是从前端获取的 const body = "Kbit"; const total_fee = amount; // 订单总金额,单位为分 const openid = uni.getStorageSync("openid"); // 生成商户订单号,这里可以使用你自己的逻辑生成唯一订单号 const out_trade_no = this.generateUniqueOrderNumber(); console.log("----------------"+out_trade_no) // 发送支付请求 uni.request({ url: "https://你的服务器/api/unifiedorder", method: "POST", data: JSON.stringify({ body: body, out_trade_no: out_trade_no, total_fee: total_fee, openid: openid, }), success: (res) => { // 调起支付 uni.requestPayment({ provider: 'wxpay', timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: res.data.signType, paySign: res.data.paySign, success: function (res) { console.log(res); if(res.errMsg=="requestPayment:ok"){ //成功付款,进行查询和提示成功 //查询余额 //请求用户的个人信息 uni.showToast({ title: "充值成功", }) }, fail: function (err) { console.log("失败了") console.log(err); } }); }, fail: (err) => { console.error('支付请求失败:', err); uni.showToast({ title: err, duration: 2000, // 提示的延迟时间,单位毫秒,默认值 1500 mask: true, // 是否显示透明蒙层,防止触摸穿透,默认值 false success: function() { // 提示框关闭后的回调函数 } }) }, }); console.log(amount) }catch (e) { // TODO handle the exception console.log("充值失败,联系客服") console.log(e) } },
是不是超级的简单,很简单的四步就能充值成功,前端其实没啥讲的,主要是python来做微信支付的后端很少人讲到,所以才写了这一篇,希望能帮到大家
总结
总之就是一个很简单的v2版本的微信支付,简单来说就是3个外部接口,分别是获取openid的接口、微信支付主接口和回调接口,其他4个方法主要是来处理数据,前端更简单,传入该传入的值,金额,主要坑的点是在签名环节,网上很多方法,我这个方法是百分之百可以用的,不会出现签名错误
如果不懂的,可以通过关注微信公众号:程序员PG
来联系我
这边会提供
- 提供test的反向代理(如果没有服务器想用自己的电脑当服务器的,我可以用我的服务器给你做代理)
- 提供源码,更进一步的指导
- 提供技术服务
ok 这次就讲到这里了,如果有大神或者其他伙伴看出问题的,欢迎评论,大家一起交流
还没有评论,来说两句吧...