1.优化提现接口/api/finance/withdrawCreate

This commit is contained in:
2026-05-20 12:01:07 +08:00
parent 91229f4477
commit b9e4d806f7
12 changed files with 219 additions and 13 deletions

View File

@@ -25,7 +25,7 @@ class WithdrawOrder extends Backend
protected bool $modelSceneValidate = true;
protected string|array $quickSearchField = ['id', 'order_no', 'idempotency_key', 'receive_type', 'receive_account', 'remark'];
protected string|array $quickSearchField = ['id', 'order_no', 'idempotency_key', 'pay_channel', 'receive_type', 'receive_account', 'ddpay_receiver_name', 'receiver_email', 'receiver_mobile', 'remark'];
protected string|array $defaultSortField = ['id' => 'desc'];
@@ -264,9 +264,13 @@ class WithdrawOrder extends Backend
} else {
$orderNo = is_string($fresh['order_no'] ?? null) ? trim($fresh['order_no'] ?? '') : strval($fresh['order_no'] ?? '');
$receiveType = is_string($fresh['receive_type'] ?? null) ? strtolower(trim($fresh['receive_type'] ?? '')) : '';
$payChannel = is_string($fresh['pay_channel'] ?? null) ? strtolower(trim($fresh['pay_channel'] ?? '')) : '';
if ($payChannel === '') {
$payChannel = 'ddpay';
}
// 当前仅接入 bank 类型出金(与移动端 withdrawCreate 校验一致)
if ($orderNo !== '' && $receiveType === 'bank') {
// 当前仅 ddpay + bank 类型自动出金(与移动端 withdrawCreate 校验一致)
if ($orderNo !== '' && $receiveType === 'bank' && $payChannel === 'ddpay') {
$base = \app\common\library\finance\DDPayGateway::publicBaseUrlForCallbacks($request);
if ($base === '') {
$base = 'https://' . strval($request->host());

View File

@@ -826,18 +826,38 @@ class Finance extends MobileBase
}
$withdrawCoinRaw = $request->post('withdraw_coin', '');
$withdrawCoin = is_string($withdrawCoinRaw) ? trim($withdrawCoinRaw) : (is_numeric($withdrawCoinRaw) ? strval($withdrawCoinRaw) : '');
$channelCode = strtolower($this->stringParam($request->post('channel_code')));
if ($channelCode === '') {
$channelCode = strtolower($this->stringParam($request->post('pay_channel')));
}
$receiveAccount = trim(is_string($request->post('receive_account', '')) ? $request->post('receive_account', '') : '');
$receiveType = trim(is_string($request->post('receive_type', '')) ? $request->post('receive_type', '') : '');
$receiveType = strtolower($receiveType);
// DDPAY 出金Payout所需扩展字段当前仅支持 receive_type=bank
$receiverName = trim(is_string($request->post('receiver_name', '')) ? $request->post('receiver_name', '') : '');
$receiverEmail = trim(is_string($request->post('receiver_email', '')) ? $request->post('receiver_email', '') : '');
$receiverMobile = trim(is_string($request->post('receiver_mobile', '')) ? $request->post('receiver_mobile', '') : '');
$bankCode = trim(is_string($request->post('bank_code', '')) ? $request->post('bank_code', '') : '');
$bankBranch = trim(is_string($request->post('bank_branch', '')) ? $request->post('bank_branch', '') : '');
$idempotencyKey = trim(is_string($request->post('idempotency_key', '')) ? $request->post('idempotency_key', '') : '');
if ($withdrawCoin === '' || $receiveAccount === '' || $receiveType === '' || $idempotencyKey === '') {
if ($withdrawCoin === '' || $channelCode === '' || $receiveAccount === '' || $receiveType === '' || $idempotencyKey === ''
|| $receiverEmail === '' || $receiverMobile === '') {
return $this->mobileError(1001, 'Missing parameters');
}
if (!in_array($channelCode, DepositChannelLib::withdrawPayoutChannelCodes(), true)) {
return $this->mobileError(2004, 'Withdraw only supports DDPay');
}
$effectiveChannels = $this->loadDepositChannelEffective();
if (!DepositChannelLib::assertChannelEnabled($channelCode, $effectiveChannels)) {
return $this->mobileError(2004, 'Pay channel not available');
}
if (mb_strlen($receiverEmail) > 255 || !filter_var($receiverEmail, FILTER_VALIDATE_EMAIL)) {
return $this->mobileError(1001, 'Invalid receiver email');
}
if (mb_strlen($receiverMobile) > 64 || !$this->isValidReceiverMobile($receiverMobile)) {
return $this->mobileError(1001, 'Invalid receiver mobile');
}
if (mb_strlen($idempotencyKey) > 64) {
return $this->mobileError(1002, 'Idempotency key is too long');
}
@@ -970,11 +990,14 @@ class Finance extends MobileBase
'idempotency_key' => $idempotencyKey,
'user_id' => $userId,
'channel_id' => $channelId,
'pay_channel' => $channelCode,
'amount' => $withdrawCoin,
'fee' => $feeCoin,
'actual_amount' => $actualArrivalCoin,
'receive_type' => $receiveType,
'receive_account' => $receiveAccount,
'receiver_email' => $receiverEmail,
'receiver_mobile' => $receiverMobile,
'ddpay_receiver_name' => $receiverName,
'ddpay_bank_name' => $ddpayBankName,
'ddpay_bank_branch' => $bankBranch,
@@ -1044,6 +1067,9 @@ class Finance extends MobileBase
'actual_arrival_coin' => $this->amountNumber($order->actual_amount ?? '0'),
'receive_type' => is_string($order->receive_type ?? null) ? $order->receive_type : strval($order->receive_type ?? ''),
'receive_account' => is_string($order->receive_account ?? null) ? $order->receive_account : strval($order->receive_account ?? ''),
'pay_channel' => is_string($order->pay_channel ?? null) ? $order->pay_channel : strval($order->pay_channel ?? ''),
'receiver_email' => is_string($order->receiver_email ?? null) ? $order->receiver_email : strval($order->receiver_email ?? ''),
'receiver_mobile' => is_string($order->receiver_mobile ?? null) ? $order->receiver_mobile : strval($order->receiver_mobile ?? ''),
'reject_reason' => $statusCode === 2 && $remark !== '' ? $remark : null,
'create_time' => $order->create_time,
'review_time' => $order->review_time,
@@ -1249,8 +1275,10 @@ class Finance extends MobileBase
$wc = $cfg['withdraw_copy'] ?? [];
$rateMode = is_array($wc) && isset($wc['rate_mode']) && is_string($wc['rate_mode']) ? $wc['rate_mode'] : 'fixed';
$payChannels = [];
$effectiveCh = DepositChannelLib::effectiveRowsFromDb();
$withdrawPayChannels = DepositChannelLib::channelsForWithdraw($effectiveCh, $lang);
$payChannels = [];
$regCh = DepositChannelLib::codeRegistry();
foreach ($effectiveCh as $row) {
if (!is_array($row)) {
@@ -1296,6 +1324,7 @@ class Finance extends MobileBase
'banks' => $depositBanks,
],
'withdraw' => [
'pay_channels' => $withdrawPayChannels,
'banks' => $withdrawBanks,
'min_ewallet' => $minEw,
'min_bank' => $minBk,
@@ -1312,8 +1341,11 @@ class Finance extends MobileBase
// 与 DDPay 出金及 withdrawCreate 一致,不由后台开关配置
'fields' => [
'receive_type_bank_only' => true,
'require_channel_code' => true,
'require_receiver_name' => true,
'require_receive_account' => true,
'require_receiver_email' => true,
'require_receiver_mobile' => true,
'require_bank_code' => true,
'require_bank_branch' => false,
],
@@ -1365,6 +1397,23 @@ class Finance extends MobileBase
return trim($raw);
}
/**
* 收款人手机号532 位,仅允许数字与常见分隔符(+ - 空格)
*/
private function isValidReceiverMobile(string $mobile): bool
{
$len = mb_strlen($mobile);
if ($len < 5 || $len > 32) {
return false;
}
if (!preg_match('/^[0-9+\-\s]+$/', $mobile)) {
return false;
}
$digits = preg_replace('/\D/', '', $mobile);
return is_string($digits) && strlen($digits) >= 5;
}
private function loadEnabledTiers(): array
{
$row = GameConfig::where('config_key', DepositTierLib::CONFIG_KEY)->find();

View File

@@ -47,6 +47,8 @@ return [
'Deposit tier not available' => 'The selected deposit tier is not available',
'Order not found after settle' => 'Order not found after settlement',
'Invalid withdraw amount' => 'Invalid withdraw amount',
'Invalid receiver email' => 'Invalid receiver email',
'Invalid receiver mobile' => 'Invalid receiver mobile',
'Withdraw exceeds available bet flow' => 'The withdraw amount exceeds the available bet-flow quota',
'Too many pending deposit orders' => 'You already have multiple pending deposit orders, please complete payment first or wait for timeout',
'Too many pending withdraw orders' => 'You already have withdraw orders under review, please wait for them to be processed',
@@ -58,6 +60,7 @@ return [
'Pay channel not available for this currency' => 'The payment channel is not available for this currency',
'DDPay deposit initiation failed' => 'DDPay deposit initiation failed',
'Deposit only supports DDPay' => 'Only DDPay deposits are supported (channel_code must be ddpay)',
'Withdraw only supports DDPay' => 'Only DDPay withdrawals are supported (channel_code must be ddpay)',
// Member center account
'Data updated successfully~' => 'Data updated successfully~',
'Password has been changed~' => 'Password has been changed~',

View File

@@ -79,6 +79,8 @@ return [
'Deposit tier not available' => '所选充值档位不可用',
'Order not found after settle' => '充值成功后未找到订单',
'Invalid withdraw amount' => '提现金额不合法',
'Invalid receiver email' => '收款人邮箱格式不正确',
'Invalid receiver mobile' => '收款人手机号格式不正确',
'Withdraw exceeds available bet flow' => '提现金额超出可提现额度',
'Too many pending deposit orders' => '存在多笔待支付充值订单,请先完成支付或等待超时',
'Too many pending withdraw orders' => '用户当前存在多笔提现订单,请等待审核',
@@ -90,6 +92,7 @@ return [
'Pay channel not available for this currency' => '当前币种不支持该支付渠道',
'DDPay deposit initiation failed' => 'DDPay 充值发起失败',
'Deposit only supports DDPay' => '仅支持 DDPay 充值channel_code 须为 ddpay',
'Withdraw only supports DDPay' => '仅支持 DDPay 提现channel_code 须为 ddpay',
// 会员中心 account
'Data updated successfully~' => '资料更新成功~',
'Password has been changed~' => '密码已修改~',

View File

@@ -402,6 +402,72 @@ final class DepositChannel
return array_values(array_unique($codes));
}
/**
* 当前服务端已对接自动出金的渠道(与 withdrawCreate 校验一致)
*
* @return list<string>
*/
public static function withdrawPayoutChannelCodes(): array
{
return ['ddpay'];
}
/**
* @param list<array{code: string, sort: int, status: int, tier_ids: list<string>}> $effectiveRows
*/
public static function assertChannelEnabled(string $channelCode, array $effectiveRows): bool
{
$row = self::findMergedByCode($effectiveRows, $channelCode);
if ($row === null) {
return false;
}
return ($row['status'] ?? 0) === 1;
}
/**
* 提现页可选支付渠道(仅返回已启用且已对接出金的渠道)
*
* @param list<array{code: string, sort: int, status: int, tier_ids: list<string>}> $effectiveRows
*
* @return list<array{code: string, name: string, sort: int}>
*/
public static function channelsForWithdraw(array $effectiveRows, string $lang): array
{
$registry = self::codeRegistry();
$allowed = self::withdrawPayoutChannelCodes();
$out = [];
foreach ($effectiveRows as $row) {
if (($row['status'] ?? 0) !== 1) {
continue;
}
$code = isset($row['code']) && is_string($row['code']) ? $row['code'] : '';
if ($code === '' || !in_array($code, $allowed, true)) {
continue;
}
if (!isset($registry[$code])) {
continue;
}
$meta = $registry[$code];
$sortRaw = $row['sort'] ?? 0;
$sortVal = is_numeric($sortRaw) ? intval($sortRaw) : 0;
$out[] = [
'code' => $code,
'name' => self::pickLangName($meta, $lang),
'sort' => $sortVal,
];
}
usort($out, static function (array $a, array $b): int {
if ($a['sort'] !== $b['sort']) {
return $a['sort'] <=> $b['sort'];
}
return strcmp($a['code'], $b['code']);
});
return $out;
}
/**
* @param list<array<string, mixed>> $items
*

View File

@@ -428,6 +428,8 @@
- `status`int启用状态1=启用)
- `tier_ids`array兼容字段当前固定空数组表示自动兼容全部充值档位
- `withdraw`object
- `pay_channels`array提现可选支付渠道用于 `withdrawCreate``channel_code`;仅返回后台已启用且服务端已对接出金的渠道)
- 每项:`code`string渠道代码小写`name`(展示名)、`sort`(排序)
- `banks`array提现银行
- `min_ewallet`string电子钱包最低提现
- `min_bank`string银行卡最低提现
@@ -437,8 +439,11 @@
- `rate_mode`string`fixed` / `live`
- `fields`object**与 DDPay / `withdrawCreate` 一致**,不由后台「支付/收款配置」开关维护;用于客户端展示必填项)
- `receive_type_bank_only`bool当前固定 `true`,仅支持银行卡出金)
- `require_channel_code`bool固定 `true`,对应 `channel_code`
- `require_receiver_name`bool固定 `true`,对应 `receiver_name`
- `require_receive_account`bool固定 `true`,对应 `receive_account`
- `require_receiver_email`bool固定 `true`,对应 `receiver_email`
- `require_receiver_mobile`bool固定 `true`,对应 `receiver_mobile`
- `require_bank_code`bool固定 `true`,对应 `bank_code`
- `require_bank_branch`bool固定 `false``bank_branch` 选填,不传时服务端按 `N/A` 提交 DDPay
@@ -578,12 +583,19 @@
### 5.7 提现申请
- **POST** `/api/finance/withdrawCreate`
说明:
- **仅支持 DDPay 出金**`channel_code` 必须为 **`ddpay`**(兼容同义字段 `pay_channel`),且该渠道在收银台配置中为启用状态,否则返回 `code=2004`
- 可选渠道列表见 `depositWithdrawConfig``withdraw.pay_channels`
请求参数:
- `channel_code`string必填支付渠道代码当前仅支持 `ddpay`;兼容字段 `pay_channel`
- `withdraw_coin`string含义申请提现金额必须 > 0
- `receive_account`string含义收款账号对接 DDPay 出金时对应官方字段 **`receiver_account`**,为收款账户号/手机号,须与银行登记一致)
- `receive_type`string含义收款类型当前版本仅支持 `bank`
- `idempotency_key`string含义防重复提交提现
- `receiver_name`string含义收款账户持有人姓名`receive_type=bank` 必填,对应官方 **`receiver_name`**,须与银行登记一致)
- `receiver_email`string含义收款人邮箱必填须为合法邮箱格式最长 255
- `receiver_mobile`string含义收款人手机号必填532 位,仅允许数字与 `+` `-` 空格,至少含 5 位数字)
- `bank_code`string含义银行代码`receive_type=bank` 必填。取值来自收银台配置 `withdraw_banks[].code`;服务端会映射为 DDPay 所需的 **`bank[name]`** 银行全称发起出金)
- `bank_branch`string含义银行支行名称`receive_type=bank` 可选。官方 **`bank_branch`** 为必填项,若客户端不传则服务端按 **`N/A`** 提交,与 DDPay 文档「若缺失则默认值为 `N/A`」一致)
@@ -611,17 +623,18 @@
- `risk_review_required`bool含义是否命中人工审核
校验顺序(任一失败即返回对应错误码,不再创建订单):
1. 参数完整性与金额合法性(`code=1001`;金额必须为数值且 > 0
2. **待审核订单数限制**:同一用户 `status=0`(待审核)的 `withdraw_order` 不得超过 3 笔,否则 `code=2004 Too many pending withdraw orders``data` 中回传:
1. 参数完整性与金额合法性(`code=1001``channel_code``withdraw_coin` 等必填项;金额必须为数值且 > 0
2. **支付渠道**`channel_code` `ddpay` 返回 `code=2004 Withdraw only supports DDPay`;渠道未启用返回 `code=2004 Pay channel not available`
3. **待审核订单数限制**:同一用户 `status=0`(待审核)的 `withdraw_order` 不得超过 3 笔,否则 `code=2004 Too many pending withdraw orders``data` 中回传:
- `max_pending`:上限值(当前为 `3`
- `pending_count`:当前待审核订单数
3. `coin_balance >= withdraw_coin`,否则 `code=2001 Insufficient balance`
4. **单笔上限校验**`withdraw_coin <= max_withdrawable`,否则 `code=2002 Withdraw exceeds available bet flow``data` 中回传:
4. `coin_balance >= withdraw_coin`,否则 `code=2001 Insufficient balance`
5. **单笔上限校验**`withdraw_coin <= max_withdrawable`,否则 `code=2002 Withdraw exceeds available bet flow``data` 中回传:
- `max_withdrawable`**当前允许的单笔最大提现金额**= `min(coin_balance, max_withdraw_by_flow)`,前端据此提示"最大可提现金额为 XXX"
- `coin_balance``bet_flow_coin``total_withdraw_coin``ratio`
- `max_withdraw_by_flow`:仅按打码量折算的上限(= `max(0, bet_flow_coin / ratio - total_withdraw_coin)``ratio=0` 时为 `null`
5. 以上全通过后在同一事务内:
- `withdraw_order` 写入:`amount` / `fee`(默认 0.5% / `actual_amount = amount - fee` / `status=0`(待审核) / `channel_id` 取自用户归属渠道快照;同时写入收款字段(`receive_type/receive_account/receiver_name/bank_code/bank_branch`)。
6. 以上全通过后在同一事务内:
- `withdraw_order` 写入:`pay_channel`= `channel_code`/ `amount` / `fee`(默认 0.5% / `actual_amount = amount - fee` / `status=0`(待审核) / `channel_id` 取自用户归属渠道快照;同时写入收款字段(`receive_type/receive_account/receiver_email/receiver_mobile/receiver_name/bank_code/bank_branch`)。
- `user` 表原子更新:`coin -= withdraw_coin``total_withdraw_coin += withdraw_coin`WHERE `coin >= withdraw_coin` 防止并发超额扣减)。
- `user_wallet_record` 写入 `biz_type=withdraw``direction=2``amount=withdraw_coin``ref_type=withdraw_order``idempotency_key=wd_apply_{order_no}`,代表"冻结"动作。
@@ -645,6 +658,11 @@
- `withdraw_coin`string含义申请提现金额与后台 `withdraw_order.amount` 对齐)
- `fee_coin`string含义手续费与后台 `withdraw_order.fee` 对齐)
- `actual_arrival_coin`string含义实际到账金额 = 申请金额 - 手续费;后台审核调整后会同步刷新)
- `receive_type`string含义收款类型
- `receive_account`string含义收款账号
- `pay_channel`string含义支付渠道代码`channel_code` 一致)
- `receiver_email`string含义收款人邮箱
- `receiver_mobile`string含义收款人手机号
- `reject_reason`string/null含义拒绝原因`status=rejected` 时取自 `withdraw_order.remark`,否则为 `null`
- `create_time`int含义申请时间
- `review_time`int/null含义审核时间戳未审核为 `null`

View File

@@ -39,7 +39,7 @@ export default {
ddpay_spec_intro:
'Withdrawals use DDPay Payout (mobile: withdrawCreate). Deposits with channel ddpay use depositCreate. Below is a short field summary; see the DDPay doc and the mobile API draft in the repo for details.',
ddpay_spec_li_withdraw:
'Withdraw (required): withdraw_coin, receive_type=bank, receive_account, receiver_name (as registered with the bank), bank_code (must match a code from “Withdraw banks by currency” on this page), idempotency_key; bank_branch optional (server sends N/A if omitted).',
'Withdraw (required): channel_code=ddpay, withdraw_coin, receive_type=bank, receive_account, receiver_name (as registered with the bank), receiver_email, receiver_mobile, bank_code (must match a code from “Withdraw banks by currency” on this page), idempotency_key; bank_branch optional (server sends N/A if omitted).',
ddpay_spec_li_bank_table:
'English bank name maps to DDPay bank[name] and must match the official full bank names, or payout may be rejected.',
ddpay_spec_li_deposit:

View File

@@ -7,8 +7,12 @@ export default {
amount: 'Apply amount',
fee: 'Fee',
actual_amount: 'Actual amount',
pay_channel: 'Pay channel',
receive_type: 'Receive type',
receive_account: 'Receive account',
receiver_name: 'Cardholder name',
receiver_email: 'Receiver email',
receiver_mobile: 'Receiver mobile',
idempotency_key: 'Idempotency key',
status: 'Status',
'status 0': 'Pending review',

View File

@@ -39,7 +39,7 @@ export default {
ddpay_spec_intro:
'当前提现走 DDPay 出金Payout移动端调用 withdrawCreate充值渠道为 ddpay 时调用 depositCreate。下列为字段约定摘要详细以仓库内 DDPay 文档与《36字花-移动端接口设计草案》为准。',
ddpay_spec_li_withdraw:
'提现必填withdraw_coin、receive_type=bank、receive_account收款账号、receiver_name与银行登记一致、bank_code须与本页「提现支持银行按币种」中 code 一致、idempotency_keybank_branch 选填,不传则服务端按 N/A 提交。',
'提现必填:channel_code=ddpay支付渠道withdraw_coin、receive_type=bank、receive_account收款账号、receiver_name与银行登记一致receiver_email、receiver_mobile、bank_code须与本页「提现支持银行按币种」中 code 一致、idempotency_keybank_branch 选填,不传则服务端按 N/A 提交。',
ddpay_spec_li_bank_table:
'「银行名(英文)」将映射为 DDPay 的 bank[name],请与 DDPay 官方银行全称列表一致,否则出金可能被拒。',
ddpay_spec_li_deposit:

View File

@@ -7,8 +7,12 @@ export default {
amount: '申请金额',
fee: '手续费',
actual_amount: '实际到账',
pay_channel: '支付渠道',
receive_type: '收款类型',
receive_account: '收款账号',
receiver_name: '持卡人姓名',
receiver_email: '收款人邮箱',
receiver_mobile: '收款人手机号',
idempotency_key: '幂等键',
status: '状态',
'status 0': '待审核',

View File

@@ -79,6 +79,14 @@ const baTable = new baTableClass(
{ label: t('order.withdrawOrder.amount'), prop: 'amount', align: 'center', minWidth: 110, operator: 'RANGE', formatter: formatAmount },
{ label: t('order.withdrawOrder.fee'), prop: 'fee', align: 'center', minWidth: 110, operator: 'RANGE', formatter: formatAmount },
{ label: t('order.withdrawOrder.actual_amount'), prop: 'actual_amount', align: 'center', minWidth: 110, operator: 'RANGE', formatter: formatAmount },
{
label: t('order.withdrawOrder.pay_channel'),
prop: 'pay_channel',
align: 'center',
minWidth: 110,
operator: 'LIKE',
operatorPlaceholder: t('Fuzzy query'),
},
{
label: t('order.withdrawOrder.receive_type'),
prop: 'receive_type',
@@ -96,6 +104,33 @@ const baTable = new baTableClass(
operatorPlaceholder: t('Fuzzy query'),
showOverflowTooltip: true,
},
{
label: t('order.withdrawOrder.receiver_name'),
prop: 'ddpay_receiver_name',
align: 'center',
minWidth: 120,
operator: 'LIKE',
operatorPlaceholder: t('Fuzzy query'),
showOverflowTooltip: true,
},
{
label: t('order.withdrawOrder.receiver_email'),
prop: 'receiver_email',
align: 'center',
minWidth: 180,
operator: 'LIKE',
operatorPlaceholder: t('Fuzzy query'),
showOverflowTooltip: true,
},
{
label: t('order.withdrawOrder.receiver_mobile'),
prop: 'receiver_mobile',
align: 'center',
minWidth: 140,
operator: 'LIKE',
operatorPlaceholder: t('Fuzzy query'),
showOverflowTooltip: true,
},
{
label: t('order.withdrawOrder.idempotency_key'),
prop: 'idempotency_key',

View File

@@ -39,12 +39,24 @@
<el-form-item :label="t('order.withdrawOrder.create_time')">
<el-input :model-value="form.create_time_text" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.pay_channel')">
<el-input :model-value="form.pay_channel || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.receive_type')">
<el-input :model-value="form.receive_type || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.receive_account')">
<el-input :model-value="form.receive_account || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.receiver_name')">
<el-input :model-value="form.receiver_name || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.receiver_email')">
<el-input :model-value="form.receiver_email || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.receiver_mobile')">
<el-input :model-value="form.receiver_mobile || '-'" readonly />
</el-form-item>
<el-form-item :label="t('order.withdrawOrder.idempotency_key')">
<el-input :model-value="form.idempotency_key || '-'" readonly />
</el-form-item>
@@ -171,8 +183,12 @@ const form = reactive({
review_admin_text: '-',
review_time_text: '-',
idempotency_key: '',
pay_channel: '',
receive_type: '',
receive_account: '',
receiver_name: '',
receiver_email: '',
receiver_mobile: '',
amount: 0,
fee: 0,
status: 0,
@@ -220,8 +236,12 @@ const hydrate = () => {
form.status = Number(row['status'] ?? 0)
form.remark = String(row['remark'] ?? '')
form.idempotency_key = String(row['idempotency_key'] ?? '')
form.pay_channel = String(row['pay_channel'] ?? '')
form.receive_type = String(row['receive_type'] ?? '')
form.receive_account = String(row['receive_account'] ?? '')
form.receiver_name = String(row['ddpay_receiver_name'] ?? '')
form.receiver_email = String(row['receiver_email'] ?? '')
form.receiver_mobile = String(row['receiver_mobile'] ?? '')
form.create_time_text = formatTime(row['create_time'])
form.review_time_text = formatTime(row['review_time'])
form.user_text = resolveRelationText(row, 'user', row['user_id'])