微信小程序支付 H5 拉起开发指引
1. 概述
当前支付组件已支持在小程序环境中正常运行。本场景中,客户在 微信内置浏览器(公众号 H5 页面) 内操作,需要通过微信 JS-SDK 的开放标签 wx-open-launch-weapp 在 H5 页面嵌入一个小程序跳转按钮,点击后直接拉起目标小程序并携带支付参数。
本指引适用于需要在微信浏览器内将 H5 页面支付流程改造为"H5 → 小程序支付"模式的技术团队。
2. 整体交互流程
(微信浏览器) participant Backend as 后端服务
(商户侧) participant MiniApp as 小程序端
支付页面 Note over H5,Backend: ① 预下单 H5->>Backend: 请求预下单 Backend-->>H5: 返回 pay_id Note over H5: ② 用户触发 H5->>H5: 用户点击「立即支付」按钮
(wx-open-launch-weapp) Note over H5,MiniApp: ③ 拉起小程序 H5->>MiniApp: wx-open-launch-weapp 拉起小程序
传入 path?pay_id= Note over MiniApp: ④ 完成支付 MiniApp->>Backend: 调用支付确认接口 Backend-->>MiniApp: 返回支付参数 MiniApp->>MiniApp: wx.requestPayment 调起支付面板
流程说明
① 预下单:H5 页面加载后,异步调用商户后端预下单接口。
② 返回参数:后端完成微信支付统一下单,向 H5 返回 pay_id。
③ 用户触发:H5 页面显示"微信支付"按钮(由 wx-open-launch-weapp 标签渲染),用户点击该按钮。
④ 拉起小程序:微信客户端拉起目标小程序,将拼接了 pay_id 的路径传递给小程序支付页面。
⑤ 完成支付:小程序接收参数后调起微信支付面板。
3. 前置条件
| 序号 | 条件 | 说明 |
|---|---|---|
| 1 | 已注册微信小程序 | 且已完成认证(个人主体不支持微信支付) |
| 2 | 已开通微信支付商户号 | 并与小程序 AppID 完成绑定 |
| 3 | 小程序已配置支付相关类目 | 在小程序管理后台确认 |
| 4 | 拥有已认证的公众号 | 用于在微信 JS-SDK 安全域名白名单中配置 H5 页面域名 |
| 5 | 公众号已绑定小程序 | 在公众号管理后台「小程序管理」中完成绑定 |
| 6 | 公众号 JS 接口安全域名已配置 | 登录公众号后台 → 设置 → 公众号设置 → 功能设置 → JS 接口安全域名 |
4. 支付组件调用参数
当前支付组件的核心调用参数如下:
| 参数名 | 值 | 说明 |
|---|---|---|
| app_id | wxa204074068ad40ef |
目标小程序的原始 ID(AppID),用于标识要拉起的小程序 |
| path | external/payment/trade/create/index |
小程序内目标支付页面的路径 |
| 参数传递 | pay_id = 调用预下单返回的 pay_id |
支付核心标识,作为 query 参数拼接在 path 后传递给小程序 |
参数拼接示例
path = external/payment/trade/create/index
query = ?pay_id={{pay_id}}
完整路径 = external/payment/trade/create/index?pay_id={{pay_id}}
其中 {{pay_id}} 为调用商户后端预下单接口后返回的真实支付凭证 ID。
5. 微信浏览器内拉起小程序方案
本方案采用 微信 JS-SDK 开放标签 wx-open-launch-weapp。这是微信官方提供的唯一能在微信内置浏览器中直接唤起小程序的方案。详细说明请参考微信官方文档:开放标签使用说明。
5.1 引入 JS-SDK
在 H5 页面中引入微信 JS-SDK(需使用 1.6.0 及以上版本),详见 微信 JS-SDK 官方文档:
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
5.2 获取 JS-SDK 签名并配置
页面加载后,先调用公众号后端签名接口获取参数,然后通过 wx.config 注入权限验证配置。签名生成算法详见微信官方文档:JS-SDK 签名算法:
// 第一步:调用后端签名接口(URL 必须为当前页面完整 URL,不含 # 部分)
fetch('/api/wx/sign?url=' + encodeURIComponent(location.href.split('#')[0]))
.then(res => res.json())
.then(data => {
// 第二步:配置 JS-SDK
wx.config({
debug: false, // 联调时可设为 true 观察签名校验日志
appId: data.appId, // 公众号的 AppID
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: ['launchWeapp'],
openTagList: ['wx-open-launch-weapp'] // 关键:声明开放标签列表
});
});
注意:
wx.config中的appId是公众号的 AppID,而wx-open-launch-weapp标签的appid属性是小程序的 AppID(gh_1bea46494b53),两者不同,请勿混淆。
5.3 嵌入开放标签
在 H5 页面中,将支付 pay_id 拼接到路径中,通过 wx-open-launch-weapp 标签渲染跳转按钮:
<wx-open-launch-weapp
id="launch-btn"
appid="wxa204074068ad40ef"
path="external/payment/trade/create/index?pay_id={{pay_id}}"
>
<template>
<style>
.payment-btn {
width: 260px;
height: 44px;
line-height: 44px;
background: #07c160;
color: #ffffff;
border: none;
border-radius: 22px;
font-size: 16px;
text-align: center;
display: inline-block;
}
</style>
<button class="payment-btn">微信支付</button>
</template>
</wx-open-launch-weapp>
属性说明
| 属性 | 必填 | 说明 |
|---|---|---|
appid |
是 | 目标小程序的 AppID(原始 ID),即 gh_1bea46494b53 |
path |
是 | 小程序页面路径,需包含 query 参数,如 external/payment/trade/create/index?pay_id=xxx |
username |
否 | 小程序的原始 ID(gh_ 开头),与 appid 二选一;推荐使用 appid |
template |
是 | 按钮的 HTML 模板,可自定义样式和文案 |
5.4 监听事件(可选)
通过监听开放标签的 launch 和 error 事件来追踪跳转状态:
document.getElementById('launch-btn').addEventListener('launch', function () {
console.log('小程序已成功拉起');
});
document.getElementById('launch-btn').addEventListener('error', function (e) {
console.error('拉起小程序失败', e.detail);
});
6. 小程序端接收参数
在小程序的目标页面中,通过 onLoad 生命周期接收 H5 传递过来的 pay_id。调起支付的方法详见微信官方文档:wx.requestPayment:
// external/payment/trade/create/index.js
Page({
onLoad(options) {
const { pay_id } = options;
if (!pay_id) {
wx.showToast({ title: '支付参数异常', icon: 'none' });
return;
}
this.processPayment(pay_id);
},
processPayment(pay_id) {
// 根据 pay_id 发起支付
wx.request({
url: 'https://your-api.com/payment/confirm',
data: { pay_id },
success: (res) => {
const { package: pkg, nonceStr, paySign, signType } = res.data;
wx.requestPayment({
timeStamp: String(Date.now()),
nonceStr,
package: pkg,
signType: signType || 'MD5',
paySign,
success: () => { /* 支付成功处理 */ },
fail: () => { /* 支付失败处理 */ }
});
}
});
}
});
7. 接入步骤
步骤一:公众号配置
- 在公众号管理后台将 H5 域名加入 JS 接口安全域名
- 确保公众号已完成微信认证
步骤二:后端对接
- 实现 JS-SDK 签名接口:接收前端 URL,生成
timestamp、nonceStr、signature - 实现 预下单接口:调用微信支付统一下单 API,返回
pay_id
步骤三:H5 前端对接
- 在 H5 支付页面引入微信 JS-SDK(
jweixin-1.6.0.js) - 页面加载完成后,调用后端签名接口完成
wx.config配置 - 调用后端预下单接口获取
pay_id - 将
pay_id拼接到wx-open-launch-weapp的path属性中 - 渲染开放标签按钮,等待用户点击
步骤四:小程序端对接
- 在
external/payment/trade/create/index页面onLoad中解析pay_id - 调用后端支付确认接口获取支付参数
- 调用
wx.requestPayment调起微信支付面板 - 处理支付成功/失败的回调
步骤五:联调验证
- 确认
wx.config签名验证通过(可在 debug 模式下观察日志) - 确认开放标签正常渲染并点击后能拉起小程序
- 确认小程序正确接收
pay_id参数 - 确认支付流程完整跑通
8. 注意事项
- appid 区分:
wx.config的appId是公众号的 AppID;wx-open-launch-weapp的appid是小程序的 AppID(wxa204074068ad40ef),两者不同,注意不要填反 - 签名 URL 必须完整:生成签名的 URL 必须与当前页面 URL 完全一致(包括 query 参数),且不含 # 后面的部分
- 仅微信浏览器内有效:开放标签仅在微信内置浏览器中渲染和响应,在其他浏览器中不显示
- 路径格式:
path属性值不要以/开头(区别于 URL Scheme 写法),直接写路径即可,如external/payment/trade/create/index - 参数长度:
path+ query 总长度建议控制在 1024 字符以内 - 调试技巧:联调时将
wx.config的debug设为true,可在开发者工具中观察签名校验与标签注入结果 - JS-SDK 版本:务必使用
jweixin-1.6.0.js或更高版本,旧版本不支持开放标签 - iOS 兼容性:iOS 微信中,开放标签需用户主动点击触发,无法通过 JS 自动调用
9. 常见问题
Q1:wx-open-launch-weapp 按钮不显示怎么办?
排查方向:
- 确认
wx.config的openTagList中已添加"wx-open-launch-weapp" - 确认当前页面在微信内置浏览器中打开
- 确认 JS 接口安全域名已正确配置
- 在
debug: true下检查 JS-SDK 配置是否通过
Q2:点击按钮但未拉起小程序?
排查方向:
- 确认
appid属性值为小程序原始 ID(gh_1bea46494b53) - 确认公众号已绑定该小程序
- 确认
path路径格式正确(不以/开头) - 检查
wx.config的签名是否正确
Q3:小程序收不到 pay_id?
排查方向:
- 确认
path的 query 参数拼接格式是否正确:path?pay_id=xxx - 检查小程序
onLoad的options参数名是否为pay_id - 注意 query 参数中特殊字符需要 URL Encode
Q4:wx-open-launch-weapp 和 URL Link / URL Scheme 的区别?
| 对比项 | wx-open-launch-weapp | URL Link / URL Scheme |
|---|---|---|
| 适用环境 | 微信内置浏览器 | 系统浏览器 / 短信 / 邮件 |
| 用户体验 | 页面内嵌按钮,无缝衔接 | 需跳转或弹窗确认 |
| 技术门槛 | 需公众号绑定 + JS-SDK 签名 | 需服务器端生成链接 |
| 推荐场景 | 微信浏览器内首选 | 微信外使用 |