Files
cursor/plans/修复第一档绑卡类型_1c86ae8f.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

116 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: 修复第一档绑卡类型
overview: "`WithdrawService::apply` 在 Free Credits 第一档(`package_id > 0`)分支把 `checkBankInfo` 返回的收款配置数组传给了需要 `UserBankCardModel``applyFreeCreditsFirstCashout`,导致 PHP 8 类型错误且 Pay 载荷取不到 `btc/usdt/email` 等字段。"
todos:
- id: refactor-checkBankInfo-return
content: WithdrawService::checkBankInfo 返回 ['model' => UserBankCardModel, 'config' => itemConfig] 并补 PHPDoc
status: cancelled
- id: fix-apply-branch
content: WithdrawService::apply 解构返回值FC 传 model普通提现用 config
status: cancelled
- id: run-integration-test
content: php82 跑 FreeCreditsFirstCashoutApplyTest 验证无 TypeError
status: completed
isProject: false
---
# 修复第一档提现绑卡类型不匹配
## 问题
[`WithdrawService::apply`](slot_console/app/service/WithdrawService.php) 中:
```171:175:slot_console/app/service/WithdrawService.php
$bankInfo = $this->checkBankInfo($applyDTO);
if ($applyDTO->package_id > 0) {
return $this->applyFreeCreditsFirstCashout($applyDTO, $bankInfo);
}
```
[`checkBankInfo`](slot_console/app/service/WithdrawService.php) 在持久化 `UserBankCardModel` 后 **返回的是按支付类型整理的 `$itemConfig` 数组**(约 353 行 `return $itemConfig`),供普通提现填 `WithdrawalInfo`
```216:219:slot_console/app/service/WithdrawService.php
$withdrawalInfo->account = $bankInfo['account'];
$withdrawalInfo->address = $bankInfo['account'];
$withdrawalInfo->userName = $bankInfo['user_name'] ?? $userTag->uid;
$withdrawalInfo->card_number = $bankInfo['card_number'] ?? '';
```
而 [`applyFreeCreditsFirstCashout`](slot_console/app/service/WithdrawService.php) / [`FreeCreditsLogic::buildFirstCashoutWithdrawalInfo`](slot_console/app/api/logic/FreeCreditsLogic.php) 签名要求 **`UserBankCardModel`**,并读取模型字段:
```490:507:slot_console/app/api/logic/FreeCreditsLogic.php
'userName' => $post['user_name'] ?? $bank->user_name ?? strval($uid),
'account' => empty($bank->card_number) ? strval($uid) : $bank->card_number,
...
if ($payType === 2) {
$withdrawalInfo->address = $bank->btc ?? '';
} elseif ($payType === 3) {
$withdrawalInfo->address = $bank->usdt ?? '';
} elseif ($payType === 6) {
$withdrawalInfo->userName = trim($bank->paypal_first_name . ' ' . $bank->paypal_last_name);
$withdrawalInfo->account = $bank->email ?? '';
```
因此第一档路径在 PHP 8 下会触发 `TypeError`;即便未开严格类型,用数组当对象也会导致 Pay 下单字段错误。
```mermaid
flowchart LR
apply[WithdrawService.apply]
checkBank[checkBankInfo]
saveModel[save UserBankCardModel]
returnConfig["return itemConfig array"]
fcBranch[package_id greater than 0]
normalBranch[normal withdraw]
fcMethod[applyFreeCreditsFirstCashout]
logic[buildFirstCashoutWithdrawalInfo]
apply --> checkBank
checkBank --> saveModel --> returnConfig
returnConfig --> fcBranch
returnConfig --> normalBranch
fcBranch -->|"wrong: array"| fcMethod
fcMethod --> logic
logic -->|"expects UserBankCardModel"| modelFields[bank.card_number btc usdt]
```
## 推荐改法(单文件、无二次查询)
在 [`WithdrawService.php`](slot_console/app/service/WithdrawService.php) 调整 `checkBankInfo` 返回值,使 `apply` 能同时满足两条路径:
1. **`checkBankInfo` 返回结构体**(关联数组即可,无需新 DTO
- `model` → 已 `save()` 的 `UserBankCardModel`
- `config` → 现有 `$itemConfig`(普通提现继续用)
2. **`apply` 解构**
- `package_id > 0` → `applyFreeCreditsFirstCashout($applyDTO, $bank['model'])`
- 否则 → `$bankConfig = $bank['config']`,后续 `account` / `user_name` / `card_number` 逻辑不变
3. **补 PHPDoc**(符合 [`php-doc.mdc`](/Users/ray/.cursor/rules/php-doc.mdc)
- `checkBankInfo`: `@return array{model: UserBankCardModel, config: array<string, mixed>}`
- `applyFreeCreditsFirstCashout`: 保持现有 `@param UserBankCardModel`
**不改动** `FreeCreditsLogic`:其契约(绑卡已由 `WithdrawService` 写入后传入模型)是正确的。
### 备选(更小 diff多一次查询
若不想改 `checkBankInfo` 签名,可在 `package_id > 0` 分支先调用 `checkBankInfo` 落库,再 `find($uid)` 取模型。可行但冗余,不推荐。
## 测试
- 现有集成测 [`FreeCreditsFirstCashoutApplyTest`](slot_console/tests/Integration/FreeCreditsFirstCashoutApplyTest.php) 已走 `WithdrawService::apply` + `package_id`;修复后应能越过 `TypeError`,继续表现为 Pay 不可用时的 `Throwable` / 余额校验未触发。
- 修复后在 `php82` 容器执行:
```bash
docker exec -w /app/www/slot/slot_console php82 ./vendor/bin/phpunit tests/Integration/FreeCreditsFirstCashoutApplyTest.php
```
(需 `RUN_DB_TESTS=1` 时按项目惯例配置环境变量。)
可选:在 `tests/Unit` 增加轻量测试,用反射调用 `checkBankInfo` 断言返回含 `model` 与 `config` 键——非必须,集成测已覆盖主路径。
## 验收
1. 第一档 `POST /api/withdraw/apply` + `package_id` 不再出现 `UserBankCardModel` 类型错误。
2. 普通提现(无 `package_id`)行为与字段映射不变。
3. Pay 下单能正确带上 `card_number` / `btc` / `usdt` / PayPal 等模型字段(与 `checkBankInfo` 写入一致)。