This commit is contained in:
ray zhou
2026-05-21 19:39:52 +08:00
parent 10f55e0262
commit 5d6d482efe
33 changed files with 2 additions and 3946 deletions

View File

@@ -1,91 +0,0 @@
---
name: 中间派奖余额可见化
overview: 在保持 Final Settlement 真账口径不变的前提下,让 is_end=0 中间派奖实时反映到三方读取的余额(接口返回和钱包查询)。
todos:
- id: pending-win-keys
content: 设计并接入 pending round/total 与 dedupe Redis key
status: pending
- id: win-is-end-branch
content: 实现 is_end=0 累计展示、is_end=1 合并结算与清理
status: pending
- id: wallet-query-overlay
content: 让 wallet 查询叠加 pending total 返回最新展示余额
status: pending
- id: dto-validator-update
content: 补齐 is_end DTO 与 win round_id 校验
status: pending
- id: regression-cases
content: 验证多次派奖余额可见、最终结算、幂等与失败重试场景
status: pending
isProject: false
---
# 中间派奖余额可见化is_end改造计划
## 目标
解决“多次派奖时三方读取余额不更新”的问题,同时保持 `win.md` 的核心原则:
- 真正入账、Lot 回流、转化/解锁只在 `is_end=1`Final Settlement执行
- `is_end=0` 仅做中间派奖累计与展示余额更新
## 核心思路
在 Redis 维护“待结算派奖池Pending Win并把它叠加到对外返回余额
- DB 里的 `withdraw/deposit/bonus` 仍保持真实账
- 对外给三方的余额 = 真实账 + pendingWin
这样能保证:
- 三方实时看到余额变化
- 不破坏现有 `WinService` 的 Round Final Settlement 账务逻辑
## 具体改造
### 1) 新增 Pending Win 缓存层
修改 [app/service/RedisKeyManagerService.php](app/service/RedisKeyManagerService.php):新增 key
- `wallet:win:pending:round:{uid}:{currency}:{round_id}`(每局中间派奖累计)
- `wallet:win:pending:total:{uid}:{currency}`(用户币种维度累计,供快速读余额)
- `wallet:win:dedupe:{uid}:{currency}:{round_id}:{biz_id}`(中间派奖严格幂等)
### 2) win 分支行为
修改 [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php) 的 `win()`
- `is_end=0`
- 命中 dedupe 直接返回
- 未命中则 `INCRBY pending:round``INCRBY pending:total`
- 返回余额时把 `pending:total` 叠加到 `withdraw`(仅对外展示)
- 不调用 `WinService::execute`、不写 `BIZ_TYPE_WIN`
- `is_end=1`
- 读取 `pending:round``finalWin = fee + pendingRound`
-`finalWin` 调用现有 [app/service/wallet/WinService.php](app/service/wallet/WinService.php)
- 成功后清理 `pending:round` 并从 `pending:total` 扣除对应值
- 返回余额按真实账(此时 pending 已回收)
### 3) 钱包查询返回也要可见化
修改 [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php) 的 `query()` 返回:
-`pending:total` 叠加到返回字段 `w/withdraw`
- 这样第三方无论读 `win` 返回还是调用 `wallet` 查询,都看到“最新展示余额”
### 4) DTO/校验补齐
- 在 [app/api/dto/request/wallet/WalletUpdateRequestDTO.php](app/api/dto/request/wallet/WalletUpdateRequestDTO.php) 增加 `is_end`(默认 1
- 在 [app/validator/Wallet2Validator.php](app/validator/Wallet2Validator.php) 增加:
- `is_end` 仅允许 `0/1`
- `win` 场景强制 `round_id` 必传
## 一致性与幂等
- `is_end=0`Redis dedupebiz_id 级)防重复累计
- `is_end=1`:延续现有 `wallet_log(uid,biz_id,biz_type=win)` 幂等
- 若 Final 失败,不清 pending便于重试恢复
## 风险说明(需明确)
- 该方案是“展示余额实时、真账延后”:若上游把展示余额当可立即可下注余额,可能出现下注时余额校验不一致。
- 若你需要“中间派奖立即可下注”,则要走另一套方案(中间账临时入库 + Final 对冲重分配),改动会显著更大。
## 改动文件
- [app/service/RedisKeyManagerService.php](app/service/RedisKeyManagerService.php)
- [app/api/dto/request/wallet/WalletUpdateRequestDTO.php](app/api/dto/request/wallet/WalletUpdateRequestDTO.php)
- [app/validator/Wallet2Validator.php](app/validator/Wallet2Validator.php)
- [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php)
## 验收场景
- 多次 `is_end=0` 后,`win` 返回余额递增
- 多次 `is_end=0` 后,`wallet` 查询余额递增
- `is_end=1` 触发后final 入账金额 = 中间累计 + 最后一笔
- 重放同一 `is_end=0` `biz_id` 不重复累计
- 重放同一 `is_end=1` `biz_id` 不重复结算