微信支付 Python

需求:

微信打开商品列表页面-> 点击商品后直接显示付款页面-> 点击付款调用微信支付

说明

微信支付需要你申请了公众号(appid, key - 用于签名), 商户号(mch_id, AppSecret - 用于获取openid, 获取code)
调起微信支付的页面需要配置授权, 如你的页面是http://www.shazuihuo.com/goods/index.html. 那么你需要配置为: http://www.shazuihuo.com/goods/ 即可, 这个是在商户号中配置
签名算法和校验工具

  1. 签名校验通过时还是提示签名错误, 可能时候商户号KEY配置的问题了, 重置一下KEY, 你可以继续使用原来的KEY来重置
  2. 公众号变更时记得修改后台和前台代码中的APPID

需要的ID和KEY

# 微信配置基础数据
WPC = {'APPID': 'wx53c1xxxxad626eb8','APPSECRET': 'fdd177a7xxxxxxxxxxxxx856eeeb187c','MCHID': '14222000000','KEY': 'd7810713e1exxxxxxxxxxadc9617d0a6','GOODDESC': '商户号中的公司简称或全称-无要求的商品名字','NOTIFY_URL': 'https://www.xxxx.com/service/applesson/wechatordernotice', 
}

流程简介

  1. 网页内调起微信支付需要一个微信统一下单生成的订单号(prepay_id)
  2. 调用微信的统一下单接口需要一个用户在商户下的唯一标示(openid)
  3. 获取openid需要code参数加上AppID和AppSecret等,通过API换取access_token(openid)
  4. 其中code又需要通过页面跳转来获取, 需要appid和重定向url(可以带有你自己的参数, 会原样返回)
    那么开发思路便是一步步回朔了.

1. 获取code

用户点击按钮跳转到微信授权页, 微信处理完后重定向到redirect_uri, 并给我们加上code=xxx的参数, 这个code就是我们需要的

    $('#buy').click(function() {var param = {appid: 'wx53c1xxxxad626eb8',redirect_uri: 'https://www.xxxxx.com/wcpay/pay.html',response_type: 'code',scope: 'snsapi_base',state: '1'}window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?' + $.param(param);})

2. 获取openid

这个在后台完成, WPC中配置了你的APPSECRET, 这个不能泄露, 接口调用成功会拿到一个openid, 这里都不会有什么问题

    @classmethoddef getOpenID(cls, kwargs):param = {'code': kwargs['code'],'appid': WPC['APPID'],'secret': WPC['APPSECRET'],'grant_type': 'authorization_code',}# 通过code获取access_tokenopenIdUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token'resp = requests.get(openIdUrl, params=param)# {openid, accss_token, refresh_token, openid, scope, expires_in}# openId = json.loads(resp.text)['openid']return resp.text

3. 微信统一下单

统一下单 时参数传递需要签名(微信用我们设定的密匙对参数进行MD5加密, 通过双方的签名判断请求是否被篡改)
签名算法

@classmethod
def getSign(cls, kwargs):# 计算签名keys, paras = sorted(kwargs), []paras = ['{}={}'.format(key, kwargs[key]) for key in keys if key != 'appkey']  # and kwargs[key] != '']stringA = '&'.join(paras)stringSignTemp = stringA + '&key=' + WPC['KEY']sign = MD5(stringSignTemp).upper()return sign

MD5函数

import hashlib# 获取MD5
def MD5(str):md5 = hashlib.md5()md5.update(str.encode('utf-8'))return md5.hexdigest()

参数转xml

@classmethod
def getxml(cls, kwargs):kwargs['sign'] = Utility.getSign(kwargs)# 生成xmlxml = ''for key, value in kwargs.items():xml += '<{0}>{1}</{0}>'.format(key, value)xml = '<xml>{0}</xml>'.format(xml)# print(xml)return xml

统一下单代码

code = self.POST.get('code')
openidresp = Utility.getOpenID({'code': code})
openid = json.loads(openidresp).get('openid')UnifieOrderRequest = {'appid': 'wx53c1xxxxad626eb8',  # 公众账号ID'body': '公司名称-商品',  # 商品描述'mch_id': '1397xxxxxx8',  # 商户号:深圳市泽慧文化传播有限公司'nonce_str': '',  # 随机字符串'notify_url': 'https://service.xxxx.com/service/applesson/wechatordernotice',  # 微信支付结果异步通知地址'openid': '',  # trade_type为JSAPI时,openid为必填参数!此参数为微信用户在商户对应appid下的唯一标识, 统一支付接口中,缺少必填参数openid!'out_trade_no': '',  # 商户订单号'spbill_create_ip': '',  # 终端IP'total_fee': '',  # 标价金额'trade_type': 'JSAPI',  # 交易类型
}
UnifieOrderRequest['nonce_str'] = Utility.getnoncestr()
UnifieOrderRequest['openid'] = openid
UnifieOrderRequest['out_trade_no'] = UnifieOrderRequest['mch_id'] + str(order.id)  # 内部订单号码
UnifieOrderRequest['spbill_create_ip'] = self.request.remote_ip
UnifieOrderRequest['total_fee'] = int(lesson.price * 100)
# 签名并生成xml
xml = Utility.getxml(UnifieOrderRequest)resp = requests.post("https://api.mch.weixin.qq.com/pay/unifiedorder", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
prepay_id = ''if xmlresp['xml']['return_code'] == 'SUCCESS':if xmlresp['xml']['result_code'] == 'SUCCESS':prepay_id = xmlresp['xml']['prepay_id']timestamp = str(int(time.time()))data = {"appId": xmlresp['xml']['appid'],"nonceStr": Utility.getnoncestr(),"package": "prepay_id=" + xmlresp['xml']['prepay_id'],"signType": "MD5","timeStamp": timestamp}data['paySign'] = Utility.getSign(data)data['orderid'] = order.id  # 付款后操作的订单# 签名后返回给前端做支付参数return JsonResponse(self, '000', data=data)else:msg = xmlresp['xml']['err_code_des']return JsonResponse(self, '002', msg=msg)
else:msg = xmlresp['xml']['return_msg']return JsonResponse(self, '002', msg=msg)

统一下单成功返回后直接调用微信支付, 显示支付界面, 其中的paySign是我们自己的签名

try {// statements// 微信统一订单, 返回预支付信息var code = query('code'),origin = query('groupid');// alert(code);$.post({url: orderurl,data: {origin: origin,mobile: phone,code: code}}).then(function(resp) {if (resp.code && resp.code == "000") {// 后台返回订单信息var wepaydata = {appId: resp.data.appId,nonceStr: resp.data.nonceStr,package: resp.data.package,paySign: resp.data.paySign,signType: "MD5",timeStamp: resp.data.timeStamp};var orderid = resp.data.orderid || 0;window.jsApiCall = function() {WeixinJSBridge.invoke('getBrandWCPayRequest',wepaydata,function(res) {WeixinJSBridge.log(res.err_msg);// alert(res.err_code + res.err_desc + res.err_msg);// alert(res.err_msg)if (res.err_msg == 'get_brand_wcpay_request:ok') {$.get(orderurl, { orderid: orderid }, function(resp) {if (resp.code == '000') {window.location.href = window.location.href.replace('pay.html', 'success.html');} else {alert(resp.msg);// 一个code只能请求一次, 重新进入indexif (resp.code == '002') {window.location.href = window.location.href.replace('pay.html', 'index.html');}}});} else {// 其他支付异常微信有显示消息// alert(res.err_msg);}});}window.callpay = function() {if (typeof WeixinJSBridge == "undefined") {if (document.addEventListener) {document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);} else if (document.attachEvent) {document.attachEvent('WeixinJSBridgeReady', jsApiCall);document.attachEvent('onWeixinJSBridgeReady', jsApiCall);}} else {jsApiCall();}}// 发起支付window.callpay();} else {alert(resp.msg);// alert(JSON.stringify(resp) + resp.msg);}}, function(resp) {alert(resp)alert(JSON.stringify(resp))// alert('请求失败, 请重试');});
} catch (e) {// statementsalert(e)
}

4. 订单查询

订单查询 是为了确认我们的支付是成功的

# 查询微信付款情况
orderid = self.GET.get('orderid')
orderquery = {'appid': WPC['APPID'],'mch_id': WPC['MCHID'],'nonce_str': Utility.getnoncestr(),'out_trade_no': WPC['MCHID'] + orderid
}
xml = Utility.getxml(orderquery)
print(xml)resp = requests.post("https://api.mch.weixin.qq.com/pay/orderquery", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
print(xmlresp)orderPaid = 0
if xmlresp['xml']['return_code'] == 'SUCCESS':if xmlresp['xml']['result_code'] == 'SUCCESS':if xmlresp['xml']['trade_state'] == 'SUCCESS':orderPaid = 1else:msg = xmlresp['xml']['trade_state_desc']return JsonResponse(self, '001', msg=smg)else:msg = xmlresp['xml']['err_code_des']return JsonResponse(self, '001', msg=msg)
else:msg = xmlresp['xml']['return_msg']return JsonResponse(self, '001', msg=msg)

官方Demo

SDK与DEMO下载, 用python就需要自己码代码, 当时看的是PHP的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/782925.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷 P4305 不重复数字——题解

洛谷P4305题解传送锚点摸鱼环节 [JLOI2011] 不重复数字 题目描述 给定 \(n\) 个数,要求把其中重复的去掉,只保留第一次出现的数。 输入格式 本题有多组数据。 第一行一个整数 \(T\),表示数据组数。 对于每组数据: 第一行一个整数 \(n\)。 第二行 \(n\) 个数,表示给定的数。…

代码随想录Day12

二叉树遍历 分为前序、中序、后续、层序四种 其中前中后序属于深度优先搜索,层序属于广度优先搜索 前序遍历顺序: 根节点->左子树->右子树 中序遍历顺序: 左子树->根节点->右子树 后序遍历顺序: 左子树->右子树->根节点 不难发现,前中后其实就是根节点在…

通信组件 --- netlink 原理及应用

什么是netlink netlink是一种基于网络的通信机制,允许内核内部、内核与用户态应用之间甚至用户态应用之间进行通信;netlink的主要作用是内核与用户态之间通信;它的思想是,基于BSD的socket使用网络框架在内核和用户态之间进行通信; 为什么要有netlink 内核中有其他一些方法…

向量数据库和异常数据

书接上文:https://www.cnblogs.com/k4n5ha0/p/18314781 最近学习机器学习期间,了解到了向量数据库:1)可以将文本向量化存储(如上图,将不同语句向量化) 2)在 检索向量的时间复杂 和 对比向量相似度的时间复杂度(例如余弦相似度)充分调优 3)可以调用TPU、GPU等硬件加…

二维差分学习备忘录

二维差分为什么我为OI泪目?因为我菜得离谱......引入 一维差分用来O(1)修改区间,配合上一维前缀和就是O(N)的查询区间和。 差分为前缀和的逆运算。 二维差分同理。 接下来这道题就用二维差分来解决。 \(例题:地毯>>\) 地毯 题目描述 在 \(n\times n\) 的格子上有 \(m\…

4.自定义的信号和槽

自定义信号 1.写到signal下 2.返回void 3.需要声明,不需要实现 4.可以有参数,可以重载 自定义槽函数 1.返回void 2.需要声明,也需要实现 3.可以有参数,可以重载 4.写到pulic slot下或者pulic或者全局函数 触发自定义的信号 1.emit 自定义信号 案例:下课后,老师触发饿了信…

Windows日志致盲与绕过

前言 在渗透测试过程中,Windows日志往往会记录系统上的敏感操作,如添加用户、写计划任务、远程登录执行等操作,对于会审计的安全运维人员或者网络管理员来说,简直就是脱掉衣服走路,被看的一清二楚。对于比较高阶的渗透操作中,要讲究的是动作无感化,来无影去无踪。而对于…

java maven项目配置及IDEA配置

一:maven作用项目管理:编译、测试、打包、部署、运行,这一套流程都可以用maven来管理。管理jar包:也就是上述提到的问题。管理插件:开发过程中会需要使用各种插件。3maven环境变量配置和Java一样,也需要配置maven环境变量。环境变量的作用在于: 可以让该程序在任何路径下…

Go并发原语之SingleFlight

引入 如下图所示,可能存在来自桌面端和移动端的用户有 1000 的并发请求,同一时刻来访问的获取文章列表的接口,获取前 20 条信息,如果这时服务直接去访问 redis 出现 cache miss, 那就会去请求 1000 次数据库,这时可能会给数据库带来较大的压力(这里的1000 只是一个例子,…

词向量的转换理解以及与真实的关系

实际上就是去除该矩阵的某一行。该矩阵实际上就是一个有N个词的300维向量,或者说该矩阵就是一个完整的词向量词汇表。而这个词汇表是通过交叉熵损失最小来构造的。 即归根到底是“在特定语料库中(包含context中共现概率),以数学方法计算输入产生哪些输出”最复合“实际情况…

盘点国内外有哪些软件测试认证

在软件测试行业,技术实力固然重要,但手握权威认证更能为职业发展增添砝码。无论你是刚入行的新人,还是经验丰富的测试工程师,获取一张含金量高的软件测试认证都能让你的职场之路更加平坦。那么,国内外有哪些值得考取的软件测试认证呢?让我们一起来盘点。 你是否正在为选择…

用友金蝶怎么选

财务知识——用友和金蝶选择谁?