从零做微信小程序(8):虚拟支付实战,从下单到发货的完整链路

9次阅读
没有评论

虚拟支付真正难的不是把按钮调起来,而是支付成功后,会员、帖子和道具能不能准确发到用户账户。这篇把下单、双签名、回调发货、幂等和审核表单压缩成一条完整链路。

lifetruth.top

一、支付成功不是发货成功

虚拟商品的交付发生在数据库里。完整链路应该是:创建业务订单、生成支付参数、拉起支付、接收结果、校验回调、发放权益、记录发货状态。

会员需要写入有效期,帖子解锁需要写入用户与帖子关系,道具需要增加数量。前端看到支付成功,只能更新界面,不能直接开通权限。

支付成功只说明钱到了,发货成功才说明业务完成。

但商品必须先有清晰的权益定义,否则即使接口正常,系统也不知道该发什么。

二、下单和双签名

下单时前端只传商品 ID,云函数根据商品表读取价格、权益类型和有效期,再生成订单。订单至少保存用户 ID、商品 ID、订单号、金额、支付状态和发货状态。

`paySig` 和 `signature` 是两类签名。前者通常由 AppKey 参与 HMAC-SHA256,后者使用登录会话对应的 `session_key`。它们都只能在云函数生成,不能把密钥放进小程序前端。

const paySig = HMAC_SHA256(appKey, payString);
const signature = HMAC_SHA256(sessionKey, signString);
return { paySig, signature };

字段拼接顺序、时间戳和参数名必须以当前官方文档为准,不要照抄旧示例。

三、调用支付和接收回调

页面向云函数请求支付参数,再调用 `wx.requestVirtualPayment`。安卓和 iOS 由平台按运行环境路由,业务代码不需要根据手机型号写两套发货逻辑。

const params = await getPayParams(orderId);
wx.requestVirtualPayment({
  ...params,
  success: () => queryOrder(orderId),
  fail: () => showPayFailed()
});

真正的发货入口是服务端收到 `virtualPayNotify`。云函数先验证通知、订单号、金额和商品 ID,再把订单标记为已支付,最后执行会员开通或帖子解锁。

回调可能延迟、重复或乱序,所以应当记录原始通知、处理结果和失败原因。

四、幂等和到账轮询

幂等就是同一件事重复来几次,结果只能算一次。回调处理前先查订单:已发货就直接返回成功;已支付但未发货就继续补发;订单不存在则拒绝处理。

解锁关系可以用“用户 ID + 帖子 ID”去重,避免重复支付或重复回调生成多条解锁记录。

支付返回后可以短时间轮询订单状态,给迟到的回调留出时间;轮询结束仍未到账,就把订单放入待补偿列表。轮询是兜底,不是替代服务端回调。

五、提审表单怎么填

订单中心 path 要填写用户能查看订单状态和权益结果的页面,不要只填支付按钮所在的首页。测试账号要能完成“进入商品页—支付—回到订单中心—看到已发货权益”的完整路径。

如果需要特殊权限,在备注里写清测试商品、操作步骤和预期结果。审核人员看到的页面、后台商品名称和提审说明必须一致。

▸ 小贴士:提审前准备一张表,列出测试账号、商品 ID、订单中心 path、支付后权益和异常联系人。

写在最后

虚拟支付不是把支付按钮换成新的 API,而是把订单、签名、回调、发货、幂等和补偿连成可验证的链路。

如果你接下来要接入虚拟支付,先画订单状态图,再写代码:待支付、已支付、发货中、已发货和待补偿,每个状态都说明谁能修改。

你更担心回调收不到,还是担心回调重复后把权益发多次?


「小程序实战路线图」

执迷者X聚焦真实业务闭环:从小程序开发、云函数与支付,到订单、权益和自动化流程,把每一次交易都落到可验证、可追溯的产品能力上。

你现在在第 08 篇:虚拟支付全链路。支付规则还不清楚,先看第 07 篇:为什么虚拟商品不能走普通微信支付;涉及权益与联系方式解锁时,再衔接第 10 篇:隐私与变现的平衡,以及第 11 篇:云开发数据库建模。

如果你正在把预约、服务展示、支付、内容权益或信息撮合做成小程序,可通过 联系页 说明当前业务、目标用户和最想先跑通的一条链路。

正文完
 0
评论(没有评论)