集成微信支付技能
场景
让 AI 在小程序内帮用户完成微信支付全流程:下单、查询订单、关闭订单、退款、查询退款、商家转账、查询转账。用户只需说"帮我付 25 元买咖啡"或"查一下订单状态",AI 就能调用对应接口完成操作并展示结果卡片。
本文基于预置的 payment-skill 模板来快速集成微信支付能力:一键安装模板 → 配置商户凭证 → 部署上线,支付逻辑通过 HTTP 云函数处理。
前置条件
- 已完成 从头构建 AI 小程序,项目能在开发者工具中正常运行
- 小程序已开通 AI 开发模式(微信公众平台 → 基础功能 → AI 能力 → 接入模式选择「开发模式」)
- 微信开发者工具 Nightly 版 已安装
- Node.js ≥ 18
-
npx mp-skills --version可正常输出版本号 - 已开通微信支付商户号(商户平台 注册)
- 已开通云开发环境(微信公众平台 → 开发管理 → 云开发)
- 已准备好商户凭证(商户号、证书序列号、APIv3 密钥、商户私钥、微信支付公钥)
实现步骤
第 1 步:安装 payment-skill 模板
# 在项目根目录下执行
npx mp-skills add TencentCloudBase/awesome-miniprogram-skills --skill payment-skill
预期输出:
从 TencentCloudBase/awesome-miniprogram-skills 获取...
* 安装 Skill: payment-skill
* skills/payment-skill/
* skills/_shared/mp-skills-shared/
* 已记录版本
* 查看 skills/payment-skill/README.md 了解功能详情
[OK] 安装完成!
有 setup 脚本待执行,建议运行:
mp-skills setup
安装后获得的完整文件结构:
miniprogram/skills/payment-skill/
├── config.js # ⚡ 需配置:云函数名 + 环境 ID
├── cloudbaserc.json # ⚡ 需配置:部署凭证 + 环境变量
├── SKILL.md # ✅ 已就绪:技能描述(AI 引擎读此文件判断何时触发)
├── mcp.json # ✅ 已就绪:原子接口声明(7 个支付接口的参数和返回值)
├── index.js # ✅ 已就绪:入口(注册所有原子接口)
├── apis/ # ✅ 已就绪:原子接口实现
│ ├── createOrder.js # 创建订单 + 调起支付
│ ├── queryOrder.js # 查询订单
│ ├── closeOrder.js # 关闭订单
│ ├── refundOrder.js # 申请退款
│ ├── queryRefund.js # 查询退款
│ ├── transferMoney.js # 商家转账
│ └── queryTransfer.js # 查询转账
├── components/ # ✅ 已就绪:UI 组件
│ ├── payment-card/ # 支付结果卡片
│ ├── order-status-card/ # 订单状态卡片
│ ├── refund-card/ # 退款结果卡片
│ └── transfer-card/ # 转账结果卡片
├── cloudfunctions/ # ✅ 已就绪:后端云函数
│ └── pay-common/ # HTTP 云函数(微信支付 V3 服务)
└── utils/ # ✅ 已就绪:前端工具函数
├── util.js # 云函数调用封装
├── id.js # 单号生成
└── storage.js # 本地存储
💡 模板已包含完整的接口实现、UI 组件和云函数代码,你只需完成后续的凭证配置即可使用。
第 2 步:配置后端凭证
2.1 准备商户凭证
从 微信支付商户平台 获取以下凭证:
| 凭证 | 获取位置 | 格式 |
|---|---|---|
商户号 (merchantId) | 商户平台首页 | 10 位数字 |
证书序列号 (merchantSerialNumber) | 账户中心 → API 安全 → API 证书 | 40 位十六进制 |
APIv3 密钥 (apiV3Key) | 账户中心 → API 安全 → 设置 APIv3 密钥 | 32 字节字符串 |
商户私钥 (privateKey) | 申请证书时下载的 apiclient_key.pem | PEM 格式 |
微信支付公钥 (wxPayPublicKey) | 账户中心 → API 安全 → 微信支付公钥 | PEM 格式 |
公钥 ID (wxPayPublicKeyId) | 同上 | 与公钥配对 |
⚠️ 微信支付公钥 ≠ 商户 API 公钥。务必使用「微信支付公钥」,不是申请证书时生成的商户公钥。
2.2 完善 cloudbaserc.json
打开 miniprogram/skills/payment-skill/cloudbaserc.json,将所有占位符替换为你的实际值:
{
"version": "2.0",
"envId": "你的云开发环境ID",
"functions": [
{
"name": "pay-common",
"type": "http",
"timeout": 30,
"runtime": "Nodejs18.15",
"handler": "index.main",
"memorySize": 256,
"installDependency": true,
"dir": "cloudfunctions/pay-common",
"envVariables": {
"signMode": "sdk",
"appId": "你的小程序AppID",
"merchantId": "你的商户号",
"merchantSerialNumber": "你的证书序列号",
"apiV3Key": "你的APIv3密钥",
"privateKey": "-----BEGIN PRIVATE KEY-----\\nMIIEvgIBA...\\n-----END PRIVATE KEY-----",
"wxPayPublicKey": "-----BEGIN PUBLIC KEY-----\\nMIIBIjAN...\\n-----END PUBLIC KEY-----",
"wxPayPublicKeyId": "你的微信支付公钥ID",
"notifyURLPayURL": "https://<envId>.service.tcloudbase.com/pay-common/wx-pay/unifiedOrderTrigger",
"notifyURLRefundsURL": "https://<envId>.service.tcloudbase.com/pay-common/wx-pay/refundTrigger",
"transferNotifyUrl": "https://<envId>.service.tcloudbase.com/pay-common/wx-pay/transferTrigger"
}
}
],
"database": {
"collections": [
{
"name": "payment_records",
"description": "支付记录",
"indexes": [
{
"field": "openid",
"unique": false
},
{
"field": "orderId",
"unique": false
},
{
"field": "outTradeNo",
"unique": false
}
],
"aclTag": "PRIVATE"
},
{
"name": "refund_records",
"description": "退款记录",
"indexes": [
{
"field": "openid",
"unique": false
},
{
"field": "outRefundNo",
"unique": false
},
{
"field": "outTradeNo",
"unique": false
}
],
"aclTag": "PRIVATE"
},
{
"name": "transfer_records",
"description": "转账记录",
"indexes": [
{
"field": "openid",
"unique": false
},
{
"field": "outBillNo",
"unique": false
}
],
"aclTag": "PRIVATE"
}
]
}
}
关键配置说明:
| 字段 | 说明 |
|---|---|
envId | 你的云开发环境 ID |
signMode | sdk(自验签,推荐)或 gateway(集成中心代验签) |
privateKey | 将 PEM 文件换行替换为 \n(字面两个字符),写成一行 |
notifyURLPayURL | 支付回调 URL,必须填写部署后的实际完整地址 |
notifyURLRefundsURL | 退款回调 URL |
transferNotifyUrl | 转账回调 URL |
回调 URL 格式规则:
https://<envId>.service.tcloudbase.com/<函数名>/wx-pay/<路由>示例:
https://test-wxpay-5gy4ugzreef15cfe.service.tcloudbase.com/pay-common/wx-pay/unifiedOrderTrigger
2.3 完善 config.js
打开 miniprogram/skills/payment-skill/config.js,填入与 cloudbaserc.json 一致的值:
module.exports = {
// 云函数名称(须与 cloudbaserc.json 中 functions 里的 name 一致)
functionName: "pay-common",
// 云开发环境 ID(须与 cloudbaserc.json 中的 envId 一致)
envId: "",
};
⚠️ 小程序运行时无法读取 JSON 文件,所以
config.js需要与cloudbaserc.json手动保持同步。如果修改了cloudbaserc.json中的函数名或环境 ID,请同步更新此文件。
第 3 步:一键部署后端
npx mp-skills setup
mp-skills setup 自动完成:
| 步骤 | 说明 |
|---|---|
| 合并配置 | Skill 级 cloudbaserc.json → 项目级 |
| 安装依赖 | cloudfunctions/pay-common/ 的 npm 包 |
| 部署云函数 | 部署为 HTTP 云函数 |
| 创建数据库 | 自动创建 payment_records、refund_records、transfer_records 集合及索引 |
部署完成后,需要在 云开发控制台 → 云函数 → pay-common → HTTP 触发 中将以下回调路径设为免鉴权:
/wx-pay/unifiedOrderTrigger(支付回调)/wx-pay/refundTrigger(退款回调)/wx-pay/transferTrigger(转账回调)
微信支付服务器直接调用回调路径,无法携带鉴权 token,必须免鉴权。安全由内部签名验证保证。
第 4 步:validate 校验
npx mp-skills validate
预期输出:
[OK] 项目配置检查通过
[OK] 接口定义与实现一致
[OK] 原子组件定义完整
如果校验失败,检查以下常见问题:
mcp.json的接口名与index.js注册名不一致componentPath指向的组件文件不存在cloudbaserc.json中回调 URL 包含模板变量未替换
第 5 步:在开发者工具中验证
# macOS
/Applications/wechatwebdevtools.app/Contents/MacOS/cli open --project /your/path/to/my-ai-app
# Windows
"C:\Program Files (x86)\Tencent\微信web开发者工具\cli.bat" open --project "D:\...\my-ai-app"
在开发者工具中:
- 基础库版本切换到 3.16.1 或以上
- 编译模式切换到「小程序 AI 编译」
- 左侧 SKILL 列表中应出现
payment-skill - 选中后右侧显示 7 个原子接口
- 测试
createOrder:填入{"description": "咖啡", "totalFee": 100}执行 - 查看返回的支付结果卡片渲染效果
验证清单
-
npx mp-skills validate全部通过 -
npx mp-skills setup部署成功,云函数状态正常 - 回调路由已设为免鉴权
- 开发者工具中
createOrder可正常调起微信支付(或预览模式返回 mock) - 支付成功后
payment-card组件正确渲染 -
queryOrder/closeOrder/refundOrder/queryRefund/transferMoney/queryTransfer接口可正常调用 - 各结果卡片(order-status-card、refund-card、transfer-card)正确展示
-
mcp.json声明与index.js注册名一致 -
config.js与cloudbaserc.json的 envId、functionName 保持一致
支付架构
关键设计决策:
| 决策 | 选择 | 理由 |
|---|---|---|
| 支付是否走云函数 | 是,通过 HTTP 云函数 | 支付涉及密钥签名,必须在后端处理。前端通过 wx.cloud.callHTTPFunction 调用,平台自动鉴权 |
| openid 获取方式 | 后端自动从 header 获取 | wx.cloud.callHTTPFunction 自动注入 x-wx-openid,无需前端传递,避免伪造 |
| 金额来源 | Demo 演示从前端传入 | 生产环境必须从后端数据库获取,禁止信任前端金额 |
| 回调验签 | signMode: sdk 自验签 | 无需依赖外部服务,云函数独立完成验签 + 解密 |
| 结果展示 | 4 种自定义卡片组件 | 支付场景需要丰富的状态展示(金额、状态图标、操作按钮) |
业务约束(跨接口铁律)
1. 执行顺序
refundOrder必须在queryOrder确认订单为 SUCCESS 状态后调用closeOrder必须在queryOrder确认订单为 NOTPAY 状态后调用- 禁止并发调用支付接口;须等上一笔结束后再发起下一笔
2. 数据来源
outTradeNo必须来自createOrder返回的原值,禁止编造outRefundNo必须来自refundOrder返回的原值,禁止编造outBillNo必须来自transferMoney返回的原值,禁止编造
3. 金额处理
- 所有金额单位为分(如 1 元 = 100 分)
- 退款金额不能超过订单总金额
- 转账金额范围:0.3 元(30 分)~ 2000 元(200000 分)
4. 安全约束
- 后端通过
wx.cloud.callHTTPFunction调用,平台自动鉴权 payer.openid由后端自动获取,前端无需传递- 禁止在前端硬编码任何密钥或证书信息
常见问题
报错 "当前环境不支持 wx.cloud.callHTTPFunction"?
- 确认基础库版本 >= 3.15.1
- 已在
app.js中调用wx.cloud.init() - 使用真机调试或体验版(非模拟器)
支付总是返回 mock 数据?
检查 mp_skills_preview_mode 是否为 true,以及后端云函数是否已部署。切换方式:
// 开启预览模式
wx.setStorageSync("mp_skills_preview_mode", true);
// 关闭预览模式(使用真实支付)
wx.setStorageSync("mp_skills_preview_mode", false);
退款报错 "订单状态不允许退款"?
只有 SUCCESS(已支付)状态的订单才能退款:
NOTPAY→ 使用closeOrder关闭SUCCESS→ 使用refundOrder退款CLOSED→ 已关闭,无法操作
商家转账有什么限制?
- 单笔:0.3 元 ~ 2000 元
- 需在商户平台开通「商家转账到零钱」功能
- 用户需在微信确认收款
如何在生产环境使用?
- 关闭预览模式
- 金额从后端获取(禁止前端直传金额)
- 配置好回调 URL(必须是实际部署后的完整地址)
- 确保无密钥暴露在前端
- 回调处理需实现幂等逻辑
config.js 和 cloudbaserc.json 的区别?
| 文件 | 用途 | 运行时 |
|---|---|---|
cloudbaserc.json | 云开发 CLI 部署用,包含完整凭证 | 仅部署时使用 |
config.js | 小程序端运行时配置 | 小程序运行时 require |
两者的 functionName 和 envId 必须保持一致。