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

11 KiB
Raw Permalink Blame History


todos:

  • id: "phase0-prep" content: "Phase 0确认 minus() 死代码、补 PHPDoc、更新 README 入口索引" status: pending
  • id: "phase1-base-query-register" content: "Phase 1新建 AbstractWalletMutationLogic + WalletQueryLogic + WalletRegisterLogicWalletLogic 委托 register/query" status: pending
  • id: "phase2-bet-win" content: "Phase 2新建 WalletBetWinLogic迁移 bet/win 及 Redis round 辅助逻辑" status: pending
  • id: "phase3-recharge" content: "Phase 3新建 WalletRechargeLogic迁移 inc/recharge/reward 与 Trial Pool 充值链" status: pending
  • id: "phase4-withdraw-trial" content: "Phase 4新建 WalletWithdrawLogic + WalletTrialLogic修复 switchBonus 路由(如需要)" status: pending isProject: false

WalletLogic 分阶段拆分方案

现状诊断

slot-wallet/app/api/logic/WalletLogic.php 当前 1885 行,承担了钱包服务几乎全部资金用例编排:

主要方法 约行数 已有下沉
路由门面 run, runRechargeOrder, ACTION_METHOD_MAP ~80
注册 register, initWalletWithoutMoney ~120 RegisterService
下注/派奖 bet, win, pending win Redis, bet split ~450 BetService, WinService
入账/充值 inc, recharge, rechargeSign, reward, Trial Pool ~400 RechargeFundLotService
提现/Bonus 转换 withdraw*, rollbackWithdraw, bonusToDeposit, switchBonus ~350 WithdrawTaskService
Trial 体验金 grantTrial, expireTrial ~250
查询 query, queryBizLog (static) ~70
公共能力 addLog, maxRetry, sendConsoleBus, getBalance ~200

问题:单文件混合 6+ 业务域事务边界、幂等、Redis 辅助状态交织Review 和改动风险都高。

已有良好先例:同目录 GrantLogicPlayerTaskLogic 已是「一用例一 Logic」核心扣款/派奖细节已在 Service 层Logic 层再拆是合理下一步。

额外发现(非本次必做):minus() 未出现在 ACTION_METHOD_MAP 且无调用方,疑似历史遗留,可在 Phase 0 确认后删除。


目标架构

flowchart TB
    subgraph controller [Controller 不变]
        WC[WalletController]
    end

    subgraph facade [门面层]
        WL[WalletLogic]
    end

    subgraph domain [子 Logic 按域]
        WQ[WalletQueryLogic]
        WRg[WalletRegisterLogic]
        WBw[WalletBetWinLogic]
        WRe[WalletRechargeLogic]
        WWd[WalletWithdrawLogic]
        WTr[WalletTrialLogic]
    end

    subgraph shared [共享]
        Base[AbstractWalletMutationLogic]
    end

    subgraph service [已有 Service 不动]
        BS[BetService]
        WS[WinService]
        RS[RegisterService]
    end

    WC --> WL
    WL --> WRg & WBw & WRe & WWd & WTr
    GrantLogic --> WQ
    WL --> WQ
    WRg & WBw & WRe & WWd & WTr --> Base
    WBw --> BS & WS
    WRg --> RS

原则(对齐 backend-layering

  • Logic 拆用例、Service 保公共能力:不再新建「只做 Model 转发」的 Service。
  • WalletLogic 只做分发 + 缓存清理:保留 run() / runRechargeOrder() 对外签名;ACTION_METHOD_MAP 改为指向子 Logic 方法。
  • Controller 不改:继续只注入 WalletLogic(你已确认)。
  • 共享状态收敛:子 Logic 继承抽象基类,统一持有 WalletUpdateRequestDTOrechargeOrderDto 仅留在 WalletRechargeLogic

共享基类设计

新建 slot-wallet/app/api/logic/AbstractWalletMutationLogic.php

abstract class AbstractWalletMutationLogic
{
    protected WalletUpdateRequestDTO $requestDTO;

    /** 绑定本次 mutation 请求上下文 */
    protected function bindRequest(WalletUpdateRequestDTO $requestDTO): void { ... }

    /** 写 wallet_log、PWA 流水、乐观锁重试、Console Bus 等 */
    protected function addLog(...): int { ... }
    protected function addTransactionRecord(...): void { ... }
    protected function getBalance(WalletAccountModel $model): int { ... }
    protected function maxRetry(callable $callback, int $retryCount = 3): WalletEntity { ... }
    protected function sendConsoleBus(string $type, int $amount): void { ... }
    protected function initWalletWithoutMoney(): ?WalletAccountModel { ... }
}
  • 从现有 WalletLogic 原样迁移上述 protected/private 方法,避免行为变化。
  • 子 Logic 方法签名改为显式接收 DTO 或在门面 bindRequest() 后调用,不再依赖 $this->requestDTO 隐式全局状态跨文件散落

子 Logic 划分

新类 职责 从 WalletLogic 迁出的方法
WalletQueryLogic 只读查询 query, queryBizLog
WalletRegisterLogic 注册赠金 register
WalletBetWinLogic 游戏下注/派奖编排 bet, win, executeTrialBet/Win, executeFreeSpinPaidBet, pending win / bet split Redis, getWinAllocationByRound, buildBetSplitRemark
WalletRechargeLogic 入账/充值 inc, executeIncWithTransaction, recharge, rechargeSign, reward, Trial Pool 扣减链, resolveRechargeOrderDtoForLots, insertRechargeFundLotsIfNeeded
WalletWithdrawLogic 提现与 Bonus 桶转换 withdraw, withdrawFrozen, rollbackWithdraw, doneWithdraw, bonusToDeposit, switchBonus
WalletTrialLogic Trial 体验金生命周期 grantTrial, expireTrial, resolveTrialAmount, makeTrialPoolBizId, buildTrialPoolRemark, deductTrialPoolInRechargeTransaction(若仍被 Recharge 调用则保留在 Recharge 或抽 TrialPoolSupport trait

Trial Pool 边界planTrialPoolDeductionForRecharge / finalizeTrialPoolAfterRechargeInc 与充值事务强耦合,建议 Phase 3 随 RechargeLogic 一起迁Trial 发放/过期独立进 WalletTrialLogic


门面 WalletLogic拆分后 ~150 行)

class WalletLogic
{
    public function __construct(
        private WalletRegisterLogic $registerLogic,
        private WalletBetWinLogic $betWinLogic,
        private WalletRechargeLogic $rechargeLogic,
        private WalletWithdrawLogic $withdrawLogic,
        private WalletTrialLogic $trialLogic,
    ) {}

    public function run(WalletUpdateRequestDTO $requestDTO) { /* 分发 + deleteWalletCache */ }
    public function runRechargeOrder(WalletRechargeRequestDTO $dto) { /* 委托 rechargeLogic */ }

    // 兼容 GrantLogic / 外部 static 调用
    public static function query(...) { return WalletQueryLogic::query(...); }
    public static function queryBizLog(...) { return WalletQueryLogic::queryBizLog(...); }
}

ACTION_METHOD_MAP 改为 Logic 实例 + 方法名callable 数组,例如:

WalletLogModel::BIZ_TYPE_BET => [$this->betWinLogic, 'bet'],

Webman DI 需在 config/ 或现有容器绑定中注册子 Logic若项目无自动注入门面构造函数内 new 亦可,与当前 GrantLogic 风格一致)。


分阶段实施(你已选 phased + facade

Phase 0准备低风险

  • WalletLogic 现有 public 方法补全/核对中文 PHPDoc拆分时会移动代码趁此对齐 php-clean-code)。
  • 确认 minus() 无调用后删除(或加 @deprecated 注释待下一版删)。
  • 更新 README.md「实现入口」一节,列出子 Logic 索引。

Phase 1Query + Register + 基类

  • 新建 AbstractWalletMutationLogicWalletQueryLogicWalletRegisterLogic
  • WalletLogic::query/queryBizLog 改为委托;GrantLogic 可继续 WalletLogic::query() 不动。
  • register 从 WalletLogic 迁出;run() 分发到 WalletRegisterLogic
  • 验收注册接口、余额查询、Grant 通知链路回归。

Phase 2BetWin最高复杂度

  • 新建 WalletBetWinLogic,迁移 bet/win 及 Redis round 状态方法。
  • WalletControllerbet/win 专用入口仍走 walletLogic->run(),行为不变。
  • 注意win() 内对 $requestDTO->fee 的临时修改必须在 BetWinLogic 内用 try/finally 保持,避免泄漏到其他域。
  • 验收:下注/派奖、Trial 阶段 bet/win、FreeSpin 代付、中间派奖 is_end=0、幂等 hit。

Phase 3Recharge / Inc

  • 新建 WalletRechargeLogic,迁移 inc 全链路 + recharge/rechargeSign/reward
  • runRechargeOrder 委托给 RechargeLogicrechargeOrderDto 生命周期)。
  • 验收:充值主链路、首充 Trial Pool 扣减、Fund Lot 落库、签到充值 sign

Phase 4Withdraw + Trial

  • 新建 WalletWithdrawLogicWalletTrialLogic
  • 补齐 ACTION_METHOD_MAP 中缺失的 switchBonus 映射(若 slot-sdk 仍在调 type=switchBonus,当前可能未路由到方法——拆分时可一并修复)。
  • 验收:提现冻结/成功/失败回滚、Bonus 转 Deposit、Trial 发放/过期。

不建议的做法

  • 不要把子用例再拆成 Logic 型 Service(如 WithdrawLogicService),违反分层红线。
  • 不要一次性改 Controller 注入多个 Logic,你已选 facade保持对外稳定。
  • 不要把 BetService/WinService 的业务编排再搬回 Logic 后又复制一份——子 Logic 只做事务、幂等、流水、MQ核心算法继续调用现有 Service。

预期收益

  • 单文件从 ~1900 行降至 门面 ~150 行 + 各子 Logic 200500 行
  • 改动 bet 不再误触 recharge 事务代码Review 范围清晰。
  • GrantLogic 风格统一,新人可按域定位代码。
  • 对外 API、WalletLogic::run() 签名、SDK 调用路径 零破坏

风险与缓解

风险 缓解
拆分引入行为回归 每 Phase 独立 PR优先复制代码再删旧代码不做顺手重构
$requestDTO 可变状态 基类 bindRequest() + 子 Logic 不跨用例复用实例
Webman 构造注入 若无 DIPhase 1 先在 WalletLogic 内 new 子 Logic后续再接线
Trial Pool 跨 Recharge/Trial Phase 3 完成 Recharge 后再动 Trial必要时抽 TrialPoolDeductionSupport trait 供 Recharge 专用

涉及文件

新建(均在 slot-wallet/app/api/logic/

  • AbstractWalletMutationLogic.php
  • WalletQueryLogic.php
  • WalletRegisterLogic.php
  • WalletBetWinLogic.php
  • WalletRechargeLogic.php
  • WalletWithdrawLogic.php
  • WalletTrialLogic.php

修改

  • WalletLogic.php — 瘦身为门面
  • README.md — 更新入口索引(可选 .cursor/rules/slot-wallet-prd-and-money.mdc 一行指向)

不改