--- name: 小程序支付切换为虚拟支付接口 overview: 将小程序商城支付从普通微信支付(wx.requestPayment)切换为微信虚拟支付(wx.requestVirtualPayment),对接后端已实现好的 /order/virtual 虚拟支付下单接口。 todos: - id: mall-payment content: 改造 mall.ts:调整 OrderResult 类型、confirmPay 调用 /order/virtual 并上报 platform、doPayment 改用 wx.requestVirtualPayment status: completed - id: models-config content: 更新 types/models.ts 新增虚拟支付响应类型,并在 utils/config.ts 补充虚拟支付错误码文案 status: completed - id: mall-wxml content: 将 mall.wxml 支付按钮文案由“微信支付”改为“立即支付” status: completed --- ## 用户需求 后端已完成虚拟支付(微信小程序虚拟支付 / XPay)接口改造,现需将小程序前端支付流程从普通微信支付切换为虚拟支付接口。 ## 产品概述 将商城(额度与会员)下单支付链路从 `wx.requestPayment` 普通微信支付迁移到 `wx.requestVirtualPayment` 虚拟支付,对接后端新增的 `POST /api/v1/order/virtual` 下单接口,覆盖 iOS/Android 全终端虚拟商品支付。 ## 核心功能 - 商城下单时调用虚拟支付下单接口 `/order/virtual`,上报用户平台(android/ios/harmony/windows) - 使用后端返回的 `sign_data`、`pay_sig`、`signature` 调起 `wx.requestVirtualPayment`(道具直购模式) - 支付成功后保留原有额度与会员信息刷新逻辑 - 补充虚拟支付相关错误码的友好提示文案 - 调整支付按钮文案为“立即支付” ## 技术栈 - 前端框架:微信小程序原生 + TypeScript - 网络请求:复用现有 `miniprogram/utils/request.ts` 的 `request` 封装 - 支付 API:`wx.requestVirtualPayment`(基础库 2.19.2+,回调风格) ## 实现方案 ### 核心改造策略 将 `mall.ts` 中的下单与支付两段逻辑整体替换为虚拟支付链路: 1. 下单:`POST /order` → `POST /order/virtual`,请求体从 `{goods_code}` 扩展为 `{goods_code, platform}` 2. 调起支付:`wx.requestPayment` → `wx.requestVirtualPayment`,参数由 `pay_params` 改为 `sign_data/pay_sig/signature/mode` 3. 后端返回的 `sign_data` 已经是 JSON 字符串,必须原样透传,禁止再次 `JSON.stringify` ### 关键决策 - **mode 取值**:本项目会员/额度购买属于“道具直购”,官方文档中 mode 合法值为 `short_series_goods`(道具直购)与 `short_series_coin`(代币充值),因此使用 `short_series_goods`。 - **platform 归一化**:`wx.getDeviceInfo().platform` 可能返回 `devtools`/`mac` 等后端不接受的枚举值,需归一化为后端 `oneof=android|ios|harmony|windows` 之一;`devtools`/`mac` 等开发调试环境默认映射为 `android`(联调时按真机切换)。 - **错误提示**:后端虚拟支付错误码(70005/70006/70008/70009/79003/71004)尚未纳入前端 `ERROR_MESSAGES`,补充文案后 `request` 封装的自动 toast 可直接生效,无需额外处理。 - **向后兼容**:`types/models.ts` 中普通支付 `PayParams` 类型暂保留(避免影响其它引用),新增虚拟支付响应类型;`/order` 普通支付接口后端仍保留,但前端商城全量切换虚拟支付。 ### 实现要点(防回归) - `sign_data` 透传字符串,不做任何序列化/解析(签名基于服务端序列化结果,重序列化会导致 `-15016`/`-15005` 签名错误)。 - `wx.requestVirtualPayment` 不支持 Promise 风格,使用回调;`success` 仅表示支付页拉起成功,最终到账以后端发货推送为准,前端仍按现有逻辑刷新额度与用户信息。 - `confirmPay` 中先关闭订单弹窗再调起支付(保持现有交互),支付 `fail` 静默处理或轻提示,不重复弹订单框。 - platform 获取失败时回退 `android`,避免请求体缺失导致 400 参数校验失败。 ## 目录结构 本次为既有项目局部修改,涉及文件如下: ``` miniprogram/ ├── pages/ │ └── mall/ │ ├── mall.ts # [MODIFY] 核心改造:OrderResult 类型、confirmPay 下单、doPayment 调起虚拟支付、platform 归一化 │ └── mall.wxml # [MODIFY] 支付按钮文案“微信支付”→“立即支付” ├── types/ │ └── models.ts # [MODIFY] 新增虚拟支付下单响应类型 VirtualPayResult └── utils/ └── config.ts # [MODIFY] ERROR_MESSAGES 补充虚拟支付错误码文案 ```