Files
cursor/plans/RTP-ffd1b7b6.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

5.9 KiB
Raw Permalink Blame History


todos:

  • id: "ddl" content: "新增 slot-pwa/db/game_user_recharge_rtp_stat.sql用户 DDL 原样)" status: pending
  • id: "service-model" content: "GameUserRechargeRtpStatModel + GameUserRechargeRtpStatService + UserRechargeStatusService" status: pending
  • id: "wire-wallet-service" content: "WalletService bet/win 成功后挂载累计与 RTP 重算" status: pending
  • id: "redis-key" content: "RedisKeyManagerService 补充 recharge:exchange key" status: pending isProject: false

game_user_recharge_rtp_statslot-pwa

变更范围

  • :按你提供的 DDL不做额外字段
  • 服务slot-pwa 统一处理(游戏回调 → 调 wallet 的入口)
  • 不做wallet 侧改表、移除 TrialValidBetNotifyService、activity 同步(后续再定)

表结构(原样采用)

库:s_common(与 game_launch_session 同库)

CREATE TABLE `game_user_recharge_rtp_stat` (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `uid` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
    `before_recharge_bet_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '充值前累计下注金额金额扩大1000倍',
    `before_recharge_payout_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '充值前累计派奖金额金额扩大1000倍',
    `before_recharge_rtp_rate` DECIMAL(10, 6) NOT NULL DEFAULT 0.000000 COMMENT '充值前RTPpayout / bet',
    `after_recharge_bet_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '充值后累计下注金额金额扩大1000倍',
    `after_recharge_payout_amount` BIGINT NOT NULL DEFAULT 0 COMMENT '充值后累计派奖金额金额扩大1000倍',
    `after_recharge_rtp_rate` DECIMAL(10, 6) NOT NULL DEFAULT 0.000000 COMMENT '充值后RTPpayout / bet',
    `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    `updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_uid` (`uid`),
    KEY `idx_before_rtp_bet` (`before_recharge_rtp_rate`, `before_recharge_bet_amount`),
    KEY `idx_after_rtp_bet` (`after_recharge_rtp_rate`, `after_recharge_bet_amount`),
    KEY `idx_before_bet` (`before_recharge_bet_amount`),
    KEY `idx_after_bet` (`after_recharge_bet_amount`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='用户充值前后下注派奖RTP累计统计表';

DDL 文件:slot-pwa/db/game_user_recharge_rtp_stat.sql


为什么在 slot-pwa

所有厂商下注/派奖最终都走 WalletService::bet() / win()pop / quick / jsgame / jdb / self / gasea / bbgt 等),与现有 UserProfitService 挂载点一致,一处写入、全覆盖

flowchart LR
    Provider[厂商回调] --> PwaCash[pop/quick/... CashLogic]
    PwaCash --> WalletSvc[WalletService bet/win]
    WalletSvc --> WalletApi[slot-wallet API]
    WalletSvc --> RtpStat[GameUserRechargeRtpStatService]
    RtpStat --> Db[(game_user_recharge_rtp_stat)]

阶段判定(充值前 / 充值后)

读 wallet 同款 Redis 充值标记(RechargeExchangeService::isRecharge

  • Keyrecharge:exchange:{uid % 10}field = uidrecharge > 0充值后
  • 否则 → 充值前

在 slot-pwa 新增薄封装 UserRechargeStatusService(读 default Rediskey 规则与 wallet 一致),不新增表字段


写入口径

挂载点:WalletService::bet() / win(),在 updateWallet() 成功返回非 null 之后 写统计(比现有 UserProfitService 更早调用更安全,避免 wallet 失败仍累加)。

动作 条件 更新字段
bet 成功 未充值 before_recharge_bet_amount += fee
bet 成功 已充值 after_recharge_bet_amount += fee
win 成功 is_end === 1 且未充值 before_recharge_payout_amount += fee
win 成功 is_end === 1 且已充值 after_recharge_payout_amount += fee

派奖仅计 is_end=1:与 wallet 实际入账一致(中间派奖 is_end=0 只写 Redis pending不落库

RTP 重算(同事务内 SQL 更新):

before_recharge_rtp_rate = before_bet > 0
    ? ROUND(before_payout / before_bet, 6) : 0
after_recharge_rtp_rate  = after_bet > 0
    ? ROUND(after_payout / after_bet, 6) : 0

幂等:依赖 slot-pwa 已有 provider_tx 幂等(同一 biz 不会重复调 wallet不在本表再存 biz_id。

fee=0跳过累加zero win 等场景)。


代码落点

文件 职责
slot-pwa/db/game_user_recharge_rtp_stat.sql 建表
slot-pwa/app/model/game/GameUserRechargeRtpStatModel.php ThinkORM Model + 完整 PHPDoc
slot-pwa/app/service/game/GameUserRechargeRtpStatService.php accumulateBet / accumulatePayout、RTP 重算、upsert by uid
slot-pwa/app/service/user/UserRechargeStatusService.php 读 Redis 判断是否已充值
slot-pwa/app/service/WalletService.php bet/win 成功后调用 Service
slot-pwa/app/service/RedisKeyManagerService.php 补充 getRechargeExchangeKey(与 wallet 一致)

与 wallet / activity 的关系(后续)

  • 本表成为 充值前后 bet/payout/RTP 权威数据源
  • activity 的 valid_bet_amount / 4→5 解锁、移除 trial_valid_bet_accumulate MQ → 下一阶段,本计划不改动

验收

  1. 未充值用户游戏:只涨 before_*RTP 随 bet/win 更新
  2. 首充后:只涨 after_*
  3. is_end=0 的中间 win 不计入 payout
  4. wallet 调用失败时不写表
  5. 风控可按 idx_before_rtp_bet / idx_after_rtp_bet 扫异常 RTP