编程 微信小程序虚拟支付接入实战:机制差异与踩坑记录

2026-08-26 15:40:22 views 11

微信小程序虚拟支付接入实战:机制差异与踩坑记录

最近在给小程序接入虚拟支付(道具直购模式),把支付发起、支付确认、退款三条链路从头到尾切换了一遍。由于之前一直用的是微信 V3 支付,这次改造过程中踩了不少坑。如果你也在小程序里卖会员、课程、订阅或游戏道具,这篇文章应该能帮你省掉一些弯路。

先说明一下接入背景:小程序虚拟商品(虚拟支付)有明确合规要求,不能继续用普通微信支付。审核被拒之后,只能老老实实接虚拟支付。下面主要聊两件事——虚拟支付和 V3 支付的机制差异,以及实际接入中容易踩的坑。

虚拟支付和 V3 支付的区别

简单说:这不是换一套 API 的问题,而是整个支付确认机制都变了。

  1. 下单方向反过来了
    V3 支付是服务端预下单,拿到预支付单号后再由客户端拉起支付。虚拟支付正好相反:服务端不做下单,只生成签名参数,客户端调用 wx.requestVirtualPayment 时,微信侧才真正创建订单。

  2. 支付确认多了一层“确认发货”
    V3 支付靠回调通知 + 对账轮询基本就能闭环。虚拟支付不同:支付成功后微信推送“发货通知”,服务端收到后要确认发货(即确认权益已发放),微信才会认为订单最终完成。如果推送丢了,必须靠轮询订单状态来兜底。

  3. 退款是异步的,而且 iOS 退款走不了微信接口
    V3 支付退款是同步接口,调一次就知道结果。虚拟支付退款是异步发起,结果通过推送通知。还有更麻烦的:iOS 端订单走的是 Apple 支付,开发者无法通过微信接口退款,只能引导用户走苹果官方渠道,审核周期非常长。

  4. 费率差距明显
    虚拟支付需要单独申请开通资质,收费模式是技术服务费:标准费率 10%,iOS 端标准费 12%(腾讯技术服务费 5%,2026 年前有减免)。相比普通微信支付 0.6%~1% 的费率,成本压力不小。

接入前需要确认的三件事

  • 资质开通:需要在小程序 PC 管理端单独申请虚拟支付资质。官方说审核周期 1~7 个工作日,我提交后 1 小时就过了,但建议提前申请,避免卡在最后一步。
  • 支付模式:虚拟支付有道具直购、代币充值等多种模式。不同模式接口差异很大,务必先确认自己属于哪一种。
  • 基础库版本:客户端支付接口 wx.requestVirtualPayment 要求基础库 2.19.2 以上,确保线上环境符合要求。

功能改造

由于其他端还在用微信 V3 支付,所以需要多支付方式兼容。整体链路依然是:发起 → 确认 → 退款

发起

服务端新增“下单准备”接口,负责校验定价和生成签名参数,前端改为 wx.requestVirtualPayment 拉起。签名的核心是严格按官方《签名详解》来:把 offerId / buyQuantity / env / currencyType / productId / goodsPrice / outTradeNo / attach 按固定字段序序列化,计算 paySigsignature 后原样透传给客户端。

这里有个提示:客户端接口的错误码非常多,建议在小程序端做一层友好的错误映射,别让用户直接看到冷冰冰的错误码。

支付确认

虚拟支付的推送走的是 MP 后台配置的“消息推送”,和 V3 支付的开发者服务器回调不是一回事。建议使用安全模式加密传输:接收时强制解密校验,无有效密文或解密失败直接返回失败,不要进入业务处理。这样可以避免伪造消息触发发货逻辑。

退款

退款的原则简单概括:发起时判重,确认以推送为主,管理端手动操作为兜底。不要为退款也设计一套轮询,原因后面会细说。

沙箱测试

沙箱环境需要在后台先配置好道具或代币的开发版本,然后就可以在小程序开发者工具中测试。注意:沙箱环境也会真实扣款,只是不收取服务费。而且 iOS 端部分场景会绕过沙箱直接走 Apple 支付——我测试时用开发者工具扫码,苹果手机直接就扣款成功了。所以测试之前一定先把价格改对,上线后还要再做一轮灰度验证。

踩坑清单

以下是实际开发中遇到的几个比较典型的问题,供参考。

1. 订单号只能用一次

在 V3 支付里,用户取消或支付失败后,我习惯复用旧订单号。但虚拟支付不行:每个订单号只能使用一次,复用旧单号会直接报错(-15002)。所以每次用户唤起支付都必须新建订单,后端会多出一些待支付的脏数据,只能靠定时任务去关闭。

2. 支付确认不能只依赖推送

这是最需要强调的。微信推送不是 100% 可靠——推送一旦丢失,服务端收不到通知,用户钱付了但权益没到账,这就是事故。所以一定要加轮询兜底:定时扫待支付订单,主动查订单状态,发现已支付就补激活和确认发货。前提是推送和轮询走同一个幂等入口,确保同一笔订单只会激活一次。

3. iOS 订单不能主动退款

Android/微信渠道的订单可以走微信退款接口,但 iOS 订单走的是 Apple 支付,开发者无法主动退款,只能引导用户去 App Store 申请。所以退款逻辑必须按渠道分开处理,千万别用同一套逻辑。

另外,退款不需要像支付确认那样做轮询。支付是用户侧发起的,服务端控制不了,推送丢了只能轮询;退款是管理端单点发起,完全可控,推送丢了重发一次或查一下状态就能收敛。多一套轮询只会增加复杂度。

4. 沙箱扣款不是免费的

很多人以为沙箱就是纯模拟环境,实际上沙箱环境会真实从账户扣款,只是免了服务费。尤其是 iOS 端,用开发者工具扫码测试时,苹果手机直接扣款。所以测试前一定要调整好道具价格。

5. 配置生效有延迟

在商户后台修改道具信息(最常见的是改价格),微信侧大约需要 10 分钟才生效。在此期间唤起支付会直接报错。所以改了配置后别急着测,等 10 分钟再操作,否则容易误以为是代码问题。

另外,后端写的虚拟商品价格必须和后台配置的道具价格完全一致,否则支付同样会报错。

总结

这次改造最大的体感是:虚拟支付不是普通微信支付的升级版,而是一套独立的支付机制。限制多、规则严,费用也高出不少。接入时最核心的就是把“确认”这件事想清楚:推送不可靠,就加轮询兜底;退款可控,就不要过度设计。

以上仅代表个人项目中的接入经验,不构成官方承诺。有关虚拟支付资质、道具配置、费率、审核要求等,最终以微信官方文档为准。

复制全文 生成海报 微信小程序 虚拟支付 支付接入 踩坑

推荐文章

程序员茄子在线接单