微信二次开发案例,python制作微信支付小程序!插图

近在琢磨小程序的支付,在这里简单介绍一下讲一下用python做小程序支付这个流程。当然在进行开发之前还是建议读一下具体的流程,清楚支付的过程。

1.支付交互流程

微信二次开发案例,python制作微信支付小程序!插图1

当然具体的参数配置可以参考官方文档

https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1

2.获取openid(微信用户标识)

import requests from config import APPID, SECRET class OpenidUtils(object): def __init__(self, jscode): self.url = “https://api.weixin.qq.com/sns/jscode2session” self.appid = APPID 小程序id self.secret = SECRET 不要跟后面支付的key搞混 self.jscode = jscode 前端传回的动态jscode def get_openid(self): url一定要拼接,不可用传参方式 url = self.url + “?appid=” + self.appid + “&secret=” + self.secret + “&js_code=” + self.jscode + “&grant_type=authorization_code” r = requests.get(url) print(r.json()) openid = r.json()[openid] return openid
微信二次开发案例,python制作微信支付小程序!插图2

3.支付请求

-*- coding:utf-8 -*- import requests import hashlib import xmltodict import time import random import string import urllib2 import sys class WX_PayToolUtil(): “”” 微信支付工具 “”” def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL): self._APP_ID = APP_ID 小程序ID self._MCH_ID = MCH_ID 商户号 self._API_KEY = API_KEY self._UFDODER_URL = “https://api.mch.weixin.qq.com/pay/unifiedorder” 接口链接 self._NOTIFY_URL = NOTIFY_URL 异步通知 def generate_sign(self, param): 生成签名 stringA = ks = sorted(param.keys()) 参数排序 for k in ks: stringA += (k + = + param[k] + &) 拼接商户KEY stringSignTemp = stringA + “key=” + self._API_KEY md5加密,也可以用其他方式 hash_md5 = hashlib.md5(stringSignTemp.encode(utf8)) sign = hash_md5.hexdigest().upper() return sign python2另外一种实现方法 def generate_sign(self, params): ret = [] for k in sorted(params.keys()): if (k != sign) and (k != ) and (params[k] is not None): ret.append(%s=%s % (k, params[k])) params_str = &.join(ret) params_str = %(params_str)s&key=%(partner_key)s % {params_str: params_str, partner_key: key} reload(sys) sys.setdefaultencoding(utf8) params_str = hashlib.md5(params_str.encode(utf-8)).hexdigest() sign = params_str.upper() return sign def getPayUrl(self, orderid, openid, goodsPrice, **kwargs): “””向微信支付端发出请求,获取url””” key = self._API_KEY nonce_str = .join(random.sample(string.letters + string.digits, 30)) 生成随机字符串,小于32位 params = { appid: self._APP_ID, 小程序ID mch_id: self._MCH_ID, 商户号 nonce_str: nonce_str, 随机字符串 “body”: 测试订单, 支付说明 out_trade_no: orderid, 生成的订单号 total_fee: str(goodsPrice), 标价金额 spbill_create_ip: “127.0.0.1”, 小程序不能获取客户ip,web用socekt实现 notify_url: self._NOTIFY_URL, trade_type: “JSAPI”, 支付类型 “openid”: openid, 用户id } 生成签名 params[sign] = self.generate_sign(params) python3一种写法 param = {root: params} xml = xmltodict.unparse(param) response = requests.post(self._UFDODER_URL, data=xml.encode(utf-8), headers={Content-Type: text/xml}) xml 2 dict msg = response.text xmlmsg = xmltodict.parse(msg) 4. 获取prepay_id if xmlmsg[xml][return_code] == SUCCESS: if xmlmsg[xml][result_code] == SUCCESS: prepay_id = xmlmsg[xml][prepay_id] 时间戳 timeStamp = str(int(time.time())) 5. 五个参数 data = { “appId”: self._APP_ID, “nonceStr”: nonce_str, “package”: “prepay_id=” + prepay_id, “signType”: MD5, “timeStamp”: timeStamp, } 6. paySign签名 paySign = self.generate_sign(data) data[“paySign”] = paySign 加入签名 7. 传给前端的签名后的参数 return data python2一种写法 request_xml_str = for key, value in params.items(): if isinstance(value, str): request_xml_str = %s<%s> % (request_xml_str, key, value, key,) else: request_xml_str = %s<%s>%s % (request_xml_str, key, value, key,) request_xml_str = %s % request_xml_str 向微信支付发出请求,并提取回传数据 res = urllib2.Request(self._UFDODER_URL, data=request_xml_str.encode(“utf-8”)) res_data = urllib2.urlopen(res) res_read = res_data.read() doc = xmltodict.parse(res_read) return_code = doc[xml][return_code] if return_code == “SUCCESS”: result_code = doc[xml][result_code] if result_code == “SUCCESS”: doc = doc[xml] data = { “appId”: self._APP_ID, “nonceStr”: nonce_str, “package”: “prepay_id=” + doc[“prepay_id”], “signType”: MD5, “timeStamp”: str(int(time.time())), } paySign签名 paySign = self.generate_sign(data) data[“paySign”] = paySign 加入签名 return data else: err_des = doc[xml][err_code_des] return err_des else: fail_des = doc[xml][return_msg] return fail_des

当然你可能会遇到的错误有签名错误,一般的情况是你的appSecret和商户号的API密钥两个弄错了,当然如果不是还有可能是其他问题 。

其他的支付方式获取用户的ip地址可以通过socket.gethostbyname(socket.gethostname())方法来获取。

4.支付回调

统一下单回调处理 import xmltodict from django.http import HttpResponse def payback(request): msg = request.body.decode(utf-8) xmlmsg = xmltodict.parse(msg) return_code = xmlmsg[xml][return_code] if return_code == FAIL: 官方发出错误 return HttpResponse(“”” “””, content_type=text/xml, status=200) elif return_code == SUCCESS: 拿到这次支付的订单号 out_trade_no = xmlmsg[xml][out_trade_no] 根据需要处理业务逻辑 return HttpResponse(“”” “””, content_type=text/xml, status=200)

5.安全问题

在使用的过程中 商户系统对于支付结果通知的内容一定要做 签名验证,并校验返回的订单金额是否与商户侧的订单金额一致 ,防止数据泄漏导致出现假通知,造成资金损失。

我在开发过程中的解决方式是在向微信支付端发起请求的时候, 把订单号,金额,签名等存入数据库,然后在回调函数那里进行校验判断 。在确认跟前面订单情况一样的情况下,才进行后续一系列的操作。

觉得文章还不错的朋友可以转发+关注哦

需要免费Python学习资料的朋友可以私信资料领取。

作者 nasiapp

在线客服
官方客服
我们将24小时内回复。
12:01
您好,有任何疑问请与我们联系!

选择聊天工具: