--- name: firstCashout 合并评估 overview: 客户端入参与普通提现几乎一致(仅多 package_id、不传 amount),推荐在 WithdrawController::apply 做薄入口合并并复用 WithdrawValidator;编排仍留 FreeCreditsLogic,不并入 WithdrawService::apply 内部。 todos: - id: merge-withdraw-entry content: WithdrawController::apply 增加 package_id 分支,委托 FreeCreditsLogic::firstCashout;复用 WithdrawValidator 新增 scene(type 1/2/3/6 + package_id,无 amount) status: completed - id: align-bank-persist content: firstCashout 改为复用 WithdrawService::checkBankInfo(或抽 helper),与普通提现一致写绑卡信息 status: completed - id: deprecate-fc-endpoint content: /api/free-credits/first-cashout 保留作兼容 alias 或标记 deprecated,文档指向 /api/withdraw/apply?package_id= status: completed - id: keep-logic-split content: FreeCreditsLogic 仍负责 package 状态机 + bizType;WithdrawService::apply 不增加 Free Credits 分支 status: completed isProject: false --- # firstCashout 合并进现有提现接口 — 修订评估 ## 用户反馈:客户端参数基本一致 对照 [`WithdrawValidator`](slot_console/app/api/validator/WithdrawValidator.php) 与 [`FreeCreditsValidator::SCENE_FIRST_CASHOUT`](slot_console/app/api/validator/FreeCreditsValidator.php): | 字段 | 普通提现 apply | Free Credits firstCashout | |------|----------------|---------------------------| | `type` | require (1/2/3/6) | require (1/2/3/6) | | `pay_net` | require (1/2/3) | Logic 使用,Validator scene 未含(可补齐) | | `user_name` / `cash_tag` | type=1 时 require | post 传入,Logic 读取 | | `btc` / `usdt` | type=2/3 时 require | 同上 | | `paypal_*` / `email` | type=6 时 require | 同上 | | `amount` | **require,用户输入** | **不传,服务端取 package 金额** | | `package_id` | 无 | **require,活动档位 id** | **结论**:C 端独立提现页(需求 §11)本来就是对普通提现页的精简——同一套收款字段,只是隐藏 amount 输入框。从接口契约看,**完全可以用同一个 apply 入口**,用 `package_id` 有无区分业务类型。 --- ## 仍建议合并的范围:入口 + 校验 + 组单,不是 WithdrawService 内部 ```mermaid flowchart TB Client["C 端 POST /api/withdraw/apply"] Client --> Branch{package_id 存在?} Branch -->|是| FC["FreeCreditsLogic::firstCashout"] Branch -->|否| WS["WithdrawService::apply"] FC --> Pay["PayService::apply bizType=free_credit_first_cashout"] WS --> Pay2["PayService::apply 普通"] Pay --> PayEntity["WithdrawalOrderEntity::apply 已统一"] Pay2 --> PayEntity ``` ### 可以合并(推荐) 1. **统一入口**:[`WithdrawController::apply`](slot_console/app/api/controller/WithdrawController.php) 检测 `package_id`,有则委托 `FreeCreditsLogic::firstCashout`,无则走 `WithdrawService::apply`。 2. **统一校验**:在 `WithdrawValidator` 新增 scene,与普通 apply 对称,仅把 `amount` 换成 `package_id`: - `SCENE_APPLY_CASH_FC` => `['package_id', 'type', 'user_name', 'cash_tag']` - `SCENE_APPLY_BTC_FC` => `['package_id', 'type', 'btc']` - 等 3. **统一绑卡写库**:`firstCashout` 目前只读 `UserBankCardModel`;普通提现通过 `WithdrawService::checkBankInfo` 会更新绑卡。合并入口后应 **复用同一绑卡逻辑**,避免两套行为。 4. **统一 DTO**:`WithdrawApplyDTO` 增加可选 `package_id` 字段即可,不必维护两套 post 结构。 ### 不应合并进 WithdrawService::apply 编排差异仍在 Logic 层,不应塞进 [`WithdrawService::apply`](slot_console/app/service/WithdrawService.php): | 仍分离的逻辑 | 原因 | |-------------|------| | 金额 | 普通:用户 amount;FC:package->amount_qf | | 余额/手续费/VIP/黑规则 | 普通:checkInfo + getAmountAndFee;FC:跳过 | | 活动状态 | FC:markFirstCashoutProcessing / 失败回滚 | | pay 回调 | 已通过 bizType 在 pay 层分支,无需 console 再分 | --- ## 推荐实现(修订后方案 B) [`WithdrawController::apply`](slot_console/app/api/controller/WithdrawController.php): ```php public function apply(Request $request) { $post = $request->post(); $type = input('type', 1); if (!empty($post['package_id'])) { // 复用 WithdrawValidator 的 FC scene(无 amount) $error = $this->validate(WithdrawValidator::SCENE_APPLY_CASH_FC /* 按 type */, $post); if ($error !== true) { return $this->errorCode(ErrorCode::PARAMS_ERROR, $error); } return $this->success( (new FreeCreditsLogic())->firstCashout( $request->userEntity->uid, (int) $post['package_id'], $post ), 'Submitted successfully! ...' ); } // 原有普通提现 $error = $this->validate($type, $post); // ... } ``` [`FreeCreditsLogic::firstCashout`](slot_console/app/api/logic/FreeCreditsLogic.php) 内部改动: - 绑卡:改为调用 `WithdrawService` 的 `checkBankInfo`(需将 `checkBankInfo` 改为 `protected` 公开方法,或抽到 helper)。 - 其余不变:package 校验、固定金额、`bizType`、状态机。 [`FreeCreditsController::firstCashout`](slot_console/app/api/controller/FreeCreditsController.php): - 保留为 **兼容 alias**(内部同样调 Logic),或直接 deprecated 指向 withdraw apply。 --- ## 与初版评估的差异 | 初版 | 修订 | |------|------| | 方案 A 推荐保持双入口 | **方案 B 升为推荐** — 参数一致,双入口无必要 | | 强调「参数/校验不同故难合并」 | 参数 **高度重合**,差异仅 `package_id` vs `amount`;校验可共用 Validator scene | | 合并障碍在入口层 | 合并障碍仅在 **WithdrawService 内部编排**,入口层应合并 | --- ## 验收 - C 端独立提现页调用 `POST /api/withdraw/apply`,传 `package_id + type + 收款字段`,**不传 amount** - 普通提现不传 `package_id`,行为与现网一致 - Free Credits 仍不走 `withdrawFrozen`,回调仍更新 package/player - 绑卡信息与走普通 apply 后一致落库