active
This commit is contained in:
@@ -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 dedupe(biz_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` 不重复结算
|
||||
Reference in New Issue
Block a user