
作用:让小程序可以微信支付
如果是虚拟商品,IOS平台暂时不允许
收入也是要合法啊
登录微信公众平台,也就是小程序后台
功能 — 微信支付
2种情况:
1、已经有的就直接走起
2、没有的就去注册一个(注释:微信商户平台也就是微信支付,这里巨坑,名字会乱的,微信商户平台是旧名)
3个表
1、订单表
2、订单商品数据表
3、支付回调数据表
openid不要发送到前端,这是可以做到的
.wxml:
<button bindtap="pay">支付</button>
.js:
pay:function(){wx.request({url: "http://127.0.0.1:8000/pay/",method: "POST",data:{"login_key":wx.getStorageSync("login_key")},header: { "content-type": "application/json" },success: function (e) {console.log(e)// 签权调起支付wx.requestPayment({'timeStamp': e.data.data.timeStamp,'nonceStr': e.data.data.nonceStr,'package': e.data.data.package,'signType': e.data.data.signType,'paySign': e.data.data.paySign,'success': function (res){console.log(res,"成功")//小程序轮询服务器订单信息that.checkThePayInfo(e.data.out_trade_no)},'fail': function (res){console.log("支付失败",res)},})}})},
1、url,后端/商户系统/服务器的路由
2、data传一个可以识别openid的编号
from flask import Flask, jsonify, request, url_for,render_template,flash,make_response#蓝图configfrom flask import current_app as appimport hashlib,time,random#向微信服务器发送https请求import requests@app.route('/pay', methods=['POST'])def pay1():pay = Pay()#1、实例化Pay类data = pay.post(request)#2、使用Pay类的post方法return data #26、返回class Pay():def post(self,request):id = request.json.get('login_key') # 3、读取json,id用来获得openidprint(id)openid = User.query.filter_by(pk=id).first().openid # 4、id获得openidself.openid=openid #5、写入这个类里self.ip = request.remote_addr # 6、获取ip地址data = self.pay()# 7、调用 生成商户订单 方法return jsonify({"code":200,"msg":"ok","data":data,"out_trade_no":self.out_trade_no})#25、返回# 生成商户订单 提供 支付统一下单 所需参数def pay(self):#8、准备一下参数self.appid=app.config["WEIXIN_APP_ID"]#9、小程序应用idself.mch_id=app.config["WEIXIN_APP_MCH_ID"]#10、商户号idself.nonce_str=self.get_str()#11、服务器自己获得一个随机数self.body="商品名" # 12、商品名一般由小程序端传到后端self.out_trade_no=self.get_order()#13、服务器生成一个订单self.total_fee=1 #14、价格:一般用服务器里的价格,不用小程序的self.spbill_create_ip=self.ip #15、ipself.notify_url=app.config["WEIXIN_NOTIFY_URL"]# 16、返回支付成功/失败的地址self.trade_type="JSAPI" #17、交易类型JSAPIself.sign = self.get_sign() # 18、获取sign 签名#19、写成XML格式data=f'''<xml><appid>{self.appid}</appid><body>{ self.body}</body><mch_id>{self.mch_id}</mch_id><nonce_str>{self.nonce_str}</nonce_str><notify_url>{self.notify_url}</notify_url><openid>{self.openid}</openid><out_trade_no>{self.out_trade_no}</out_trade_no><spbill_create_ip>{self.spbill_create_ip}</spbill_create_ip><total_fee>{self.total_fee}</total_fee><trade_type>{self.trade_type}</trade_type><sign>{self.sign}</sign></xml>'''# 20、支付统一下单url="https://api.mch.weixin.qq.com/pay/unifiedorder"# 21、返回预付单信息# response = urllib.request.urlopen(url,data.encode("utf-8"))response = requests.post(url,data.encode("utf-8"))print("微信返回信息")# print(response.read())# 22、xml转dictres_data=self.xml_to_dict(response.text)# print(res_data)# 23、二次签名data = self.two_sign(res_data["prepay_id"])return data #24、返回#11、服务器自己获得一个随机数def get_str(self):str_all="1234567890abcdefghjklmasdwery" # 注意 开发活动功能时, 去掉1,i,0,ononce_str="".join(random.sample(str_all,20))return nonce_str# 13、服务器生成一个订单:包括时间+随机数def get_order(self):str_all = "1234567890abcdefghjklmasdwery"nonce_str = "".join(random.sample(str_all, 10))order_id = str(time.strftime("\\\\\\\\\\\\%Y\\\\\\\\\\\\%m\\\\\\\\\\\\%d\\\\\\\\\\\\%H\\\\\\\\\\\\%M\\\\\\\\\\\\%S") + nonce_str)return order_id# 18、获取sign 签名MD5def get_sign(self):data_dic = {"nonce_str": self.nonce_str,"out_trade_no": self.out_trade_no,"spbill_create_ip": self.ip,"notify_url": self.notify_url,"openid": self.openid,"body": self.body,"trade_type": "JSAPI","appid": self.appid,"total_fee": self.total_fee,"mch_id": self.mch_id}sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])sign_str = f"{sign_str}&key={app.config['WEIXIN_APP_MCH_KEY']}"md5 = hashlib.md5()md5.update(sign_str.encode("utf-8"))return md5.hexdigest().upper()# 23、二次签名,将组合数据再次签名def two_sign(self,prepay_id):timeStamp=str(int(time.time()))nonceStr=self.get_str()data_dict={"appId":app.config["WEIXIN_APP_ID"],"timeStamp":timeStamp,"nonceStr":nonceStr,"package":f"prepay_id={prepay_id}","signType":"MD5"}sign_str = "&".join([f"{k}={data_dict[k]}" for k in sorted(data_dict)])sign_str = f"{sign_str}&key={app.config['WEIXIN_APP_MCH_KEY']}"md5 = hashlib.md5()md5.update(sign_str.encode("utf-8"))sign=md5.hexdigest().upper()data_dict["paySign"]=sign#加入paySigndata_dict.pop("appId")#去掉appId# 返回支付参数到小程序端,小程序端获取所需参数向微信服务器发送 调起支付 方法return data_dict# 22、xml转dict处理,返回预付单方法def xml_to_dict(self,data):import xml.etree.ElementTree as ETxml_dict = {}data_dic = ET.fromstring(data)for item in data_dic:xml_dict[item.tag]=item.textreturn xml_dict
也就是上面小程序的代码
这里是设置notify_url的路由是啥,这里是/payback
算是示例代码
@app.route('/payback', methods=['POST'])def Payback():print("微信回调来的数据")data = request.dataprint(data)dict = xml_to_dict2(data)print(dict)return_code = dict['return_code']if return_code == "SUCCESS":###这里是判断,详细看微信文档:API列表:支付结果通知##print("succ")data = f'''< xml >< return_code > <![CDATA[SUCCESS]] > < / return_code >< return_msg > <![CDATA[OK]] > < / return_msg >< / xml >'''return dataelse:print("fail")data = f'''< xml >< return_code > <![CDATA[FAIL]] > < / return_code >< return_msg > <![CDATA[OK]] > < / return_msg >< / xml >'''return data# 处理返回预付单方法def xml_to_dict2(data):import xml.etree.ElementTree as ETxml_dict = {}data_dic = ET.fromstring(data)for item in data_dic:xml_dict[item.tag]=item.textreturn xml_dict
1、蓝图命名
2、对比判断有无出错
小程序轮询
//轮询服务器订单信息checkThePayInfo(out_trade_no) {const requestTask = wx.request({url: Config.restUrl + '/checkThePayInfo', //仅为示例,并非真实的接口地址data: {x: out_trade_no,y: ''},header: {'content-type': 'application/json'},success(res) {console.log(res.data.info)requestTask.abort() // 取消请求任务//返回墙页和刷新wx.navigateBack({url: '../logs/logs',})}})}
#小程序轮询@app.route('/checkThePayInfo', methods=['GET'])def checkThePayInfo():return {"info":"ok"}