Skip to content

08 · 实时返水系统

0. 文档说明

内容
版本V1.0

投注即返。订阅 12BetSettled 实时累计;费率档位读 06 等级;领取入账走 02

一租户 = 一「本位币站」,站内单币种(→ 00 架构总纲)。返水池、有效投注、累计、领取到账口径恒为本位币 wallet.baseCurrency;返水池按 游戏类型 × 厂商 两维分桶,池值恒本位币。


一、定位与职责

  • 定义返水的实时累计模型(注单结算 → 按费率入池,按 游戏类型 × 厂商 分桶,金额恒本位币);
  • 定义费率矩阵(游戏类型 × VIP 等级,厂商可覆盖)与取值规则;
  • 定义领取(阈值/粒度/幂等)与「即将派发」倒计时的准确语义;
  • 定义返水面板、返水比例详情页、规则页的展示契约。

边界:有效投注(validTurnover)的产生与冲正归 12;等级归 06;打码权重是 10 的概念(返水用原始有效投注,不加权)。


二、核心概念与数据模型

2.1 返水池 RakebackPool(用户 × 游戏类型 × 厂商)

字段说明
userId / tenantId归属
gameType / vendor分桶维度(游戏类型:原创/电子/真人/棋牌/捕鱼/体育…,目录归 12);无 currency 维度——站内单币种,池值恒本位币
accrued当前可领金额(本位币,实时累计,已结算即入)
lastAccrualAt最近累计时间

场馆链路的 CNY 映射(→ 02 链路 route:仅 USDT 站高价值场馆可选)只影响向厂商申报的符号/数值口径,厂商回传注单由通道适配层 1:1 重标为本位币入库;本系统拿到的 validTurnover 已是本位币真实值,返水计算零特判。

2.2 累计与领取流转

 BetSettled(12) ──► accrual = validTurnover × rate(gameType, vipLevel, vendor?) ──► 池 accrued +=(本位币)

 用户领取(≥ minClaim) ──► REWARD_CREDIT(claimId) ──► 池清零(领取范围内) ──► 界面出「即将派发」倒计时
                                                                              = 下一结算批次(settleCycle)
 注单取消(BetCancelled) ──► 对应累计冲正(池扣回;池不足时挂负债,后续累计抵扣)

「即将派发」语义:倒计时仅在领取之后显示(settle.showCountdown=true),含义是「下一批结算入池的时间」(settle.nextSettleAt 绝对时间戳,→ §五 settle 字段);未领取时面板只显示当前可领金额与领取按钮,不显示倒计时,也不出现「每 2 小时到账」类固定文案;realtime 模式恒出静态文案「投注后实时到账」。

2.3 费率取值(优先级)

rate = vendorOverrides[vendor][gameType][level]   // 厂商级覆盖(可选)
     ?? matrix[gameType][level]                    // 游戏类型 × 等级(主矩阵)
     ?? 0

等级取注单结算时点的用户等级;费率用小数(0.006 = 0.6%,→ 00 §4.8);入池金额向下取整到本位币精度(→ 02 §3.7)。


三、业务规则

  1. 实时性:结算即入池(事件驱动,秒级);未结算注单不产生返水。
  2. 领取:粒度由 claimGranularity 配置——all(一键领全部)/ perType(按游戏类型分领);门槛 minClaim(本位币);幂等键 claimId;领取发 RewardClaimed(source=RAKEBACK),默认直入可用(rewardTarget=available),入本位币钱包。
  3. 冲正:注单取消(BetCancelled,幂等键 betId+cancelSeq)→ 从对应池扣回,写一条 rakeback_accrual_log(kind=REVERSE, amount<0)(与结算行 kind=ACCRUE 共享 bet_id、靠 kind+cancel_seq 区分,支持同注单多次/部分取消);池已被领走导致不足 → 记负余额(负债),后续累计先抵扣,不向用户追讨:返水冲正只作用于返水池;已解锁/已 FULFILLED 的彩金打码义务不因取消回退(资金已放,→ 10 §3.1),二者处置口径独立。
  4. 等级变化:LevelChanged 后,新结算的注单按新费率;已入池金额不重算。
  5. 过期:expireDays 可配(默认 null 不过期);过期清零走 BONUS_EXPIRE 语义的返水专用记录(留痕)。
  6. 风控:领取过 14 前置;对打套利(两边对冲刷流水)由 14 识别,处置=冻结领取/名单。

四、★ 租户可配置项(rakeback 命名空间)

jsonc
"rakeback": {
  "enabled": true,
  "rewardTarget": "available",
  "claimGranularity": "all",            // all | perType
  "minClaim": "1",                      // 领取门槛(本位币;站内单币种,单值不分币种)
  "settleCycle": "realtime",            // realtime | 每 N 分钟批次(倒计时展示依据)
  "expireDays": null,
  "matrix": {                           // 游戏类型 × 等级段(段内同率,覆盖 1..maxLevel)
    "slots":  [ { "levels": "1-10", "rate": 0.003 }, { "levels": "11-30", "rate": 0.006 }, { "levels": "31-50", "rate": 0.009 } ],
    "live":   [ { "levels": "1-10", "rate": 0.002 }, { "levels": "11-30", "rate": 0.004 }, { "levels": "31-50", "rate": 0.006 } ],
    "card":   [ /* … */ ], "lottery": [ /* … */ ], "fish": [ /* … */ ], "sport": [ /* … */ ], "esport": [ /* … */ ], "original": [ /* … */ ]
  },
  "vendorOverrides": { }                // 可选:{ "pg": { "slots": [ … ] } }
}

Schema 校验:每 gameType 的段覆盖 1..level.maxLevel 且不重叠;rate ∈ [0, 上限(平台风控线)];gameType ⊆ 12 目录;minClaim 单值(本位币)。


五、与其他系统的关系 / 接口

接口调用方幂等键说明
getRakebackPanel(userId)展示层按游戏类型分组的厂商池列表 + 可领总额(本位币) + settle 倒计时字段(见下)
getRateTable(gameType, vendor?)展示层该维度 1..50 级费率表(比例详情页)
claim(userId, scope)展示层claimId领取(scope=all/type),入本位币钱包
消费 BetSettled / BetCancelled← 12betId(+cancelSeq)累计/冲正
消费 LevelChanged← 06changeSeq刷新费率档位
RewardClaimed→ 02/13/14/16claimId入账留痕(本位币)

settle 倒计时字段结构(getRakebackPanel 返回):

jsonc
"settle": {
  "mode": "realtime",        // realtime | batch(取自 rakeback.settleCycle)
  "nextSettleAt": null,       // batch 模式=下一结算批次的绝对时间戳(ISO,后端已对齐批次边界);realtime 模式=null
  "showCountdown": false      // 仅「本次领取之后」为 true(未领取不显示倒计时)
}
  • 来源:mode 直取 rakeback.settleCycle;nextSettleAt 由后端按批次边界对齐后下发绝对时间戳(前端只做 nextSettleAt − now 倒计时,不自行推批次);showCountdown 由「是否刚领取过」决定。
  • 批次边界对齐规则:settleCycle=每N分钟 时,nextSettleAt = 租户时区自然整点起算的下一个 N 分钟边界(如 N=120 → 对齐到偶数整点),与用户注册时刻无关,保证同租户所有用户对齐同一批次。
  • 前端分支:mode=realtime → 出静态文案「投注后实时到账」(不倒计时);mode=batch && showCountdown → 按 nextSettleAt 倒计时;showCountdown=false → 只显示可领金额与领取按钮,无倒计时(→ §2.2)。

六、运营后台能力(→ 15)

能力
平台控制台费率上限风控线(防商户误配 10% 级费率)
商户控制台费率矩阵编辑(游戏类型×等级段,厂商覆盖)、领取门槛/粒度/过期、返水成本报表(→17)、用户返水流水查询

七、展示契约(→ 原型映射)

UI 元素数据原型载体系统契约
游戏类型侧边栏池按 gameType 分组返水 tab 左侧类型栏类型目录来自 12;仅显示有池或有费率的类型
厂商行vendor 池金额(本位币) + logo品牌 logo 复用大厅 app/assets/img/brand/wd/pXX.webp;行可点点击 → 比例详情页(带入该厂商);金额恒本位币符号
领取按钮可领总额 ≥ minClaim完成态领取按钮(可领=绿/不足门槛=灰)claim(all);领取后即时刷新池与红点
「即将派发」倒计时settle.{mode,nextSettleAt,showCountdown}(→ §五)仅领取后显示(showCountdown)batch 按 nextSettleAt 绝对时间戳倒计时;realtime 出「投注后实时到账」静态文案
比例详情页费率表#sub-rebate-detail:游戏类型/厂商双下拉 + 1..50 级费率表(当前级高亮)getRateTable;下拉选项来自 12 目录
规则页计算口径#sub-rebate-rules(独立页,由 ? 入口进入)文案与配置联动(门槛/粒度/口径:有效投注=已结算注单本金,取消冲正)

八、数据库设计(全表含 tenant_id;金额 DECIMAL(32,8))

关键字段约束/索引
rakeback_poolstenant_id, user_id, game_type, vendor, accrued(本位币,可负=负债), last_accrual_atUK(tenant_id,user_id,game_type,vendor)
rakeback_accrual_logid PK, tenant_id, user_id, bet_id, kind(ACCRUE/REVERSE:结算入池 / 取消冲正), cancel_seq(结算行=0,冲正行=取消序号), game_type, vendor, turnover, rate, amount(本位币,冲正为负), created_atUK(tenant_id,bet_id,kind,cancel_seq)——结算与多次冲正各一行,靠 kind+cancel_seq 区分;IDX(tenant_id,user_id,created_at)
rakeback_claimsclaim_id PK, tenant_id, user_id, scope, amount(本位币), detail JSON(各池扣减明细), created_atUK(tenant_id,claim_id)

(池键为 (tenant_id, user_id, game_type, vendor)——站内单币种,金额恒本位币,键内无 currency 分量。)accrual_log 为审计与「返水明细」展示依据;高频场景可批次聚合写入(实现优化,语义一致)。


九、扩展点与开放问题

  • 加权返水:返水基数用原始有效投注,权重仅存在于 10 的打码;若租户要求加权返水,复用 10 的权重表作可选项。
  • 负债展示:冲正负债对用户可见(「待抵扣 -X」)还是静默抵扣,交互待定。
  • 实时批次的成本:realtime 逐注入池在高频下的写放大,实现层可微批(N 秒聚合),语义不变。
  • 返佣 basis=rakebackShare 的取数口径:本系统返水池是发给用户的(无「平台返水池」实体)。11 若配 basis=rakebackShare,其分成基数 = 下级实际领取的返水净额(RewardClaimed(source=RAKEBACK) 的领取额,已含冲正抵扣后的真实到手值),数据源 = rakeback_claims(而非入池 accrued 或冲正前流水),避免与返水成本双计(→ 11 §2.3)。

十、验收要点

  • [ ] 注单结算后池金额 = Σ(validTurnover × 结算时点费率),向下取整到本位币精度;未结算注单不入池;
  • [ ] 池仅按 游戏类型 × 厂商 分桶,金额全程本位币,无 currency 分桶维度;
  • [ ] 领取幂等,入本位币钱包;领取后池清零、红点清除、倒计时才出现(settle.showCountdown=true,batch 按 nextSettleAt 绝对时间戳、realtime 出静态文案);未领取时无倒计时、无「每2小时」文案;
  • [ ] 注单取消(betId+cancelSeq)后池扣回,写 accrual_log(kind=REVERSE) 与结算行 kind=ACCRUE 靠 kind+cancel_seq 共存不撞 UK;池不足挂负债并被后续累计抵扣;
  • [ ] 升级后新注单按新费率,旧池不重算;
  • [ ] 比例详情页:切换游戏类型/厂商,费率表与当前级高亮正确;费率全配置驱动;
  • [ ] 费率超平台上限的配置发布被拒。