Răsfoiți Sursa

docs(virtual-pay): 同步设计文档 §5.1/5.2/§8 与 PROJECT-OVERVIEW 状态

设计文档: 签名算法改 JSON 串、orderInfo 示例改官方 camelCase、offerId/productId 语义澄清、配置项补 offer-id/sandbox-appkey/virtual-pay-token。PROJECT-OVERVIEW: 虚拟支付 设计中 → 已实现(联调中)。

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
asus 3 luni în urmă
părinte
comite
4093cb39ba

+ 9 - 9
docs/superpowers/PROJECT-OVERVIEW.md

@@ -2,7 +2,7 @@
 
 
 **文档版本:** v2.3
 **文档版本:** v2.3
 **日期:** 2026-08-02
 **日期:** 2026-08-02
-**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(设计中)
+**状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(已实现·联调中)
 **维护:** 所有需求变更需更新本文档
 **维护:** 所有需求变更需更新本文档
 
 
 ---
 ---
@@ -17,7 +17,7 @@
 | **Phase 3** | 2026-Q3 | 五维增强 | 富维度子维度拆分、文章发布系统、辈分重构 | ✅ 已完成 |
 | **Phase 3** | 2026-Q3 | 五维增强 | 富维度子维度拆分、文章发布系统、辈分重构 | ✅ 已完成 |
 | **Phase 4** | 2026-Q4 | 平台扩展 | 供应商体系、健康7维模型、成长档案 | ✅ 已完成 |
 | **Phase 4** | 2026-Q4 | 平台扩展 | 供应商体系、健康7维模型、成长档案 | ✅ 已完成 |
 | **Phase 5** | 2026-Q3 | 主动健康六阶模型 | 微启动+即时反馈+智能预警+身份重塑+家庭互动+社区扩散 | ✅ 已完成(P0-P3 全栈交付) |
 | **Phase 5** | 2026-Q3 | 主动健康六阶模型 | 微启动+即时反馈+智能预警+身份重塑+家庭互动+社区扩散 | ✅ 已完成(P0-P3 全栈交付) |
-| **Phase 6** | 2026-08 | 虚拟支付合规化 | 小程序虚拟支付接入(测评/会员/订阅)、道具映射、发货/退款闭环 | 🟡 设计中 |
+| **Phase 6** | 2026-08 | 虚拟支付合规化 | 小程序虚拟支付接入(测评/会员/订阅)、道具映射、发货/退款闭环 | 🟢 实施中 |
 
 
 ---
 ---
 
 
@@ -85,14 +85,14 @@
 ### 2.5 小程序虚拟支付合规接入 ⭐ P0
 ### 2.5 小程序虚拟支付合规接入 ⭐ P0
 
 
 **阶段:** Phase 6(2026-08 启动)
 **阶段:** Phase 6(2026-08 启动)
-**状态:** 🟡 设计完成 + 实施计划就绪(`plans/2026-08-02-virtual-payment-implementation.md`)
+**状态:** 🟢 已实现(联调中;2026-08-03 修正 offerId=支付应用ID、signData 改官方 camelCase JSON 串)
 **背景:** 小程序内测评订单/会员/订阅此前为假支付或假定已支付,需接入官方「小程序虚拟支付」能力(`wx.requestVirtualPayment`),合规收款
 **背景:** 小程序内测评订单/会员/订阅此前为假支付或假定已支付,需接入官方「小程序虚拟支付」能力(`wx.requestVirtualPayment`),合规收款
 
 
 | 功能 | 状态 | 关联文档 |
 | 功能 | 状态 | 关联文档 |
 |------|:----:|---------|
 |------|:----:|---------|
-| 虚拟支付服务层(VirtualPayService + 签名/发货/退款) | 🟡 设计中 | `specs/2026-08-02-virtual-payment-design.md` |
-| 道具映射表 virtual_goods_config + Web 管理端 CRUD | 🟡 设计中 | `specs/2026-08-02-virtual-payment-design.md` |
-| 三类订单接入(测评/会员/订阅)| 🟡 设计中 | `specs/2026-08-02-virtual-payment-design.md` |
+| 虚拟支付服务层(VirtualPayService + 签名/发货/退款) | 🟢 已实现 | `specs/2026-08-02-virtual-payment-design.md` |
+| 道具映射表 virtual_goods_config + Web 管理端 CRUD | 🟢 已实现 | `specs/2026-08-02-virtual-payment-design.md` |
+| 三类订单接入(测评/会员/订阅)| 🟢 已实现 | `specs/2026-08-02-virtual-payment-design.md` |
 
 
 ---
 ---
 
 
@@ -328,7 +328,7 @@
 | `2026-07-10-certainty-ppt-design.md` | 🔄 已废弃(一次性PPT设计,无代码实现) | 确定性叙事PPT |
 | `2026-07-10-certainty-ppt-design.md` | 🔄 已废弃(一次性PPT设计,无代码实现) | 确定性叙事PPT |
 | `2026-07-30-service-role-apply-design.md` | ✅ 已实施 | 服务角色统一申请(规划师/营养师/管家/服务商/文章管理员/活动提供商) |
 | `2026-07-30-service-role-apply-design.md` | ✅ 已实施 | 服务角色统一申请(规划师/营养师/管家/服务商/文章管理员/活动提供商) |
 | `2026-07-31-compare-table-mobile-redesign.md` | 🟡 设计稿 | 四大饮水方案对比 — 移动端轮播式重设计 |
 | `2026-07-31-compare-table-mobile-redesign.md` | 🟡 设计稿 | 四大饮水方案对比 — 移动端轮播式重设计 |
-| `2026-08-02-virtual-payment-design.md` | 🟡 设计中 | 小程序虚拟支付合规接入(测评/会员/订阅)|
+| `2026-08-02-virtual-payment-design.md` | 🟢 已实施(offerId/签名按官方 signData 修正) | 小程序虚拟支付合规接入(测评/会员/订阅)|
 
 
 ### 实施计划(plans/)
 ### 实施计划(plans/)
 
 
@@ -383,7 +383,7 @@
 | `2026-07-24-cfc-web-responsive-implementation.md` | ✅ 已实施(commit 3ee7289e) | 管理后台手机自适应 |
 | `2026-07-24-cfc-web-responsive-implementation.md` | ✅ 已实施(commit 3ee7289e) | 管理后台手机自适应 |
 | `2026-07-28-membership-price-tier-update.md` | ✅ 全栈完成(FREE/FAMILY/PREMIUM 三等级,7 次提交) | 会员等级价格体系更新 |
 | `2026-07-28-membership-price-tier-update.md` | ✅ 全栈完成(FREE/FAMILY/PREMIUM 三等级,7 次提交) | 会员等级价格体系更新 |
 | `2026-07-31-family-members-redesign.md` | 🟡 计划中 | 家庭成员页面重新设计 |
 | `2026-07-31-family-members-redesign.md` | 🟡 计划中 | 家庭成员页面重新设计 |
-| `2026-08-02-virtual-payment-implementation.md` | 🟡 计划就绪 | 小程序虚拟支付接入实施计划(12 Tasks:建表/签名/推送/三链路改造/前端/管理端) |
+| `2026-08-02-virtual-payment-implementation.md` | 🟢 已实施 | 小程序虚拟支付接入实施计划(12 Tasks:建表/签名/推送/三链路改造/前端/管理端) |
 
 
 ### 计划与设计文档(specs/)
 ### 计划与设计文档(specs/)
 
 
@@ -394,7 +394,7 @@
 | `2026-07-24-cfc-web-responsive-design.md` | ✅ 已实施 | 管理后台手机自适应设计 |
 | `2026-07-24-cfc-web-responsive-design.md` | ✅ 已实施 | 管理后台手机自适应设计 |
 | `2026-07-30-service-role-apply-design.md` | ✅ 已实施 | 服务角色统一申请设计 |
 | `2026-07-30-service-role-apply-design.md` | ✅ 已实施 | 服务角色统一申请设计 |
 | `2026-07-22-active-health-six-stage-design.md` | 🟡 当前 | 主动健康六阶模型改进总设计 |
 | `2026-07-22-active-health-six-stage-design.md` | 🟡 当前 | 主动健康六阶模型改进总设计 |
-| `2026-08-02-virtual-payment-design.md` | 🟡 当前 | 小程序虚拟支付合规接入设计 |
+| `2026-08-02-virtual-payment-design.md` | 🟢 已实施 | 小程序虚拟支付合规接入设计 |
 | `2026-07-30-jia-suanfa-webnovel-design.md` | �? 设计完成 | 假算法题材网络小说设计(book2 章节库) |
 | `2026-07-30-jia-suanfa-webnovel-design.md` | �? 设计完成 | 假算法题材网络小说设计(book2 章节库) |
 
 
 ---
 ---

+ 25 - 11
docs/superpowers/specs/2026-08-02-virtual-payment-design.md

@@ -100,33 +100,44 @@ CREATE TABLE virtual_goods_config (
 ### 5.1 签名算法(官方参考脚本同款)
 ### 5.1 签名算法(官方参考脚本同款)
 
 
 ```java
 ```java
-// paySig = to_hex(hmac_sha256(appKey, uri + "&" + signData))
-// uri 固定为 "requestVirtualPayment"(wx.requestVirtualPayment 场景)
-// signData = orderInfo + extInfo 按官方规则拼接(实现时对照官方 Python 脚本输出做断言单测)
+// paySig    = to_hex(hmac_sha256(appKey, "requestVirtualPayment&" + signData))
+// signature = to_hex(hmac_sha256(sessionKey, signData))   // sessionKey 直接字符串编码,不 base64 解码
+// signData  = orderInfo 的 JSON 串(LinkedHashMap 插入序序列化,与前端 JSON.stringify(orderInfo) 逐字节一致)
 String paySig = HmacUtils.hmacSha256Hex(appKey, "requestVirtualPayment&" + signData);
 String paySig = HmacUtils.hmacSha256Hex(appKey, "requestVirtualPayment&" + signData);
 ```
 ```
 
 
+> ⚠️ 修正(2026-08-03):signData 必须是 **JSON 串**(非字典序 key=value 拼接),且 paySig/signature 都基于**同一** JSON 串(前端实际发送的 signData),否则微信验签报 -15005。
+
 ### 5.2 后端下单返回体 `VirtualPayParamsDTO`
 ### 5.2 后端下单返回体 `VirtualPayParamsDTO`
 
 
 ```json
 ```json
 {
 {
   "orderInfo": {
   "orderInfo": {
-    "mch_id": "虚拟支付商户号",
-    "appid": "wx5ba8038ef16fb245",
-    "out_trade_no": "A20260802xxx",
-    "total_fee": 9900,
-    "product_info": "五维测评·基础版",
+    "offerId": "1450607643",
+    "buyQuantity": 1,
+    "env": 0,
+    "currencyType": "CNY",
+    "productId": "member1314",
+    "goodsPrice": 131400,
+    "outTradeNo": "A20260802xxx",
     "attach": "assessment:12"
     "attach": "assessment:12"
   },
   },
   "extInfo": {},
   "extInfo": {},
   "sign": "paySig值",
   "sign": "paySig值",
+  "signature": "用户身份签名",
   "env": 0,
   "env": 0,
   "signType": "HMAC-SHA256"
   "signType": "HMAC-SHA256"
 }
 }
 ```
 ```
 
 
-- `total_fee` 单位:分,**以服务端计算为准**(防篡改)
-- `attach` 透传业务信息(goodsType:bizKey),便于对账
+- **orderInfo 为官方 `wx.requestVirtualPayment` signData 固定结构(camelCase),字段集不得增删:**
+  - `offerId`:**支付应用ID**(mp-虚拟支付基本配置,全应用唯一)——**不是道具ID**
+  - `productId`:**道具ID**(如 member1314),仅 `mode=short_series_goods` 必填
+  - `goodsPrice`:道具单价(分),官方校验与后台道具价格一致(金额以服务端计算为准,防篡改)
+  - `buyQuantity`:道具直购恒为 1
+  - `attach`:透传业务信息(goodsType:bizKey),发货推送时透传,便于对账
+  - `mode`:顶层参数(前端传 `short_series_goods`),**不在 signData 内**
+- ⚠️ 前端 `signData` 必须 = `JSON.stringify(orderInfo)`(保持插入序),与后端签名串逐字节一致,否则 -15005
 - `env`:0=现网 1=沙箱,由配置 `wechat.virtual-pay-env` 控制
 - `env`:0=现网 1=沙箱,由配置 `wechat.virtual-pay-env` 控制
 
 
 ### 5.3 三个业务下单接口改造
 ### 5.3 三个业务下单接口改造
@@ -178,10 +189,13 @@ String paySig = HmacUtils.hmacSha256Hex(appKey, "requestVirtualPayment&" + signD
 ```yaml
 ```yaml
 wechat:
 wechat:
   appkey: ${WECHAT_APPKEY:}                # 虚拟支付 AppKey(商户后台基本配置获取,现网/沙箱分开)
   appkey: ${WECHAT_APPKEY:}                # 虚拟支付 AppKey(商户后台基本配置获取,现网/沙箱分开)
+  sandbox-appkey: ${WECHAT_SANDBOX_APPKEY:} # 虚拟支付沙箱 AppKey
+  offer-id: ${WECHAT_VIRTUAL_PAY_OFFER_ID:1450607643}  # 支付应用ID(mp-支付基础配置;productId 才是道具ID)
   virtual-pay-env: ${WECHAT_VIRTUAL_PAY_ENV:0}   # 0=现网 1=沙箱
   virtual-pay-env: ${WECHAT_VIRTUAL_PAY_ENV:0}   # 0=现网 1=沙箱
+  virtual-pay-token: ${WECHAT_VIRTUAL_PAY_TOKEN:cfcVirtualPay2026}  # 消息推送 Token
 ```
 ```
 
 
-同步更新 `config/application.yml`(模板)与 `config/application-prod.yml`(生产覆盖)。
+> `config/application*.yml` 模板不在仓库内,服务器部署用环境变量注入。
 
 
 ## 9. 前端改动
 ## 9. 前端改动