## Context 修正业务方案 v5 中 5 项业务逻辑补全,涉及佣金计算、订单查询、支付对接、订单创建、资产状态管理共 5 个模块。各项之间无强依赖,但 J-2(平台钱包代购)与 J-1(富友支付)涉及同一个文件 `order/service.go`,建议 J-2 先做避免合并冲突。 ## Goals / Non-Goals **Goals:** - 佣金链断裂可被平台发现(F-1) - C端订单查询符合 Handler → Service 分层(F-4) - 富友支付 JSAPI/MiniApp 可正常预下单(J-1) - 平台可代用代理钱包购包(J-2) - 卡/设备状态反映真实使用情况(J-3) **Non-Goals:** - 不修改佣金计算核心算法 - 不新增自动化测试 - 不改动回调链路(已存在且正常工作) - 不新建 DB 表(仅插入配置数据) ## Decisions ### 1. F-1 零额待审记录的触发点 **决策**:在 `calculateChainOneTimeCommission` 和类似链式计算函数中,当 `getCostPrice` 返回零/无配置时,`break` 之前创建记录。 **原因**:这是佣金链唯一的断裂点——上游代理缺少套餐系列授权。在此处插入最精准。 记录写入失败不阻断主流程(`_ = store.Create()`),仅记 Error 日志。 ### 2. F-4 迁移范围 **决策**:仅迁移 `ListOrders` 和 `GetOrderDetail` 两个查询方法到 Service 层。不重构其他正常工作的 Handler 方法。 **原因**:最小改动原则。其他 Handler 方法如果没有绕层问题则不动。 迁移后 Handler 中删除 `h.db` 字段引用和 `SkipPermissionCtx` 用法。 ### 3. J-1 富友客户端构造方式 **决策**:每次调用时从 `wechatConfigStore.GetActive()` 读配置并构造 `fuiou.Client`,不做全局单例缓存。 **原因**:配置可以在管理端切换(activate/deactivate),缓存可能导致读到旧配置。构造成本很低(纯内存操作),无需优化。 **替代方案**:全局单例 + 配置变更时刷新 → 增加复杂度,收益不大,拒绝。 ### 4. J-2 平台代购的身份伪装 **决策**:平台代购时,`orderBuyerType` 设为 `agent`,`orderBuyerID` 设为 `*resourceShopID`。成本价和钱包都使用资产所属代理的。 **原因**:从订单归属和佣金计算角度,这笔订单等效于"该代理用自己钱包买的",只是操作人是平台。 ### 5. J-3 状态更新时机 **决策**: - `status → 3`:在 `PackageActivationHandler` / `ActivateByRealname` 激活套餐成功后,检查 `card.Status < 3` 则更新为 3 - `status → 4`:在套餐到期处理逻辑中(`OrderExpireHandler` 或类似),当卡的最后一个 active 套餐过期时更新为 4 **原因**:与套餐生命周期绑定最自然——有活跃套餐就是"已激活",无活跃套餐就是"已停用"。 ## Risks / Trade-offs - **[F-1 零额记录堆积]** 如果某代理长期缺配置,会产生大量 status=99 记录 → 平台应定期处理待审记录(这本身就是 F-1 的目的) - **[F-4 SkipPermissionCtx 移除]** 迁移后 Service 层查询会经过数据权限过滤 → 需确保 C端用户的数据权限配置正确,否则可能查不到数据 - **[J-1 凭证安全]** 富友私钥存在 DB → 当前 `wechat_config` 表已有类似敏感数据(微信支付密钥),风险等级一致 - **[J-3 并发更新]** 多个套餐同时激活可能并发更新 status → 使用条件更新 `WHERE status < 3` 避免覆盖