10 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 首充定格资金修复 | 本次仅改 slot_wallet 与 slot_console。wallet 删除 Recharge bus、首充发 free_credit_init;console 消费该事件完成定格。pay 等其它服务不在本次范围。 |
|
false |
首充定格资金操作修复方案(修订 v4)
变更范围(硬约束)
本次仅编辑以下仓库/服务,不修改任何其它服务(含 slot_pay、slot_lib 等):
| 在范围内 | 不在范围内 |
|---|---|
slot_wallet |
slot_pay |
slot_console |
slot_lib、slot_agent、… |
Recharge总线消息假定由 pay 或其它既有链路 发送;本次不从 wallet 重复发送,也不改 pay 去补发。若线上 pay 未发Recharge,统计/档位问题需另开 pay 任务,不纳入本 PR。
设计原则
情愿用户定格失败,也不能让系统亏钱。
| 服务(本次) | 职责 |
|---|---|
| slot_wallet | 入账;首充发 free_credit_init;删除 Recharge bus;移除 CreateWagerTask 旧首充打码拆分 |
| slot_console | 消费 free_credit_init → 定格扣款 + 活动落库;RechargeEvent 不再做首充定格 |
目标架构
sequenceDiagram
participant Ext as 外部_pay等_本次不改
participant Wallet as slot_wallet
participant MQ as console_bus
participant Console as slot_console
Ext->>Wallet: recharge / rechargeSign
Wallet->>Wallet: 采 balance_before_qf,入账
Wallet->>MQ: free_credit_init
Ext->>MQ: Recharge(本次不实现)
MQ->>Console: FreeCreditInitEvent
Console->>Wallet: freeCreditsFreeze RPC
Console->>Console: player/package 落库
MQ->>Console: RechargeEvent(既有逻辑,无定格)
实现步骤
1. slot_wallet
1.1 删除 Recharge bus
从 WalletLogic::recharge()、rechargeSign() 移除:
$this->sendConsoleBus('Recharge', $this->requestDTO->recharge);
保留 sendConsoleBus('reward', ...) 及其它非 Recharge 类型(本次不动)。
1.2 maybeSendFreeCreditInit() + 扩展 sendConsoleBus
- 改账/
inc()前:balance_before_qf、is_first_recharge(total_deposit == 0,在statModel->inc之前判断)。 - 改账成功后:
is_first_recharge && balance_before_qf > 0时发送:
$this->sendConsoleBus('free_credit_init', 0, [
'balance_before_qf' => $balanceBeforeQf,
'recharge_amount' => $this->requestDTO->recharge,
]);
sendConsoleBus()增加可选参数array $extraData = []。
1.3 recharge() 与 rechargeSign() 均接入
签到购买 rechargeSign() 与普通 recharge() 使用同一套 maybeSendFreeCreditInit() 逻辑。
1.4 移除 CreateWagerTask 旧首充打码逻辑(已废弃)
app/command/CreateWagerTask.php 在 Free Credits 上线前 于首充时本地拆分余额打码,与现「console 定格 + 分档释放」重复且易冲突,本次删除。
旧逻辑位置(条件均为 RechargeExchangeService::total 累计充值等于本笔 recharge_amount,即首充):
| 方法 | 行号(约) | 行为 |
|---|---|---|
version1() |
L87–140 | SOURCE_TYPE_FIRST_RECHARGE 任务 + SOURCE_TYPE_FREE 免打码任务 + SOURCE_TYPE_FIRST_LEFT「首充剩余」打码 |
version2() |
L186–244 | 首充充值/赠送打码 + SOURCE_TYPE_FIRST_LEFT(first_recharge_left 系数) |
与新方案关系:
- 充值前免费余额 → 由 console
free_credit_init→freeCreditsFreeze扣出活动池(不再在 wallet 侧拆FREE/FIRST_LEFT任务)。 - 免打码第一档 / 后续释放 → 由 console
FreeCreditsLogic+freeCreditsClaim创建 Y1(WalletLogic::freeCreditsClaim内createTask)。 - 首充本笔充值金额的打码 → 与其它充值相同,走
elseif ($dto->required_wager > 0)通用分支即可。
改动要点:
- 删除
version1/version2中整段if ($entity->recharge > 0 && $entity->recharge == $dto->recharge_amount) { ... }。 - 首充与普通充值统一落入后续
elseif ($dto->required_wager > 0)(version1L142+、version2L246+)。 - 保留其中对
SOURCE_TYPE_BUY_SIGN(购买签到解锁额度为 0)的处理——该逻辑在elseif分支内已有,无需首充专用块。 - 删除后确认无引用孤立的
SOURCE_TYPE_FIRST_RECHARGE/SOURCE_TYPE_FIRST_LEFT首充专用路径(常量可保留供历史任务读)。
2. slot_console
2.1 EventBus 注册 free_credit_init
EventBus::deal() 增加显式分支(类名不能走 default 动态加载):
case 'free_credit_init':
(new FreeCreditInitEvent())->handle($busEntity);
break;
新建 app/command/event/FreeCreditInitEvent.php。
2.2 FreeCreditsLogic::handleFreeCreditInit
- 入参:
uid、balance_before_qf、wallet_amount、orderId(来自 busdata)。 frozenAmount = max(balance_before_qf, 0);不以充值后再读余额反推为主路径。- 活动未开启 / 已定格 → 幂等 return。
- 调用调整后的
freezeFirstRecharge()。
2.3 调整 freezeFirstRecharge(先扣款、后落库)
- 幂等:已有
free_credits_freeze:{orderId}流水则跳过 RPC。 frozenAmount = min(事件金额, RPC 前当前可扣余额);≤0 不扣。- 先
freeCreditsFreezeRPC,后Db::transaction写 player/packages。 - RPC 失败 → 不落库,抛异常。
2.4 RechargeEvent 去掉首充定格
RechargeEvent::handle() 删除 L73-82 对 handleRecharge 的调用(首充定格改由 free_credit_init 触发)。
保留并可继续调用 仅档位推进 的逻辑,例如:
- 新增
FreeCreditsLogic::advanceAfterRecharge($uid, $walletAmount),或 handleRecharge内去掉首充freezeFirstRecharge分支,仅保留advanceByRecharge(供既有Recharge消息使用)。
统计、黑名单、代理首充等 RechargeEvent 现有代码不动(本次范围外行为保持)。
2.5 MQ 可靠性(仅 console)
FreeCreditInitEvent/free_credit_init:异常上抛;EventBus对该 type 失败时 nack/requeue(需对齐现有 consumer)。Recharge路径统计块仍可独立 try/catch(本次不改 pay 发消息前提)。
3. 测试(仅 wallet + console)
| 用例 | 位置 |
|---|---|
| wallet 删除 Recharge bus | slot_wallet |
wallet 首充发 free_credit_init(含 rechargeSign) |
slot_wallet |
| 首充不再走 CreateWagerTask 特殊分支 | slot_wallet CreateWagerTask |
FreeCreditInitEvent 定格成功 |
slot_console 集成测 |
| RPC 失败不落库 / 先扣后落库 / 幂等 | slot_console |
RechargeEvent 不再触发定格 |
调整 FreeCreditsHandleRechargeTest 等 |
不新增 pay 侧联调用例。
关键改动文件(仅此两份)
slot_wallet
slot_console
app/command/EventBus.phpapp/command/event/FreeCreditInitEvent.php(新建)app/api/logic/FreeCreditsLogic.phpapp/command/event/RechargeEvent.php- 相关 tests(console 仓内)
验收标准(本 PR)
- wallet:
recharge/rechargeSign不再发送type=Recharge;首充且 inc 前有免费余额时发送free_credit_init,balance_before_qf正确。 - wallet:首充不再触发
CreateWagerTask的FIRST_RECHARGE/FREE/FIRST_LEFT拆分,仅按本笔充值/赠送金额走通用打码任务。 - console:收到
free_credit_init后完成定格扣款与落库;扣款 ≤ 事件金额且 ≤ 可扣余额;幂等。 - console:
RechargeEvent不再执行首充定格;已定格用户经Recharge仍可advanceByRecharge(依赖外部 pay 发消息,本 PR 不验证 pay)。 - 范围:
git diff仅涉及slot_wallet、slot_console路径。