# Django 如何对接公众号调起微信支付
我只讲重要的部分,其他像申请什么公众号资料、商户号等都不在这倾述,因为太多了,需要的自己去网上搜一搜别人的案例,看看需要什么
首先在 Django 可以安装 wechatpy 模块,由于微信支付的 sdk 方面并没有很好的支持 Python,至少我没看见(没查到),wechatpy 是第三方微信支付的 sdk,使用该模块可以忽略很多加密的部分,减少代码量,详细可以参考官方文档
https://github.com/wechatpy/wechatpy
另外,wechatpy 也使用到了 cryptography 模块,在 window 安装多半会报错,这时你可以升级一下 pip,在进行安装即可。
# 公众号及证书、域名配置
在公众号后台,找到设置与开发 -> 接口权限,找到 “网页授权获取用户基本信息”,点击设置
注意:如果不是企业号,是不支持微信支付的
前提你需要有能访问的外网,或者自己弄一个内网穿透,才能设置成功,在你点击设置域名时,在注意事项中,你需将提示中的 txt 文件下载,放到你服务器的根目录,确保能访问到即可,这时点击保存修改才能成功,否则会报错提示为找到 txt 文件
你的网页授权域名设置时,比如你的 H5,也要确保 txt 能访问到,如 vue3,直接放到 public 目录即可。对于 JS 接口安全域名,因为使用的是 Django,所以你也需要将 txt 文件放到 templates 目录,因为 Django 默认配置下是在 templates 目录里中查找,然后在 urls 中配置文件路径
from django.urls import path | |
from django.views.generic.base import TemplateView | |
urlpatterns = [ | |
path('MP_verify_3wHwPaaUMrpct6Fu.txt', TemplateView.as_view(template_name="MP_verify_3wHwPaaUMrpct6Fu.txt", content_type="text/plain")), | |
] |
接口权限地址:https://mp.weixin.qq.com/advanced/advanced?action=table&token=162251921&lang=zh_CN
接下来找到设置与开发 -> 基本设置,找到 appId 和 appSecret
在你后端调用获取获取微信用户信息时需要用到,比如 openid,其他的数据看需不需要
获取授权文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
import requests | |
params = { | |
"grant_type": "authorization_code", | |
"appid": "appId", | |
"secret": "appSecret", | |
"code": "前端页面获取的code值,具体看下面" | |
} | |
response = requests.get(url="https://api.weixin.qq.com/sns/oauth2/access_token", params=params) |
在你的公众号页面中,比如登录页,你要先获取 code 值传递到后端才能得到 access_token,然后根据该 access_token 值才能真正获取到微信用户的基本信息,最重要时 openid,在测试支付时,你必须使用的是正式环境下获取的用户 openid,因为你如果使用测试账户获取的 openid,实际是和正式环境不一样的,需要注意。
在网页中你可以使用跳转的方式获取到 code 值,比如
const redirectUrl = window.location.href | |
if (redirectUrl.includes('code')) { | |
this.code = redirectUrl.split('?')[1].split('&')[0].split('=')[1] | |
} else { | |
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=appId&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect&forcePopup` | |
} | |
//snsapi_userinfo 参数会有弹窗提示用户是否授权,可以获取更多的用户信息,而 snsapi_base 是静默授权,只能获取 openid |
对于 redirect_uri 参数重定向的链接,你需要在前面先设置好网页授权域名才可以,否则会有问题,我记得是。。。然后还有 appId 参数,比如与公众号的 appId 一致,还有后端。
# Django 生成预支付订单
前面的配置工作应该差不多了,这时回到 Django 中,使用 wechatpy 模块生成预支付订单参数,那么在次之前,你需要在微信商户平台中申请好 API 证书、V2、V3、平台证书,调用 wechatpy 时会用到
微信商户平台:https://pay.weixin.qq.com/index.php/core/home/login
然后将这些证书配置放到 Django 项目,首先我们需要导入 wechatpy 模块
from wechatpy.pay import WeChatPay | |
client = WeChatPay( | |
appid="appId", | |
mch_id="商户号ID", | |
api_key="v2或v3的密钥值", | |
mch_cert="apiclient_cert.pem证书路径", | |
mch_key="apiclient_key.pem文件路径" | |
) | |
# apiclient_cert.pem 与 apiclient_key.pem 都在你下载下来的证书压缩包里面,解压就能找到 |
接着我们调用 client 生成预订单参数
create_result = client.order.create( | |
trade_type="交易类型,取值的JSAPI", body="商品描述", total_fee="订单总金额,单位为分", notify_url="微信支付成功回调", user_id=openid, out_trade_no="商户订单号", fee_type="默认CNY" | |
) | |
# 还有其他参数可以看源码 |
调用成功的情况下你会得到一个 dict,最主要是里面的 prepay_id 值,我们将 prepay_id 值再传递到 client 里进行二次加密,一定要再做二次加密,不然调用支付弹窗会失败,提示【unable to verify signature】
params = client.jsapi.get_jsapi_params(create_result["prepay_id"]) | |
# 加密成功后你会得到 params: {'appId': '123', 'timeStamp': '123', 'nonceStr': 'abc', 'package': 'prepay_id=123', 'signType': 'MD5', 'paySign': '123abc'} |
这是我们才能拿到正确的微信支付参数,然后我们将得到的 params 返回给前端进行调用
// 在微信浏览器中调用,没问题得到调用后会弹出微信支付的窗口,说明成功了 | |
// 但正常情况下你可能还是报错了,大概率提示【URL not registered http://www.xxx.com/xxx/xxx】,看下边 | |
WeixinJSBridge.invoke('getBrandWCPayRequest', | |
{ | |
appId: appId, | |
timeStamp: timeStamp, | |
nonceStr: nonceStr, | |
package: package, | |
signType: signType, | |
paySign: paySign | |
}, | |
function (res) { | |
if (res.err_msg == "get_brand_wcpay_request:ok") { | |
console.log("支付成功!") | |
} | |
} | |
) |
这是因为我们忘记配置支付授权目录了,也是你当前支付页面的路由地址
我们需要在微信商户平台的产品中心 -> 开发配置中,修改支付配置的 JSAPI 支付,在支付授权目录中添加你当前支付页的路劲
要注意,添加路劲时比如加上斜杠 “/” 结尾,所以我们在调用微信支付前还需要修改一下路劲,不然还是会一直提示你地址未注册
history.pushState(null, null, "/xxx/") |
那么基本上微信支付接口就没什么问题了,OK!