# 虚拟支付:个人
为进一步支持个人开发者实现可持续经营,激发个人主体的创新活力,微信小程序平台将在符合条件的类目范围内,向个人主体小程序开放虚拟支付能力。
# 一、agent 自动接入(以下两种方式均可)
方式一:复制下方提示词,发给开发小程序的Agent:
阅读接入指引,并完成个人主体小程序的虚拟支付接入: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/virtual-payment/person 最后按文末「部署前检查清单」逐项验收。
方式二: 安装SKILL并完成接入
# 二、开通条件
| 条件 | 说明 |
|---|---|
| 个人主体 | 小程序主体为个人,开发者持有居民身份证 |
| 服务类目 | 小程序服务类目含「工具」 |
| 认证与备案 | 已完成小程序认证、备案 |
限额:个人主体小程序月支付限额为 10 万元。
# 三、开通流程
打开浏览器,登录微信开放平台,按下面步骤操作:
左侧栏找到并点击【支付与交易 - 虚拟支付】

点击【开通】→ 勾选同意协议 → 填写个人资料(个人身份信息、提现账户、支付管理员)

提交后等待审核,一般为5分钟内
刷新页面、确认审核通过后,扫码签约
# 开通后:记下这 3 个关键信息
| 信息 | 它是什么 | 在哪找 |
|---|---|---|
| AppID | 小程序的「身份证号」 | MP 后台 → 设置 |
| OfferID | 你的支付账号 | 虚拟支付 → 基本配置 |
| 现网AppKey | 支付密钥 | 虚拟支付 → 基本配置 |
同时,需在【道具管理】里创建你的商品(道具),记下道具 ID 和价格(这就是你卖的「商品」),并完成发布。
# 开通小程序 iOS 支付
如需在 iOS 端使用支付,还需配置小程序简称(Apple 支付需展示 display name)。配置入口:mp.weixin.qq.com → 虚拟支付 → 基础配置,详见配置小程序简称。
配置后,可在 虚拟支付 → 基本配置中开通苹果IAP支付。
# 四、开发接入
# 4.1 虚拟支付与现有业务流程串接
你的小程序已有业务流程(登录 → 选择功能 → 使用)。虚拟支付只是把「收钱」这个环节接入进来:
用户打开小程序 → 登录 → 选择要购买的功能/道具 → 点击「购买」
↓
① 前端请求服务器下单 → 服务器生成唯一单号 outTradeNo,保存订单(状态:待支付)
↓
② 服务器返回 payData → 前端调用 wx.requestVirtualPayment 拉起支付
↓
③ 支付成功后,服务器通过两条路径确认并完成发货:
路径 A:收到平台「发货推送」→ 直接发货
路径 B:推送丢失时,定时调用 query_order 查单 → 查到已支付就补发货
↓
④ 前端查询自己服务器的订单状态 → 展示「购买成功」并开放权益
关键点:
outTradeNo:商家自己生成的业务单号,下单时必填,须唯一wx_order_id:平台返回的单号,跟踪订单、发货、对账以此为准- 发货以「发货推送」为主,推送丢失时用
query_order查单兜底;前端支付回调不作为发货依据
# 4.2 整体流程:道具直购
用户点购买
→ 小程序调用 wx.requestVirtualPayment(带签名,拉起支付)
→ 支付成功
→ 平台向你的服务器推送 xpay_goods_deliver_notify(发货推送)
→ 服务器校验签名 + 幂等 → 给用户发货 → 返回 <xml><ErrCode>0</ErrCode></xml>
→(可选兜底)前端 success 回调 + 服务器定时 query_order 查单补发
术语:「发货推送」= 支付成功后平台自动通知你的服务器发货;「幂等」= 同一订单重复通知也只发一次货;「签名」= 防伪校验,防止伪造订单。
# 4.3 前端接入:小程序端
调用基础库接口 wx.requestVirtualPayment(签名 = 防伪校验,防止伪造订单),示例:
// 需要后端先返回一个签名后的 payData
function buyGoods(payData) {
wx.requestVirtualPayment({
// payData 由你的服务器生成并签名后返回(见 4.5)
...payData,
success(res) {
// 支付成功(可能丢失,不能作为唯一发货依据)
wx.showToast({ title: '支付成功' });
},
fail(err) {
wx.showToast({ title: '支付失败', icon: 'none' });
}
});
}
// 页面内购买按钮:先请求自己服务器获取 payData,再调用 buyGoods
iOS 版本限制:iOS 端需使用微信客户端 8.0.68 及以上版本。调用支付前需先校验,版本不满足时提示用户更新微信至最新版:
// 购买前校验(iOS 需微信 ≥ 8.0.68)
function checkIosVersion() {
const sys = wx.getSystemInfoSync();
if (sys.platform !== 'ios') return true; // 非 iOS 直接放行
const cur = sys.version.split('.').map(Number); // 当前微信版本
const base = [8, 0, 68]; // 最低要求
for (let i = 0; i < 3; i++) {
if ((cur[i] || 0) > base[i]) return true;
if ((cur[i] || 0) < base[i]) break;
}
wx.showModal({ title: '提示', content: '请将微信更新至最新版后再进行支付', showCancel: false });
return false;
}
// 购买入口:校验通过后才允许下单支付
function onBuy() {
if (!checkIosVersion()) return;
// ...请求服务器获取 payData,再调用 buyGoods
}
payData 核心字段(由服务器按签名规则生成,见 4.5):
| 字段 | 说明 |
|---|---|
| signData | 以下支付参数拼成的 JSON 字符串(服务器生成): |
| ├ offerId | OfferID(虚拟支付商户号) |
| ├ buyQuantity | 购买数量 |
| ├ env | 环境标识,固定填 0 |
| ├ currencyType | 币种,固定填 CNY |
| ├ productId | 道具 ID |
| ├ goodsPrice | 道具单价(分),需与后台道具价格一致 |
| ├ outTradeNo | 业务单号(必填,须唯一,如 T + 时间戳 + 随机数) |
| └ attach | 透传数据(必填,发货时原样透传) |
| mode | 固定 short_series_goods(道具直购) |
| paySig | 服务器用 AppKey 对 requestVirtualPayment&signData 做 HMAC-SHA256 |
| signature | 服务器用 sessionKey 对 signData 做 HMAC-SHA256(用户态签名) |
# 4.4 服务端接入
# 4.4.1 接收发货推送
消息推送接收部署:支付成功后,平台会把发货推送回调到你的服务器,需要先部署「消息推送接收」能力。使用腾讯云开发时,可借助微信开发者工具「Skills」自动完成该部分的部署与配置,无需开发者手动操作;其余服务端逻辑(下单、查单、发货)由 Agent 完成代码实现。
在 MP 后台【虚拟支付 → 基本配置 → 基础配置 → 发货推送配置】填你的服务器 URL。支付成功后平台推送 XML 到该 URL。
推送核心字段:
| 字段 | 说明 |
|---|---|
| Event | 固定 xpay_goods_deliver_notify |
| OpenId | 用户 openid(确定发货给谁) |
| OutTradeNo | 商家下单时传入的业务单号 |
| WeChatPayInfo.MchOrderNo | 平台单号 wx_order_id(跟踪订单、幂等去重,以此为准) |
| GoodsInfo.ProductId | 道具 ID |
| GoodsInfo.Quantity | 购买数量(按数量发放) |
服务器处理逻辑:
- 收到推送,解析 XML,取平台单号
wx_order_id(位于WeChatPayInfo.MchOrderNo字段) - 幂等(同一订单重复通知只发一次货):查本地订单表,若该 wx_order_id 已发货则直接返回成功
- 发货:根据
OpenId和道具 ID,给对应用户发放对应数量,更新订单状态 - 返回
0表示成功,否则平台会重试(最多 15 次)
<xml><ErrCode>0</ErrCode><ErrMsg><![CDATA[success]]></ErrMsg></xml>
# 4.4.2 查询订单(兜底发货)
接口:POST /xpay/query_order(带 pay_sig 签名),请求示例:
{
"openid": "用户openid",
"env": 0,
"order_id": "业务订单号 outTradeNo"
}
用于:推送丢失时主动查单补发货,建议定时每 5 分钟查一次,查到已支付就发货。
# 4.4.3 服务端接口清单
| 接口 | 作用 |
|---|---|
POST /pay/order | 生成 outTradeNo + signData + paySig,返回给前端去支付 |
POST /pay/notify | 接收发货推送,验签后发货,返回 XML |
POST /pay/query | 转发调用 query_order,供兜底查单 |
# 4.5 签名算法(两套签名)
# 支付签名 paySig(服务端算,AppKey 是密钥)
import hmac, hashlib
def calc_pay_sig(uri, post_body, appkey):
"""uri 不带问号参数。
- C 端(wx.requestVirtualPayment 下单):uri 固定为 requestVirtualPayment
- B 端(服务端 /xpay/* 接口):uri 为实际接口路径,如 /xpay/query_order
"""
msg = uri + '&' + post_body # post_body 是真正发出去的原始字符串
return hmac.new(appkey.encode('utf-8'), msg.encode('utf-8'),
hashlib.sha256).hexdigest()
# 用户态签名 signature(服务端算,sessionKey 是密钥)
def calc_signature(post_body, session_key):
return hmac.new(session_key.encode('utf-8'), post_body.encode('utf-8'),
hashlib.sha256).hexdigest()
# 五、退款、结算与订单查询
# 5.1 退款
| 终端 | 退款方式 | 说明 |
|---|---|---|
| Android 等 | 开发者主动退款 | 在 MP 后台【虚拟支付 → 交易订单】操作退款,或用 refund_order 接口发起;退款完成后收到 xpay_refund_notify 推送 |
| iOS | 用户向 App Store 申请 | 开发者无法主动退款;用户申请后由 Apple 决定,退款成功收到 xpay_refund_notify |
手续费规则:支付时间 180 天以内的退款,平台退还手续费;超过 180 天的退款,平台不退还手续费。
# 5.2 结算
| 终端 | 结算周期 | 费率 | 说明 |
|---|---|---|---|
| Android 等 | T+3 | 1% | 腾讯技术服务费 |
| iOS | 约 45-60 天 | 12% | Apple 佣金 |
提现:资金到账后,可在 MP 后台【虚拟支付】查看账户余额、每日账单并发起提现。
发票:可在次月 5 号后申请开具上个月的腾讯技术服务费发票。
# 5.3 订单查询
- 页面查询:MP 后台【虚拟支付 → 交易订单】,可按支付渠道切换「普通支付 / Apple 支付」
- 接口查询:
query_order(见 4.4.2),可用于核对订单与退款状态
# 六、Agent 注意事项
- 用户告知:向用户确认开放条件(个人主体、工具类目、认证备案)与月支付限额 10 万元,并说明退款、结算与费率规则(见第五节)。
- 接入范围:只做道具直购,不引入代币等额外功能。
- outTradeNo:每次下单重新生成、保证唯一(8-32 位,不能以下划线开头),不能复用。
- 签名:严格按 4.5 节实现;
post_body必须与实际请求体完全一致(不格式化、不改键顺序);appkey用正式 AppKey;sessionKey通过auth.code2Session获取。 - 发货:以
wx_order_id做幂等去重;success回调可能丢失(用户异常退出会丢),以「发货推送」为主、query_order查单兜底。 - 金额与 env:金额单位是「分」,全程不要换算;
env固定填0(正式环境/现网)。
# 七、部署前检查清单
- [ ] 开放条件确认:个人主体 + 中国大陆居民身份证 + 服务类目为「工具」+ 已完成认证、备案
- [ ] 已了解并告知用户:全终端月支付限额为 10 万元
- [ ] MP 后台虚拟支付已开通
- [ ] 已拿到 AppID / OfferID / 现网AppKey
- [ ] 若需 iOS 支付:已配置小程序简称
- [ ] 消息推送接收已部署(腾讯云开发可用开发者工具 Skills 自动完成)
- [ ] MP 后台已配置发货推送 URL,并完成一笔测试支付验证
- [ ] 服务器验签逻辑通过(签名函数与官方文档签名示例核对一致)
- [ ] 发货推送已做幂等(以 wx_order_id 去重)
- [ ] 前端 wx.requestVirtualPayment 打通,支付成功并收到发货推送
- [ ] 兜底查单逻辑已就绪(query_order)
- [ ] 已向用户说明退款规则、结算周期与费率(Android 1%、iOS 12%)
- [ ] 上线后用小额真单验证:支付 → 推送 → 发货 → 后台账单金额一致