Files
cursor/plans/is_end派奖结算改造_14ce4dc5.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

4.1 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
is_end派奖结算改造 基于现有 BetFunding/WinService 实现,新增 is_end 分支:中间派奖仅累计不入账,结束派奖统一按 Round Final Settlement 入账;并对中间派奖增加 biz_id 严格幂等。
id content status
dto-validator-is-end 扩展 DTO 与校验器,支持 is_end 并强制 win 场景 round_id 校验 pending
id content status
redis-win-keys 新增 pending/dedupe Redis key 生成方法与 TTL 约定 pending
id content status
logic-win-branching 在 WalletLogic::win 中实现 is_end=0 累计与 is_end=1 最终结算分支 pending
id content status
idempotency-regression 补充关键回归场景说明并验证与现有幂等不冲突 pending
false

is_end 驱动的派奖结算改造计划

目标

win 接口支持第三方 is_end 语义:

  • is_end=0:仅记录/累计本局派奖,不做钱包入账、不做 Lot 终态收敛
  • is_end=1:将本次派奖 + 已累计派奖合并后,执行一次 Final Settlement现有 WinService::execute

现状结论(基于代码)

实现方案(按你选择)

1) 入参扩展与校验

2) Redis Key 设计

  • app/service/RedisKeyManagerService.php 新增两个 key 生成器:
    • wallet:win:pending:{uid}:{currency}:{round_id}:累计未结算派奖金额
    • wallet:win:dedupe:{uid}:{currency}:{round_id}:{biz_id}:中间派奖幂等标记
  • 过期策略建议:pending 48hdedupe 72h与重放窗口对齐

3) win 主流程分支

  • 修改 app/api/logic/WalletLogic.phpwin()
    • is_end=0
      • 命中 dedupe key 则直接返回当前钱包(幂等)
      • 未命中则将 fee 累加到 pending key写 dedupe key返回当前钱包不写 BIZ_TYPE_WIN 流水)
    • is_end=1
      • 读取 pending 累计并与本次 fee 合并为 finalWinAmount
      • finalWinAmount 调用现有 WinService::execute
      • 事务提交后清理 pending key失败不清

4) 幂等与一致性

  • is_end=1 继续沿用现有 wallet_log(uid,biz_id,biz_type=win) 幂等。
  • is_end=0 使用 Redis dedupe key 防重,避免重复累计。
  • is_end=1 无待分配 funding保持当前行为报错便于暴露上游时序问题。

5) 兼容与回归

  • 默认 is_end=1,兼容未传该字段的旧调用。
  • 回归场景:
    • 单次结算(只发 is_end=1
    • 多次派奖(多条 is_end=0 + 一条 is_end=1
    • is_end=0 重放同 biz_id 不重复累计
    • is_end=1 重放同 biz_id 不重复入账
    • is_end=1 失败后 pending 不丢失

关键改动文件

风险与边界

  • 该方案不新增 wallet_game_round / wallet_game_round_event 持久化表;中间派奖仅 Redis 暂存,审计粒度弱于 DB 事件流。
  • 若某局长期无 is_end=1pending 依赖 TTL 过期清理。后续可升级为 DB 事件表方案。