ok
This commit is contained in:
115
plans/修复第一档绑卡类型_1c86ae8f.plan.md
Normal file
115
plans/修复第一档绑卡类型_1c86ae8f.plan.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
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` 写入一致)。
|
||||
Reference in New Issue
Block a user