# 服务号网页 1 元支付 本模块用于 `public/wcs/pay.html` 的微信公众号网页支付,与原有 `src/api/pay` 并行。原 `ProductPayLoginWeb`、`ProductPayNotifyWebchatService` 等接口继续保留,网页入口 改用 `src/api/wechatServicePay` 下的新接口。 该页面在微信内置浏览器中使用普通 JSAPI 支付。Android 和 iOS 使用相同服务端接口, 不使用小程序虚拟支付 `requestVirtualPayment`。 ## 兼容数据规则 - 金额由服务端固定为 100 分,客户端不能指定价格。 - `ProductPayInfo.ProductID=167`。 - `PayType=8`,`BuyType=131`,订单初始 `Status=0`。 - 支付成功后 `Status=1`,同时写入 `PayEndTime`、`XMLPay`、 `ProductServiceTime` 和服务号 `UserID`。 - `WechatServiceWXUsers` 写入 `IsProbation=1` 和 `ProbationPayTime`。 - 如果服务号用户的 UnionID 已关联 `MiaoguoWXUsers`,秒过有效期更新为支付时间后 16 天。 - 微信重复通知或“通知与主动查单同时到达”不会重复发放权益,完成逻辑使用数据库事务、 行锁和 `Status=1` 幂等判断。 ## 新接口 | 接口 | 方法 | 用途 | | --- | --- | --- | | `/api/MiaoguoWechatServicePayLogin500` | POST | OAuth code 换 OpenID、固定 1 元统一下单、返回 JSAPI 参数 | | `/api/MiaoguoWechatServicePayOrderStatus500` | POST | 主动向微信查单,必要时补发权益 | | `/api/MiaoguoWechatServicePayNotify500` | POST XML | 微信 APIv2 支付结果通知 | 下单响应、查单响应和支付成功通知均校验 APIv2 签名、AppID 和商户号;完成订单前还会 校验 OpenID、交易单号与 100 分金额。微信通知地址默认是: ```text https://www.kylx365.com/api/MiaoguoWechatServicePayNotify500 ``` 如部署域名变化,可配置: ```bash WX_WECHAT_SERVICE_PAY_NOTIFY_URL=https://域名/api/MiaoguoWechatServicePayNotify500 WX_WECHAT_SERVICE_PAY_TIMEOUT_MS=10000 ``` 微信商户平台 APIv2 密钥仍读取现有 `config.wx.payapisecret`,服务号 AppID、AppSecret 和 商户号也沿用现有配置,因此数据库及部署配置与旧模块兼容。 ## 支付完成确认 网页不会再把微信前端 `getBrandWCPayRequest:ok` 当作最终成功。它会把服务端生成的 `TradeNo` 提交到新查单接口,只有服务端向微信确认 `trade_state=SUCCESS` 且事务完成后 才跳转成功页。支付按钮在整个流程中防重复点击;如果微信已受理但查单暂时失败,页面会 保持禁用并提醒不要重复支付。 本地自动测试不会访问微信或修改真实数据库: ```bash npm run test:wechat-service-pay ``` 测试包含固定服务端金额、APIv2 签名/XML、伪造通知拦截、事务完成、重复通知幂等、 金额不一致回滚、主动查单补完成,以及网页支付后确认逻辑。