Files
cursor/plans/firstcashout_合并评估_df95dacf.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

6.1 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
firstCashout 合并评估 客户端入参与普通提现几乎一致(仅多 package_id、不传 amount推荐在 WithdrawController::apply 做薄入口合并并复用 WithdrawValidator编排仍留 FreeCreditsLogic不并入 WithdrawService::apply 内部。
id content status
merge-withdraw-entry WithdrawController::apply 增加 package_id 分支,委托 FreeCreditsLogic::firstCashout复用 WithdrawValidator 新增 scenetype 1/2/3/6 + package_id无 amount completed
id content status
align-bank-persist firstCashout 改为复用 WithdrawService::checkBankInfo或抽 helper与普通提现一致写绑卡信息 completed
id content status
deprecate-fc-endpoint /api/free-credits/first-cashout 保留作兼容 alias 或标记 deprecated文档指向 /api/withdraw/apply?package_id= completed
id content status
keep-logic-split FreeCreditsLogic 仍负责 package 状态机 + bizTypeWithdrawService::apply 不增加 Free Credits 分支 completed
false

firstCashout 合并进现有提现接口 — 修订评估

用户反馈:客户端参数基本一致

对照 WithdrawValidatorFreeCreditsValidator::SCENE_FIRST_CASHOUT

字段 普通提现 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 内部

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 检测 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. 统一 DTOWithdrawApplyDTO 增加可选 package_id 字段即可,不必维护两套 post 结构。

不应合并进 WithdrawService::apply

编排差异仍在 Logic 层,不应塞进 WithdrawService::apply

仍分离的逻辑 原因
金额 普通:用户 amountFCpackage->amount_qf
余额/手续费/VIP/黑规则 普通checkInfo + getAmountAndFeeFC跳过
活动状态 FCmarkFirstCashoutProcessing / 失败回滚
pay 回调 已通过 bizType 在 pay 层分支,无需 console 再分

推荐实现(修订后方案 B

WithdrawController::apply

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 内部改动:

  • 绑卡:改为调用 WithdrawServicecheckBankInfo(需将 checkBankInfo 改为 protected 公开方法,或抽到 helper
  • 其余不变package 校验、固定金额、bizType、状态机。

FreeCreditsController::firstCashout

  • 保留为 兼容 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 后一致落库