--- todos: - id: "define-rate-semantics" content: "确定贡献率字段名、取值范围(0-100)、默认值 100 与 effective_wager 计算公式,写入 MQ 对接文档" status: pending - id: "wallet-v2-consume" content: "slot_wallet:UpdateWagerTask 解析 MQ 中 wager_contribution_rate,仅 version2 使用 effective_wager" status: pending - id: "mq-contract-doc" content: "输出 slot_pwa 对接说明:在现有 wager_task_update MQ 上增加 wager_contribution_rate 字段" status: pending - id: "compat-test" content: "slot_wallet 单测:MQ 无 rate 默认 100、version1 不变、version2 部分贡献" status: pending isProject: false --- # slot_wallet 打码贡献率方案(仅 slot_wallet 改动) ## 范围约束 - **本方案只改 [`slot_wallet`](slot_wallet)**,不改动 slot_pwa / slot_sdk 等其它服务代码。 - 已确认:**仅 version2 打码**应用贡献率;version1 保持 1:1。 - **打码 MQ 仍由 slot_pwa 发送**(现有架构不变);wallet 只改 **消费端**。 --- ## 现网链路(正确理解) 打码触发方一直是 **slot_pwa**,不是 slot_wallet: ```mermaid sequenceDiagram participant Pwa as slot_pwa participant Wallet as slot_wallet participant TxMQ as transaction_log_MQ participant TxLog as slot_pwa_TransactionLog participant WagerMQ as wager_task_update_MQ participant Consumer as slot_wallet_UpdateWagerTask Pwa->>Wallet: POST /api/wallet/update type=bet 扣款 Pwa->>TxMQ: 写入用户交易流水 TxMQ->>TxLog: 消费 BET 流水 TxLog->>WagerMQ: 发 MQ uid/fee/currency WagerMQ->>Consumer: UpdateWagerTask::version2 Note over Consumer: current_wager += min(fee, needed) ``` 关键代码(**发送方在 pwa,消费方在 wallet**): - 发送:[`slot_pwa/app/process/TransactionLog.php`](slot_pwa/app/process/TransactionLog.php) → `updateWagerTask()`,消息体 `{uid, fee, currency}` - 消费:[`slot_wallet/app/command/UpdateWagerTask.php`](slot_wallet/app/command/UpdateWagerTask.php) → `version2()`,按下注额 **100%** 计入 - wallet 下注:[`slot_wallet/app/api/logic/WalletLogic.php`](slot_wallet/app/api/logic/WalletLogic.php) 只扣款,**不发** 打码 MQ(`//todo 更新打码任务` 未实现) 因此:**贡献率应加在 PWA 发出的 MQ 里**;slot_wallet 侧只需让 `UpdateWagerTask` 读懂新字段。 --- ## 结论:仅改 slot_wallet 时做什么 | 谁改 | 做什么 | |---|---| | **slot_wallet(本仓库)** | `UpdateWagerTask` 消费 MQ 时读取 `wager_contribution_rate`,version2 按 rate 计算有效打码额 | | **slot_pwa(他人开发)** | 在**现有** `updateWagerTask()` 发出的 MQ 中增加 `wager_contribution_rate`;rate 由 pwa 按游戏/厂商配置在下注流程中确定 | **不需要** wallet 在下注 API 接参、也 **不需要** wallet 改发 MQ——那会与 pwa 现有职责冲突,且可能造成双计。 --- ## slot_wallet 改动(仅此一处核心逻辑) ### 文件 [`slot_wallet/app/command/UpdateWagerTask.php`](slot_wallet/app/command/UpdateWagerTask.php) ### 贡献率语义 | 项 | 约定 | |---|---| | MQ 字段名 | `wager_contribution_rate` | | 含义 | 有效打码占比;**100 = 全额计入**(与现网一致) | | 缺省 | MQ 无此字段 → **100** | | 校验 | 消费端 clamp 到 `0~100` | | 计算公式 | `effective_wager = intdiv(fee * rate, 100)`(厘,向下取整) | | 作用范围 | 仅 `version2()`;`version1()` 仍用原始 `fee` | ### 伪逻辑 ```php // deal() 解析 MQ body $betAmount = (int)($body['fee'] ?? 0); $rate = max(0, min(100, (int)($body['wager_contribution_rate'] ?? 100))); // updateWagerTasks() if (ShareConfigService::isVersion2($uid)) { $effectiveWager = intdiv($betAmount * $rate, 100); if ($effectiveWager <= 0) return; $this->version2($uid, $effectiveWager, $currency); return; } $this->version1($uid, $betAmount, $currency); // version1 忽略 rate ``` ### 可选增强(非必须) - 为 `deal()` / `updateWagerTasks()` 补中文 PHPDoc - 单测覆盖:无 rate、rate=50、rate=0、version1 不受影响 **不改动**:`WalletUpdateRequestDTO`、`WalletLogic` 下注接口(与打码 MQ 链路无关)。 --- ## MQ 对接约定(给 slot_pwa 同事,wallet 不写 pwa 代码) ### 现有消息(today) ```json { "uid": 123, "fee": 1000, "currency": "INR" } ``` ### 目标消息(pwa 在 `TransactionLog::updateWagerTask` 增加字段) ```json { "uid": 123, "fee": 1000, "currency": "INR", "wager_contribution_rate": 50 } ``` - `fee`:仍为实际下注扣款额(不变) - `wager_contribution_rate`:pwa 按 game_id / 游戏类型 / 厂商配置赋值;未配置游戏传 `100` - wallet 先上线 consumer(兼容无 rate),pwa 再发带 rate 的消息即可灰度 ### pwa 侧职责(他人实现) 1. 下注时解析该游戏的贡献率配置 2. 在**原有**打码 MQ 中附带 `wager_contribution_rate` 3. **无需**关闭或迁移 MQ 发送点——仍走 `TransactionLog::updateWagerTask` --- ## 目标架构 ```mermaid sequenceDiagram participant Pwa as slot_pwa participant Wallet as slot_wallet participant WagerMQ as wager_task_update_MQ participant Consumer as UpdateWagerTask Pwa->>Wallet: bet 扣款 Pwa->>WagerMQ: uid fee currency wager_contribution_rate WagerMQ->>Consumer: version2 effective_wager ``` --- ## 风险与约束 ### 兼容 - pwa 未发 `wager_contribution_rate` 前:wallet consumer 默认 100,**与现网完全一致**。 - wallet 可先单独上线,不破坏现网。 ### 安全 - rate 由 pwa 写入 MQ;wallet 消费端做范围 clamp,**不在 wallet 内校验游戏配置**(本期 scope 不含配置表)。 ### 其它 - `total_bet` 仍按 wallet 扣款 `fee` 统计,与有效打码额分离。 - 无打码回滚逻辑;本需求不新增。 --- ## slot_wallet 验收要点 1. MQ `{fee:100, wager_contribution_rate:50}` → version2 用户 `current_wager` +50。 2. MQ 无 rate 字段 → version2 仍 +100(fee=100)。 3. version1 用户:即使 MQ 带 rate,仍按 fee 全额计入。 4. `effective_wager=0`(rate=0)→ 不更新打码。 --- ## 不在本方案范围 - slot_pwa 改 MQ 发送(由他人完成,wallet 只提供对接约定) - wallet 下注 API 增加 `wager_contribution_rate`(与现链路无关,非必须) - wallet 改发打码 MQ - 游戏贡献率配置表 / 后台 - version1 贡献率、打码回滚