8.1 KiB
8.1 KiB
todos:
- id: "expiry-service-mark-only" content: "TrialBalanceExpiryService:新增 markTrialExpiredIfNeeded / isTrialPlayBlocked / ensureCanLaunchGame,停止对外清零编排" status: pending
- id: "ws-connect" content: "TrialBalanceExpiryConnectService:仅打 tag + 弹窗,移除 clearExpiredTrialBalanceIfNeeded" status: pending
- id: "entry-logic" content: "TrialRewardEntryLogic:移除全路径清零,修正 trial_balance_expired 判定" status: pending
- id: "game-launch-guard" content: "GameLogic + GameController::login:体验过期未充值时 BusinessException 拦截" status: pending
- id: "constants-copy" content: "TrialRewardEntryConstants:更新弹窗与 launch 拒绝文案" status: pending
- id: "verify" content: "docker php -l + slot-backend-completion-report 自检" status: pending isProject: false
体验到期:仅标识、不清余额、禁止进游戏
背景与现状
当前 TrialBalanceExpiryConnectService 在 WS 连接时:
- 调用
clearExpiredTrialBalanceIfNeeded→ walletexpireTrialBalance+ activity 删trial_reward_record - 打 user tag
trial_bonus_expired - 推送弹窗(文案写「Trial balance has been cleared」)
TrialRewardEntryLogic 在 entry/status/withdraw-click 三条路径同样调用清零。
这与需求文档 03_wallet_fund_flow.md「不再产生 TRIAL_BONUS_EXPIRE」不一致。wallet 侧 isTrialPhase 在超期后已返回 false,体验金留在 frozen_bonus 但无法用于试玩下注;需在 console 启动接口 显式拦截。
目标行为
flowchart TD
subgraph wsConnect [WS连接事件]
A[未充值且体验期已过] --> B[打 user tag trial_bonus_expired]
B --> C[推送 WS 弹窗一次]
A --> D[不调用 wallet expireTrialBalance]
A --> E[不调用 activity trial-balance/expire]
end
subgraph gameLaunch [game/launch 与 game/login]
F[未充值且体验期已过] --> G[拒绝启动 BusinessException]
H[已充值或仍在体验期内] --> I[正常 launch]
end
| 场景 | 余额 | activity 记录 | user tag | 进游戏 |
|---|---|---|---|---|
| 体验期内、未充值 | 保留 | 保留 | 无 | 允许 |
| 体验过期、未充值 | 保留 frozen_bonus | 保留 | 标记过期 | 拒绝 |
| 已充值 | 按首充规则 | 按首充规则 | 不处理 | 允许 |
实现步骤
1. 收敛「到期处理」到仅标识(TrialBalanceExpiryService)
文件:slot-console/app/service/trial/TrialBalanceExpiryService.php
- 新增
markTrialExpiredIfNeeded(int $uid, string $source, string $currency, int $organization): bool:- 已充值 → 直接返回
false resolveWalletSnapshot+resolveTrialBalanceExpiry未过期 →false- 已过期 → 仅
markTrialBonusExpiredUserTag($uid),返回true - 不调用
expireTrialBalance、不调用markActivityTrialBalanceExpired
- 已充值 → 直接返回
- 新增
isTrialPlayBlocked(int $uid, string $source, string $currency, int $organization): bool(供 launch 守卫复用):- 逻辑:
!has_recharged && resolveTrialBalanceExpiry(...).expired
- 逻辑:
- 新增
ensureCanLaunchGame(...):当isTrialPlayBlocked为真时throw new BusinessException(...) clearExpiredTrialBalanceIfNeeded保留方法体但 删除所有调用方(避免误用);类注释改为「到期判定与标识」,去掉「清零」表述markActivityTrialBalanceExpired可保留 private 方法(历史兼容),但本需求下不再被调用
2. 改写 WS 连接处理
文件:slot-console/app/service/trial/TrialBalanceExpiryConnectService.php
- 删除
clearExpiredTrialBalanceIfNeeded及wasBalanceCleared/hadNoTrialBalance分支 - 流程简化为:
- user tag 已标记 → return(幂等防重复弹窗)
- 已充值 → return
- 未过期 → return
markTrialBonusExpiredUserTag+WsService::notifyClientPOP+ info 日志
- 更新类 PHPDoc:「检测试玩到期:打 user tag、推送弹窗(不清零余额)」
3. 入口 Logic 停止清零并修正 trial_balance_expired
文件:slot-console/app/api/logic/TrialRewardEntryLogic.php
- 在
buildEntryPayload/buildStatusPayload/resolveWithdrawClick中:- 移除
clearExpiredTrialBalanceIfNeeded调用及trialBalanceBeforeClear相关刷新逻辑 trial_balance_expired改为:$trialExpiry['expired'] && !$walletSnapshot['has_recharged'](不再依赖bonus_amount <= 0)
- 移除
- 删除 private
clearExpiredTrialBalanceIfNeeded方法 - 移除对
TrialExpiredBalanceClearCommand的 use(DTO 可保留文件以免大范围删除,但无引用)
4. game/launch 与 game/login 拦截
文件:slot-console/app/api/logic/GameLogic.php
- 构造注入或懒加载
TrialBalanceExpiryService launch()开头调用ensureCanLaunchGame($dto->uid, source, currency, organization)- source/currency/organization 从
GameLaunchDTO或userEntity读取(与 wallet 快照现有参数对齐)
- source/currency/organization 从
GameController::login在调用SlotPlatformService::login前同样守卫(deprecated 路径仍可能被launchByGameId使用)
错误处理:抛 Webman\Exception\BusinessException,消息使用新常量;api/exception/Handler 已注册,前端 useGameLaunch 会 toast 该 message。
5. 常量与文案
文件:slot-console/app/constants/TrialRewardEntryConstants.php
- 更新
POPUP_MESSAGE_TRIAL_BALANCE_EXPIRED:去掉「balance has been cleared」,改为体验期结束、需充值后才能继续游戏(英文与产品口径一致) - 新增
GAME_LAUNCH_BLOCKED_MESSAGE(launch 拒绝文案,可与弹窗语义一致)
CLEAR_SOURCE_* 常量暂保留(activity 接口仍存在,仅本链路不再调用)。
6. 不改动的服务
- slot-wallet:不删
expireTrialBalanceAPI(历史兼容),本需求不再调用 - slot-activity:
trial-balance/expireinnerapi 保留,本需求不再调用 - slot-pwa:按你的选择不拦截
- lobby:依赖 launch API 错误 message 即可,无需必改
关键代码对照
WS 连接当前清零调用(将删除):
$clearOutcome = $this->trialBalanceExpiryService->clearExpiredTrialBalanceIfNeeded(
new TrialExpiredBalanceClearCommand(
$uid,
$channelSource,
$currency,
$organization,
$walletSnapshot,
[]
),
TrialRewardEntryConstants::CLEAR_SOURCE_WS_CONNECT
);
入口当前过期判定(将修改):
'trial_balance_expired' => $walletSnapshot['bonus_amount'] <= 0 && $trialExpiry['expired'],
验证要点
- 模拟未充值用户、
wallet.created_at超过配置validity_hours:WS 连接一次 → user tag 写入、收到弹窗、bonus 余额不变、无TRIAL_BONUS_EXPIRE流水 - 再次 WS 连接 → 无重复弹窗(tag 幂等)
- 同用户调用
POST /api/game/launch→ BusinessException,不返回 url - 同用户
GET /api/trial-reward/entry→trial_balance_expired=true,trial_balance仍 > 0 - 已充值用户超体验窗口 → launch 正常、WS 不弹窗
- 收尾跑
slot-backend-completion-report与 verify 脚本