uni-app 平台接入 · 微信支付配置说明
面向 uni-app 多端(微信小程序 / 微信内 H5 / 普通 H5 / App / PC 扫码)的微信支付配置保姆级说明:讲清为什么会有这么多 AppID 与 openid、五端配置矩阵、微信与商户后台操作步骤、常见报错排查。
版本:V1.0
更新日期:2026-09-14
对应基础库:reglow 0.4.5(Python / Node.js / Java / Rust 四语言一致)
适用场景:用 uni-app(含 uni-app x / uvue)开发的应用接入微信支付,一个后端要同时服务小程序、微信内 H5、普通 H5、App、PC 扫码多端。
读者假设:没接触过微信支付,或接过一次但被 AppID / openid 绕晕过。
确定性说明:文中微信后台的菜单名、报错提示语与错误码会随微信改版而变化,实际以微信官方后台与官方文档为准;代码、接口与配置项部分对本仓库(reglow 0.4.5)是确定的。
写在前面:一个大白话故事
一句话总结:
复杂的是微信的规则,不是我们的代码。 好消息是:Reglow 基础库已经把这些规则吸收掉了 —— 业务侧只需要说清楚「我现在跑在哪个端」,剩下的 AppID 选择、接口选择、openid 换取,全部由库里自动处理。
目录
一、先搞懂:为什么会有这么多 AppID 和 openid
1.1 三张工牌:三个互相独立的应用实体
微信生态里,公众号、小程序、移动应用是三个独立的应用,各自申请、各自审核、各自有一个 AppID。它们不是"同一个东西的三种形态"。
| 配置项 | 对应实体 | 申请入口 | 我们用它做什么 |
|---|---|---|---|
wechat_app_id | 公众号(服务号) | mp.weixin.qq.com | 微信内置浏览器里打开你的 H5 时,用公众号 JSAPI 拉起支付;以及网页授权换 openid |
wechat_mini_app_id | 小程序 | mp.weixin.qq.com(小程序后台) | 小程序内拉起支付;wx.login → jscode2session 换 openid |
wechat_app_app_id | 开放平台·移动应用 | open.weixin.qq.com | 自研 App 里拉起微信 App 支付(移动应用没有 AppSecret,App 支付也不需要 openid) |
不要试图只配一个 AppID 打通所有端。微信支付 V3 在下单时会校验
appid与payer.openid的同源性,也会校验 AppID 是否已关联到该商户号;混用会被微信拒绝。
1.2 openid 是「用户 × 应用」的身份证
openid 不是用户的微信号,而是「某个微信用户,在某一个应用里的编号」。
同一个人的 openid:
| 场景 | 值 |
|---|---|
| 在你的公众号里 | oXa...A1 |
| 在你的小程序里 | oYb...B2(和上面不一样) |
| 在你的 App 里(走开放平台) | App 支付不需要 openid |
所以两种 openid 的获取方式、以及能用在哪种下单接口上,是绑定死的:
| openid 来源 | 获取方式 | 用于哪种下单 |
|---|---|---|
| 小程序 openid | 小程序 wx.login() 拿 code → 后端调 sns/jscode2session(用小程序 AppID + 小程序 AppSecret) | 只能用小程序 AppID 下 JSAPI 单 |
| 公众号 openid | 用户在微信里打开 H5 → 静默网页授权(snsapi_base)→ 后端用 code 调 sns/oauth2/access_token(用公众号 AppID + 公众号 AppSecret) | 只能用公众号 AppID 下 JSAPI 单 |
| App 支付 | —— | 不需要 openid,用移动应用 AppID 下 APP 单 |
为什么小程序不需要网页授权,而微信内 H5 需要? 因为小程序内有 wx.login() 这个原生能力,可以直接拿到 code 交给后端换 openid;而浏览器页面没有这个能力,只能借道「网页授权」——先整页跳到微信、用户授权后带着 code 跳回来。这就是微信内 H5 比小程序「多一次跳转」的根本原因。
这正是「appid 和 openid 不匹配」这类报错的根本原因。 库内部已经按「端」自动挑对了 AppID(见第二章矩阵表),业务代码不需要手动传 AppID。
想要打通同一个用户? 只有把公众号、小程序、移动应用都绑定到同一个微信开放平台账号下,才会多出一个跨应用共享的 unionid。但注意:
unionid只解决「这是同一个人」,不解决「用哪个 AppID 下单」。下单仍然必须用对应端自己的 AppID。
1.3 商户号与证书:收钱的那一端
AppID 解决「谁在调用」,商户号解决「钱进哪里」。
| 配置项 | 是什么 | 从哪里拿 |
|---|---|---|
wechat_mch_id | 微信支付商户号(收款主体) | 微信支付商户平台 → 账户中心 → 商户信息 |
wechat_api_v3_key | APIv3 密钥,用于解密回调数据 | 商户平台 → 账户中心 → API 安全 → APIv3 密钥(自己设置,务必留存) |
wechat_serial_no | 商户 API 证书序列号 | 商户平台 → 账户中心 → API 安全 → API 证书(下载证书后可见) |
wechat_private_key | 商户私钥(apiclient_key.pem 的内容) | 同上,随证书一起下载 |
wechat_notify_url | 支付回调地址(微信支付成功后通知你的服务器) | 你自己的公网 HTTPS 地址,如 https://api.example.com/api/v1/payment/wechat/notify |
1.4 那 11 个配置项,到底谁在用
后端的支付配置分组是 payment,在后台「运营 → 系统设置 → 支付设置」里维护。逐项的"用途 / 什么时候必须填"如下:
| 配置项(key) | 用途 | 谁来消费 |
|---|---|---|
wechat_enabled | 是否启用微信支付渠道 | 库:选择当前生效渠道 |
wechat_app_id | 公众号 AppID | 微信内 H5(JSAPI)、网页授权 |
wechat_app_secret | 公众号 AppSecret | 网页授权 code 换 openid |
wechat_mini_app_id | 小程序 AppID | 小程序支付;也用于生成小程序码 |
wechat_mini_app_secret | 小程序 AppSecret | jscode2session 换 openid、取 access_token 生成小程序码 |
wechat_app_app_id | 开放平台移动应用 AppID | App 端微信支付 |
wechat_mch_id | 商户号 | 各端通用(下单必填) |
wechat_serial_no | 商户证书序列号 | 各端通用(请求签名) |
wechat_private_key | 商户私钥 | 各端通用(请求签名) |
wechat_api_v3_key | APIv3 密钥 | 各端通用(回调验签解密) |
wechat_notify_url | 回调地址 | 各端通用(可选,但强烈建议填:接收支付结果) |
只做某几端时,未用到的项可以不填。 下表里的「基础四项」指
wechat_mch_id、wechat_serial_no、wechat_private_key(下单签名必需)、wechat_api_v3_key(回调验签解密必需):
只做这个端 必须填 可以不填 PC 扫码( web)基础四项 + 公众号 AppID 两个 AppSecret、 wechat_app_app_id微信小程序( miniapp)基础四项 + wechat_mini_app_id+wechat_mini_app_secretwechat_app_id/wechat_app_secret、wechat_app_app_id微信内 H5( mpweb)基础四项 + wechat_app_id+wechat_app_secretwechat_mini_app_id/wechat_mini_app_secret、wechat_app_app_id普通浏览器 H5( h5)基础四项 + wechat_app_id两个 AppSecret、 wechat_app_app_idApp( app)基础四项 + wechat_app_app_idwechat_app_id、两个 AppSecret
wechat_notify_url强烈建议填:不填微信无法回调,支付结果只能靠前端轮询兜底,线上会延迟入账甚至漏入账。wechat_enabled要在后台打开(渠道开关)。- 多个端都要做时,取各端并集即可。
关于兜底:库对
miniapp有「小程序 AppID 未配则回退公众号 AppID」的逻辑,对web扫码也有「公众号 AppID 未配则回退小程序 AppID」的逻辑。两处兜底互相独立,都只是防止初始化直接报错;一旦回退后 openid 与 AppID 不同源,微信会拒绝下单。所以生产环境请把用到的 AppID 全部配齐 —— 小程序端一定要填小程序 AppID 与 AppSecret。
1.5 名词速查(看不懂就回来查)
| 名词 | 一句话解释 |
|---|---|
| AppID | 一个微信应用的唯一标识(公众号 / 小程序 / 移动应用各有一个) |
| AppSecret | 该应用的密钥,只在服务端使用,用于换 openid、换 access_token |
| openid | 「某个用户 × 某个应用」的唯一编号;同一人在不同应用下 openid 不同 |
| unionid | 同一用户在同一开放平台账号下多个应用间的共享编号(只解决「是同一人」,不解决「用哪个 AppID 下单」) |
| JSAPI | 微信支付的一种下单方式,用于小程序和微信内置浏览器里拉起支付面板 |
| prepay_id | 微信下单成功后返回的「预支付交易会话标识」,前端拉起支付必用 |
| pay_params | 后端返回的「拉起支付所需参数集合」:小程序 / 公众号给 timeStamp nonceStr package signType paySign;App 给一组 orderInfo 字段 |
| qr_code | Native 下单返回的二维码链接,PC 端渲染成二维码供扫码 |
| h5_url | H5 下单返回的收银台地址,普通手机浏览器直接跳转过去 |
| WeixinJSBridge | 微信客户端注入到内置浏览器里的桥,公众号 JSAPI 靠它拉起支付 |
| access_token | 微信应用的「接口调用凭证」(微信侧有效期约 2 小时),库已做单点缓存 |
| scene(场景值) | 生成小程序码时携带的短参数,扫码进入小程序后可读到(上限 32 字符) |
| ICP 备案 | 中国大陆网站必须完成的域名备案;微信的网页授权域名、H5 支付域名都要求已备案 |
| 内网穿透 | 把本地服务临时映射成公网地址,用于让微信服务器能回调到你的开发机 |
| X-Forwarded-For | 反向代理透传「真实客户端 IP」的请求头;H5 支付下单必须带真实 IP |
| 幂等 | 同一操作执行多次与执行一次结果相同(支付回调重复触发时只入账一次) |
二、五端配置矩阵与对照表
2.1 一张表看懂五端差异
业务侧只需要告诉后端「我现在跑在哪个端」——这个值就是 platform。AppID 由库按 platform 自动选,前端不许也不需要传 AppID。
| 端 | platform | 微信下单接口 | 用哪个 AppID 下单 | 需要 openid? | 前端调起方式 | 后端返回 |
|---|---|---|---|---|---|---|
| PC / 桌面浏览器 | web | /v3/pay/transactions/native | 公众号 AppID(未配则回退小程序) | 否 | 页面渲染二维码,轮询支付状态 | qr_code |
| 微信小程序 | miniapp | /v3/pay/transactions/jsapi | 小程序 AppID(必须配,见下方说明) | 需要(小程序 openid) | uni.requestPayment({provider:'wxpay', ...}) | pay_params |
| 微信内置浏览器(H5) | mpweb | /v3/pay/transactions/jsapi | 公众号 AppID | 需要(公众号 openid) | WeixinJSBridge.invoke('getBrandWCPayRequest') | pay_params |
| 手机普通浏览器(H5) | h5 | /v3/pay/transactions/h5 | 公众号 AppID | 否(但要客户端 IP) | 跳转 h5_url,回跳后查单 | pay_params.h5_url |
| 原生 App(iOS/Android) | app | /v3/pay/transactions/app | 开放平台移动应用 AppID | 不需要 | uni.requestPayment({provider:'wxpay', orderInfo}) | pay_params |
三个必须知道的"反常点":
- 小程序和公众号用的是同一个微信接口(
/v3/pay/transactions/jsapi),区别只在appid与openid的来源必须配对。 - 微信内置浏览器里不能用 H5 支付(
platform=h5)。微信会拦截,提示「请到微信外打开」。微信内必须走mpweb。 - App 支付不需要 openid,这是五端里最简单的一环。
2.2 前端怎么判定当前端
项目已封装好,不要在页面里自己写判断。见 common/utils/pay.uts:
判定规则:编译期按平台裁剪(MP-WEIXIN / APP-ANDROID / APP-IOS / WEB),H5 端再用 UA 判断是否微信内置浏览器(UA 含 MicroMessenger)。
2.3 前端标准调用流程
五端流程统一为三步,差异全部被工具函数吃掉了:
invokeWechatPay 内部对各端的处理:
| platform | 内部动作 |
|---|---|
miniapp | uni.requestPayment({provider:'wxpay', timeStamp, nonceStr, package, signType, paySign}) |
mpweb | WeixinJSBridge.invoke('getBrandWCPayRequest', {appId, timeStamp, nonceStr, package, signType, paySign})(桥未注入时会重试) |
app | uni.requestPayment({provider:'wxpay', orderInfo:{appid, partnerid, prepayid, package, noncestr, timestamp, sign}}) |
h5 | window.location.href = pay_params.h5_url |
web | 不适用(请用二维码 + 轮询) |
微信内 H5 首次支付需要点两次:第一次点击会跳转到微信授权页换取 openid,回跳后 openid 已缓存,再点一次即正常拉起支付。 授权在同一浏览器、且本地缓存未被清除的前提下只会发生一次(openid 存在本地 Key
K_WX_OPENID);换设备、换浏览器或清缓存后会重新授权一次。
2.4 后端接口清单
| 接口 | 方法 | 用途 | 公开 |
|---|---|---|---|
/api/v1/payment/orders | POST | 创建支付订单(通用,含 platform / openid) | 是 |
/api/v1/payment/orders/{id}/status | GET | 查询支付单状态(前端轮询用) | 是 |
/api/v1/payment/wechat/notify | POST | 微信支付结果回调(微信服务器调用) | 是 |
/api/v1/payment/wechat/oauth-url | GET | 取公众号网页授权跳转 URL | 是 |
/api/v1/payment/wechat/openid | GET | 网页授权 code 换 openid | 是 |
/api/v1/wechat/miniapp/openid | POST | 小程序 code 换 openid(jscode2session) | 是 |
/api/v1/wechat/miniapp/qrcode | POST | 生成小程序码(邀请海报等用) | 是 |
/api/v1/orders/{id}/pay | POST | 业务侧:为打印订单发起支付 | 需登录 |
/api/v1/credits/recharge | POST | 业务侧:积分充值下单 | 需登录 |
三、微信 + 商户后台配置步骤(保姆级)
所有后台菜单名以微信官方后台实际显示为准(微信会改版)。下面给的是大致路径 + 你要得到什么。 建议按 3.6 的推荐顺序操作,能显著减少来回返工。
3.1 商户平台(微信支付)——先把"收钱的地方"建好
打开 pay.weixin.qq.com,用商户号登录。
| 步骤 | 菜单路径(大致) | 你要拿到 / 填什么 |
|---|---|---|
| 1 | 账户中心 → 商户信息 | 复制 商户号 → 后台 wechat_mch_id |
| 2 | 账户中心 → API 安全 → APIv3 密钥 | 自己设置一个 32 位密钥并妥善保存 → 后台 wechat_api_v3_key |
| 3 | 账户中心 → API 安全 → API 证书 | 申请/下载证书 → 得到 证书序列号 与 apiclient_key.pem 内容 → 后台 wechat_serial_no / wechat_private_key |
| 4 | 产品中心 → 开通产品 | 按需开通:JSAPI 支付(小程序/微信内 H5)、H5 支付(普通浏览器)、Native 支付(PC 扫码)、APP 支付 |
| 5 | 产品中心 → AppID 账号管理 | 把 公众号 AppID / 小程序 AppID / 移动应用 AppID 逐个「关联」到本商户号 |
| 6 | 产品中心 → 开发配置 | 配置 JSAPI 支付授权目录(微信内 H5 页面所在目录)、H5 支付域名(需 ICP 备案) |
| 7 | (自定义)回调地址 | 无需在商户平台预先登记:V3 接口的回调地址随下单请求传递(即后端填的 wechat_notify_url) |
第 5 步是「appid 和 mch_id 不匹配」最直接的解法:AppID 没关联商户号,下单会失败。 第 3 步的私钥与序列号必须成对:序列号对不上私钥,会报签名错误。
3.2 公众号(负责"微信内 H5")
打开 mp.weixin.qq.com,用公众号管理员登录。
| 步骤 | 菜单路径(大致) | 你要拿到 / 填什么 |
|---|---|---|
| 1 | 设置与开发 → 基本配置 | 复制 AppID → 后台 wechat_app_id;生成/重置 AppSecret → 后台 wechat_app_secret |
| 2 | 设置与开发 → 公众号设置 → 功能设置 → 网页授权域名 | 填你的 H5 站点域名(如 h5.example.com),并按要求把校验文件放到域名根目录 |
| 3 | 设置与开发 → 公众号设置 → 功能设置 → JS 接口安全域名(可选) | 只有使用微信 JS-SDK 时才需要填;本项目用 WeixinJSBridge 拉起支付,不依赖此项 |
| 4 | 设置与开发 → 公众号设置 → 功能设置 → 确认「接口权限」 | 网页授权能力通常要求已认证的服务号(订阅号一般没有);以该页实际显示的权限为准 |
第 2 步是「redirect_uri 域名与后台配置不一致(10003)」最直接的解法。 注意:网页授权域名只填域名,不带路径、不带端口,且必须是已备案的 HTTPS 域名。
3.3 小程序(负责"小程序内支付")
打开小程序后台(mp.weixin.qq.com,切换到小程序)。
| 步骤 | 菜单路径(大致) | 你要拿到 / 填什么 |
|---|---|---|
| 1 | 开发 → 开发管理 → 开发设置 | 复制 AppID → 后台 wechat_mini_app_id;生成 AppSecret → 后台 wechat_mini_app_secret |
| 2 | 开发 → 开发管理 → 开发设置 → 服务器域名 | request 合法域名填后端 API 域名;downloadFile 合法域名填图片 CDN 域名(生成/展示小程序码、海报时要用) |
| 3 | 设置 → 基本设置 | 确认小程序类目允许支付;小程序需已完成认证 |
| 4 | —— | 小程序支付不需要配置网页授权域名(那是公众号侧的事) |
小程序
AppSecret只在服务端使用(换 openid、换access_token),绝不能写进前端代码。manifest.json里的mp-weixin.appid只需填 AppID(不是 AppSecret)。
3.4 开放平台·移动应用(负责"App 内支付")
打开 open.weixin.qq.com,用开放平台账号登录。
| 步骤 | 菜单路径(大致) | 你要拿到 / 填什么 |
|---|---|---|
| 1 | 管理中心 → 移动应用 → 创建/详情 | 复制 AppID → 后台 wechat_app_app_id |
| 2 | 应用详情 → 开发信息 | Android:填包名 + 应用签名(用微信官方「签名生成工具」取,必须是正式签名包) |
| 3 | 应用详情 → 开发信息 | iOS:填 Bundle ID,并配置 Universal Links |
| 4 | 确认已开通 | 在应用详情确认微信支付能力已开通(未开通需先申请) |
包名/签名填错是 App 支付的常见失败原因,且报错信息往往很含糊。务必用正式打包的 APK 取签名。 iOS 还需在
manifest.json里配置微信支付的appid与 Universal Links。
3.5 配置核对清单(可勾选)
商户平台
- 商户号已复制到
wechat_mch_id - APIv3 密钥已设置并填入
wechat_api_v3_key - 证书已下载,序列号填入
wechat_serial_no,私钥内容填入wechat_private_key - 已开通所需支付产品(JSAPI / H5 / Native / APP)
- 公众号 / 小程序 / 移动应用 AppID 已逐一关联到本商户号
- JSAPI 支付授权目录已配置(微信内 H5 用)
- H5 支付域名已配置(普通浏览器 H5 用,域名需备案)
公众号
-
wechat_app_id/wechat_app_secret已填 - 网页授权域名已配置(H5 站点域名)
- 公众号为服务号且已认证
小程序
-
wechat_mini_app_id/wechat_mini_app_secret已填 - request / downloadFile 合法域名已配置
-
manifest.json中小程序 appid 已填
移动应用
-
wechat_app_app_id已填 - Android 包名 + 签名 / iOS Bundle ID + Universal Links 已填
服务器
-
wechat_notify_url为公网可访问的 HTTPS 地址 - H5 站点为 HTTPS + 已备案域名
- 反向代理已正确透传
X-Forwarded-For(H5 支付要用真实客户端 IP) - 后端已重启,加载最新库版本
3.6 推荐的配置顺序
顺序反了会怎样:先配前端、后关联 AppID,你会一直以为是代码问题,其实是商户号没关联。
四、常见报错排查清单
4.1 下单阶段
| 报错关键词(微信返回) | 根因 | 处置 |
|---|---|---|
appid和openid不匹配 | 下单用的 AppID 与 openid 来源不是同一个应用(如拿公众号 openid 用小程序 AppID 下单) | 确认前端 platform 传对了:小程序 miniapp、微信内 H5 mpweb。库 0.4.5 已按 platform 自动选 AppID |
appid和mch_id不匹配 / APPID_MCHID_NOT_MATCH | 该 AppID 未关联到商户号 | 商户平台 → 产品中心 → AppID 账号管理,关联对应 AppID |
商户号该产品权限未开通 / NOAUTH | 未开通对应支付产品 | 商户平台 → 产品中心,开通 JSAPI / H5 / Native / APP 支付 |
签名错误 / SIGN_ERROR | 私钥与证书序列号不配对,或 APIv3 密钥错 | 重新核对 wechat_serial_no + wechat_private_key;确认没有多余换行/空格 |
微信小程序未配置 | 缺 wechat_mini_app_id 或 wechat_mini_app_secret | 后台支付设置补齐这两项(小程序端必需) |
| 金额相关报错 | 微信金额单位是分,不是元 | 后端传 amount_cents(¥15 → 1500) |
小程序支付需要 openid | platform=miniapp 但没带 openid | 前端先调 preparePayOpenid("miniapp") 再下单 |
4.2 调起阶段
| 报错关键词 | 根因 | 处置 |
|---|---|---|
当前页面的URL未注册 | 微信内 H5 的页面目录不在「JSAPI 支付授权目录」内 | 商户平台 → 产品中心 → 开发配置,把 H5 页面所在目录加入授权目录(填目录,不是完整 URL;注意层级与末尾斜杠) |
redirect_uri 域名与后台配置不一致(10003) | 网页授权域名未配置或不一致 | 公众号后台配置「网页授权域名」= H5 站点域名;前端会自动带授权域名校验 |
请在微信客户端打开链接 | 在非微信浏览器里尝试公众号 JSAPI 支付 | 普通浏览器应走 h5(H5 支付),不该走 mpweb |
请到微信外打开 | 在微信内浏览器里用了 H5 支付(h5) | 微信内必须用 mpweb(JSAPI)。库已按 UA 自动区分 |
微信支付未就绪,请在微信中重新打开本页 | WeixinJSBridge 未注入(页面刚加载就被调用,或不在微信内) | 正常会自动重试 10 次;若持续出现,确认确实在微信内打开 |
| 支付时弹出空白页 / 白屏 | 网页授权整页跳转被拦截,或 redirect_uri 域名未备案 | 使用 HTTPS + 已备案域名;确认授权域名与访问域名一致 |
total_fee / 金额校验失败 | 前后端金额不一致(尤其积分抵扣场景) | 金额一律由后端计算,前端只展示 |
4.3 回调与到账阶段
| 现象 | 根因 | 处置 |
|---|---|---|
| 微信支付成功,但订单仍是「待支付」 | 回调地址不可达,或验签/解密失败 | 确认 wechat_notify_url 公网 HTTPS 可访问;确认 wechat_api_v3_key 正确;查看后端日志 |
| 回调重复触发 | 微信在未收到成功响应时会重试 | 库已做幂等(同一支付单只入账一次),无需额外处理 |
| 微信返回「商户回调地址不是 HTTPS」 | 回调地址用了 http | 换成 HTTPS |
| 支付成功但页面没跳成功态 | 前端未做状态确认 | 小程序/App 在 requestPayment 成功后要调业务「确认支付」接口;H5 回跳后由 resumePendingPay 自动确认 |
4.4 小程序码 / access_token
| 现象 | 根因 | 处置 |
|---|---|---|
获取微信 access_token 失败 40001/40014 | token 被其它程序刷新顶掉了 | 库已做单点缓存(按 appid 加锁),不要在任何业务代码里自行获取 token |
生成小程序码失败 invalid ip | 小程序后台开启了 IP 白名单 | 小程序后台 → 开发管理 → 开发设置 → IP 白名单,加入服务器公网出口 IP |
| 小程序码图片为空 | 场景值超长 | scene 上限 32 字符,库会自动截断 |
五、联调验证:按这个顺序自测
按「从简单到复杂」的顺序,每步都能独立验证,避免多端问题混在一起排查。
| 顺序 | 验证端 | 怎么测 | 通过标准 |
|---|---|---|---|
| 1 | PC 扫码(web) | 后台填好支付设置 → 后端重启 → PC 打开下单页 → 选微信支付 | 页面出现二维码;用手机微信扫码支付成功;PC 页面状态变为已支付 |
| 2 | 小程序(miniapp) | 微信开发者工具打开小程序 → 下单 → 选微信支付 | 直接弹出微信支付面板(不跳授权页);支付后订单变已支付 |
| 3 | App(app) | 真机装上正式签名包 → 下单 → 选微信支付 | 拉起微信 App 完成支付,回到 App 显示成功 |
| 4 | 微信内 H5(mpweb) | 微信里打开 H5 站点 → 下单 → 选微信支付(第 1 次) | 跳转微信授权页并自动回跳;提示「微信授权成功,请重新发起支付」 |
| 5 | 同上(第 2 次) | 再点一次支付 | 直接弹出微信支付面板,不再跳授权页 |
| 6 | 普通浏览器 H5(h5) | 手机自带浏览器(非微信)打开 H5 → 下单 | 跳转到微信 H5 收银台完成支付;返回 H5 后自动确认订单状态 |
第 1 步不通,先别测其它端。扫码链路最短,建议先用它暴露商户号、证书、回调地址这类配置问题。
本地开发时,微信服务器无法回调
localhost:请用内网穿透把本地端口暴露成公网 HTTPS,再把wechat_notify_url指向它。
附录 A:本仓库代码与接口速查
A.1 前端(uni-app / uvue)
| 文件 | 作用 |
|---|---|
common/utils/pay.uts | 微信支付多端统一封装:端判定、openid 准备、调起支付、支付单轮询、H5 回跳恢复 |
common/api/payment.uts | 支付相关 API:fetchWechatMiniappOpenid、fetchWechatOauthUrl、fetchWechatOpenidByCode、fetchPaymentOrderStatus、fetchMiniappQrcode |
common/config.uts | 存储 Key:K_WX_OPENID(公众号 openid 缓存)、K_PENDING_PAY(H5 回跳恢复用) |
env.d.ts | WeixinJSBridge 全局声明(微信客户端注入的公众号 JSAPI 桥) |
common/utils/pay.uts 对外导出:
| 导出 | 说明 |
|---|---|
PAY_MINIAPP / PAY_MPWEB / PAY_H5 / PAY_APP / PAY_WEB | platform 常量,避免手写字符串 |
resolvePayPlatform() | 当前端 → platform |
isWechatBrowser() | 是否微信内置浏览器(仅 WEB 有意义) |
needPayOpenid(platform) | 该端是否需要先准备 openid |
preparePayOpenid(platform) | 准备 openid(小程序 wx.login / 微信内 H5 网页授权) |
invokeWechatPay(platform, params) | 调起支付(五端差异在此收敛) |
startPayPolling(id, onPaid, onClosed) / stopPayPolling() | 支付单轮询(扫码、H5 用) |
savePendingPay() / takePendingPay() | H5 跳转支付回跳后的恢复 |
handleWechatOauthCallback(query) | 在页面 onLoad 调用,处理公众号授权回跳 |
A.2 后端(Reglow 基础库)
| 位置 | 作用 |
|---|---|
reglow/core/payment.py(Python) | 微信支付 Provider:Native / JSAPI / H5 / APP 下单、签名、回调验签 |
reglow/core/wechat.py(Python) | 微信基础能力:jscode2session、get_miniapp_access_token(单点缓存)、get_miniapp_qrcode |
reglow/modules/wechat/ | 公开接口:POST /wechat/miniapp/openid、POST /wechat/miniapp/qrcode |
reglow/modules/payment/ | 支付单:创建订单、查状态、回调 |
Node.js / Java / Rust 版库提供了同名同语义的能力,接口路径与
platform取值完全一致,四语言可互换。
附录 B:十条铁律
- 三张工牌各管一摊,不要试图用一个 AppID 打通所有端。
- openid 与 AppID 必须同源,且三张工牌都要先在商户平台关联。
- AppID 与 AppSecret 只在服务端使用,AppSecret 绝不进前端代码。
- AppID 不需要前端传,前端只传
platform,选哪个 AppID 是后端的事。 - 微信内浏览器只能用 JSAPI(
mpweb),H5 支付(h5)只在微信外的浏览器可用。 - 金额单位是分,且金额一律由后端计算。
- 回调地址必须公网 HTTPS,本地开发用内网穿透。
- access_token 全库单点缓存,业务代码不要自己获取。
- 先配商务后台,再配代码;很多"代码问题"其实是 AppID 没关联。
- 按 PC 扫码 → 小程序 → App → 微信内 H5 → 普通 H5 的顺序联调,一次只排查一个变量。
