微信小程序虚拟支付接入实战
深入解析微信虚拟支付与普通 V3 微信支付的核心区别,覆盖商户资质、道具直购模式、签名参数、发货通知确认与异步退款全链路实战。
我从早期微信支付对接,到新版的 V3 支付,最近一次提审被驳回,审核原因是支付方式不合规,这才下决心接入虚拟支付功能。现在微信小程序对于虚拟产品的支付有明确的要求:必须走小程序虚拟支付。
支付接入最怕的不是功能接入本身,而是确认机制——推送会丢、回调会丢,只有加入幂等兜底才能保证链路严谨闭环。
这次把支付发起、支付确认、退款三套链路全部切换到了虚拟支付(道具直购模式),整个过程踩了不少坑。如果你也在小程序里卖会员、订阅、课程、道具这类虚拟商品,这篇文章应该能帮你少走弯路。
虚拟支付和微信V3支付的区别
先说结论:虚拟支付和普通微信支付,不是换个 API 那么简单,而是接入的机制都变了。
- 支付发起方式不同:普通微信支付是服务端预下单,拿到预支付单号,客户端再拉起支付。而虚拟支付反过来:服务端不下单,只负责生成签名参数,客户端拉起时微信侧才真正下单。
- 支付结果确认方式不同:普通微信支付靠回调通知 + 对账轮询确认结果。而虚拟支付多了一层"确认发货":虚拟商品由开发者发货,微信要确认"你真的发货了"订单才算闭环。支付成功后微信推送发货通知,服务端确认发货;推送丢了,靠轮询查订单状态兜底。
- 退款方式不一样:普通微信支付退款是同步接口,调一次就知道结果。而虚拟支付是异步的,发起后微信异步处理,退款结果通过推送通知你。而且苹果支付无法通过微信接口进行退款,要到苹果官网申请,并且有非常长的审核过程。
- 费率大幅提升:普通微信支付需要单独注册商户号,通常只需要 0.6% 到 1% 左右。而虚拟支付将收取技术服务费:标准费率 10%,iOS 端标准费更高,达 12%,腾讯技术服务费 5%(暂时 2026 年减免)。

接入实战
01 先确认三件事
开始接入前,先准备三件事情,避免开发完了才知道无法上线。
- 资质:需要在小程序 PC 管理端单独申请开通资质,官方写的审核周期 1-7 个工作日,我实际提交后 1 个小时就通过了,但建议尽早提交。
- 道具模式:虚拟支付分道具直购、代币充值等几种模式。需要明确自己产品的支付类型,因为对接的接口大不相同。
- 基础库版本:这个最简单了,确保一下基础库就行。客户端支付接口
wx.requestVirtualPayment要求基础库 2.19.2 以上。

商户资质申请比较简单,直接管理平台直接操作即可。
02 功能改造
微信 V3 支付还需要保留,其他端还需要调用,所以需要多支付方式兼容,总体架构如下:

虚拟支付整体上还是这条路线:发起 → 确认 → 退款。
1)发起准备:
后端新增下单准备接口(校验定价、生成签名参数),前端换成 wx.requestVirtualPayment 拉起。签名是这环节的核心,细节看官方《签名详解》。大概的流程为:按固定字段序序列化 signData(offerId/buyQuantity/env/currencyType/productId/goodsPrice/outTradeNo/attach),计算 paySig/signature 后返回客户端原样透传;客户端以 wx.requestVirtualPayment 拉起。
注意该客户端接口有非常多的错误码,一定要在小程序端做友好的错误映射(下图的错误码不全,请到官网查询):

2)支付确认:

这里的消息推送是 MP 后台配置的消息推送,建议使用安全模式加密传输:接收入口强制解密校验,无有效密文或解密失败一律响应失败,不进入业务处理。和 V3 支付中直接配置开发者服务器的回调接口不同,这要明确区分开。
3)退款:

一句话总结:发起时判重防重复退款,确认以推送为主、管理端再次操作为兜底。
03 沙箱联调
先将道具或者代币配置好开发版本。可以在沙箱环境测试,测试无误后可发布现网。
同时切记不要在沙箱环境测试通过之后,直接上线生产环境。因为 iOS 端比较特殊,部分场景沙箱环境都是绕过的,建议上了生产之后,还需要灰度测试一轮。
执行过程中的坑
以下都是我趟过的坑,这些还是在已经有成熟框架代码的情况下碰到的,如果从零开始只会更多。
01 订单号是一次性的
我在微信 V3 支付里,用户重复下单时习惯复用还没支付的旧订单号;虚拟支付反过来——每个订单号只能用一次。取消或失败后重试,必须新建订单,复用旧单号会直接报错(-15002)。
如果你原来的下单逻辑里有「复用旧订单」的优化,虚拟支付要单独绕开,每次都新建。代码实现不难,就是用户每次唤起一次支付,后端就有一条待支付的订单,只能等定时器,将其关闭。
02 支付确认别只靠推送
这是我最想强调的一点。微信的推送不是 100% 可靠的:推送丢了,服务端收不到通知,用户钱付了权益没有生效,这就是事故。
所以一定要有轮询兜底:定时扫待支付订单,查状态,发现已支付就补上激活和发货确认。推送和轮询共用同一个幂等入口,同一笔订单只会激活一次。

03 iOS 订单不能主动退款
退款还有一个渠道的坑:iOS 端走的是 Apple 支付,这类订单开发者无法主动退款,只能引导用户去 App Store 申请。所以 iOS 订单和微信渠道订单要分开处理,别用同一套退款逻辑。
设计退款时,很容易下意识照搬支付确认的轮询思路:推送会丢,退款结果也会丢,那也来一套?想清楚后发现:不需要。
支付是用户侧发起,服务端无法替付,推送丢了只能轮询;退款可以从管理端单点发起、完全可控,推送丢了再操作一次、查一下状态就能收敛。多一套轮询只是增加复杂度,没有任何收益。
04 沙箱测试不是免费的
很多人以为沙箱是免费的模拟环境,实际上沙箱也会真实扣款,只是免了服务费。尤其 iOS 端走 Apple 支付,用开发者工具扫码测试时,苹果手机直接扣款成功。所以测试前先改好价格,再进行测试。
05 配置生效时间
在商户后台改了道具(最常见的是改价格)之后,微信侧要等约 10 分钟才生效。这期间唤起支付会报错。改了配置别急着测,等 10 分钟再试,否则容易误判成代码问题。
还有后端虚拟产品的价格还要道具配置的价格一致,不然也会支付报错。
最后
这次改造给我最大的感受是:虚拟支付不是普通微信支付的升级版,而是一套全新的机制。而且受到的限制非常多,远没有 V3 支付来得简单。最关键的是服务费涨得太多了,看来还是没干得过 Apple。
以上只是我在实际项目里的接入经验总结,不代表官方规则承诺。涉及虚拟支付资质、道具配置、费率、审核要求等,最终还是要以微信官方文档为准。
小程序系列精选阅读
如果你对小程序开发系列文章感兴趣,可以浏览我的更多专题文章。


