1.新增获取充值/提现配置接口/api/finance/depositWithdrawConfig

2.优化充值和提现方式
This commit is contained in:
2026-04-23 10:15:01 +08:00
parent 0f28c0fd2a
commit aa1299c018
55 changed files with 901 additions and 750 deletions

View File

@@ -541,7 +541,7 @@ class Channel extends Backend
return $this->error('该渠道下暂无管理员,无法配置分配比例');
}
$enabledSum = '0.0000';
$enabledSum = '0.00';
$insertRows = [];
foreach ($rowsRaw as $line) {
if (!is_array($line)) {
@@ -553,12 +553,12 @@ class Channel extends Backend
}
$status = ((int) ($line['status'] ?? 1)) === 1 ? 1 : 0;
$shareRaw = $line['share_rate'] ?? null;
$shareRate = self::normalizeAmountScale($shareRaw === null ? '0' : (string) $shareRaw, 4);
if (bccomp($shareRate, '0', 4) < 0 || bccomp($shareRate, '100', 4) > 0) {
$shareRate = self::normalizeAmountScale($shareRaw === null ? '0' : (string) $shareRaw, 2);
if (bccomp($shareRate, '0', 2) < 0 || bccomp($shareRate, '100', 2) > 0) {
return $this->error('分配比例必须在0到100之间');
}
if ($status === 1) {
$enabledSum = bcadd($enabledSum, $shareRate, 4);
$enabledSum = bcadd($enabledSum, $shareRate, 2);
}
$insertRows[] = [
'channel_id' => (int) $row['id'],
@@ -572,7 +572,7 @@ class Channel extends Backend
if ($insertRows === []) {
return $this->error('请至少配置一条有效分配记录');
}
if (bccomp($enabledSum, '100.0000', 4) !== 0) {
if (bccomp($enabledSum, '100.00', 2) !== 0) {
return $this->error('启用的分配比例总和必须等于100');
}
@@ -696,7 +696,7 @@ class Channel extends Backend
$stats = $this->aggregateBetOrderForChannel($channelId, $periodStartTs, $lastEnd !== null, $endTs);
$totalBet = $stats['total_bet'];
$totalPayout = $stats['total_payout'];
$profit = bcsub($totalBet, $totalPayout, 4);
$profit = bcsub($totalBet, $totalPayout, 2);
$mode = (string) ($row['agent_mode'] ?? 'turnover');
$commission = $this->computeCommissionAmounts($row, $totalBet, $profit, $mode);
@@ -740,7 +740,7 @@ class Channel extends Backend
$base = $flag . $channelPart . $timePart;
for ($i = 0; $i < 8; $i++) {
$randPart = strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));
$randPart = strtoupper(substr(bin2hex(random_bytes(4)), 0, 2));
$no = $base . $randPart;
if (!Db::name('agent_settlement_period')->where('settlement_no', $no)->value('id')) {
return $no;
@@ -784,10 +784,10 @@ class Channel extends Backend
}
$row = $query->field('SUM(total_amount) AS tb, SUM(win_amount) AS tw, SUM(jackpot_extra_amount) AS tj')->find();
$tb = $row && $row['tb'] !== null && $row['tb'] !== '' ? (string) $row['tb'] : '0.0000';
$tw = $row && $row['tw'] !== null && $row['tw'] !== '' ? (string) $row['tw'] : '0.0000';
$tj = $row && $row['tj'] !== null && $row['tj'] !== '' ? (string) $row['tj'] : '0.0000';
$totalPayout = bcadd($tw, $tj, 4);
$tb = $row && $row['tb'] !== null && $row['tb'] !== '' ? (string) $row['tb'] : '0.00';
$tw = $row && $row['tw'] !== null && $row['tw'] !== '' ? (string) $row['tw'] : '0.00';
$tj = $row && $row['tj'] !== null && $row['tj'] !== '' ? (string) $row['tj'] : '0.00';
$totalPayout = bcadd($tw, $tj, 2);
return [
'total_bet' => number_format((float) $tb, 4, '.', ''),
@@ -805,8 +805,8 @@ class Channel extends Backend
if ($ratePercent === null || $ratePercent === '') {
return '普通返水代理未配置返水分红比例';
}
$rateDec = bcdiv((string) $ratePercent, '100', 6);
$amount = bcmul($totalBet, $rateDec, 4);
$rateDec = bcdiv((string) $ratePercent, '100', 2);
$amount = bcmul($totalBet, $rateDec, 2);
return [
'commission_rate' => $rateDec,
'calc_base_amount' => $totalBet,
@@ -825,27 +825,27 @@ class Channel extends Backend
return '联营阶梯规则无效或为空';
}
if (bccomp($platformProfit, '0', 4) <= 0) {
if (bccomp($platformProfit, '0', 2) <= 0) {
return [
'commission_rate' => '0.000000',
'calc_base_amount' => '0.0000',
'commission_amount' => '0.0000',
'commission_rate' => '0.00',
'calc_base_amount' => '0.00',
'commission_amount' => '0.00',
];
}
$afterFee = bcmul($platformProfit, bcsub('1', (string) $fee, 8), 4);
if (bccomp($afterFee, '0', 4) <= 0) {
$afterFee = bcmul($platformProfit, bcsub('1', (string) $fee, 2), 2);
if (bccomp($afterFee, '0', 2) <= 0) {
return [
'commission_rate' => '0.000000',
'calc_base_amount' => '0.0000',
'commission_amount' => '0.0000',
'commission_rate' => '0.00',
'calc_base_amount' => '0.00',
'commission_amount' => '0.00',
];
}
$playerLoss = $platformProfit;
$share = $this->pickAffiliateShareRateFromLadder($rules, $playerLoss);
$rateDec = number_format($share, 6, '.', '');
$amount = bcmul($afterFee, $rateDec, 4);
$amount = bcmul($afterFee, $rateDec, 2);
return [
'commission_rate' => $rateDec,
@@ -888,7 +888,7 @@ class Channel extends Backend
];
}
usort($out, function ($a, $b) {
return bccomp($a['minLoss'], $b['minLoss'], 4);
return bccomp($a['minLoss'], $b['minLoss'], 2);
});
return $out;
}
@@ -900,7 +900,7 @@ class Channel extends Backend
{
$chosen = (float) $rules[0]['shareRate'];
foreach ($rules as $rule) {
if (bccomp($playerLoss, $rule['minLoss'], 4) >= 0) {
if (bccomp($playerLoss, $rule['minLoss'], 2) >= 0) {
$chosen = (float) $rule['shareRate'];
}
}
@@ -959,24 +959,24 @@ class Channel extends Backend
->select()
->toArray();
if ($rows !== []) {
$sum = '0.0000';
$sum = '0.00';
$out = [];
foreach ($rows as $row) {
$adminId = (int) ($row['admin_id'] ?? 0);
if ($adminId <= 0) {
continue;
}
$shareRate = self::normalizeAmountScale((string) ($row['share_rate'] ?? '0'), 4);
if (bccomp($shareRate, '0', 4) <= 0) {
$shareRate = self::normalizeAmountScale((string) ($row['share_rate'] ?? '0'), 2);
if (bccomp($shareRate, '0', 2) <= 0) {
continue;
}
$sum = bcadd($sum, $shareRate, 4);
$sum = bcadd($sum, $shareRate, 2);
$out[] = [
'admin_id' => $adminId,
'share_rate' => $shareRate,
];
}
if ($out !== [] && bccomp($sum, '100.0000', 4) === 0) {
if ($out !== [] && bccomp($sum, '100.00', 2) === 0) {
return $out;
}
}
@@ -987,7 +987,7 @@ class Channel extends Backend
}
return [[
'admin_id' => (int) $fallbackAdminId,
'share_rate' => '100.0000',
'share_rate' => '100.00',
]];
}
@@ -1007,19 +1007,19 @@ class Channel extends Backend
if ($shareRows === []) {
return [];
}
$sum = '0.0000';
$sum = '0.00';
$rows = [];
$lastIndex = count($shareRows) - 1;
foreach ($shareRows as $index => $shareRow) {
$shareRate = self::normalizeAmountScale((string) ($shareRow['share_rate'] ?? '0'), 4);
$shareDec = bcdiv($shareRate, '100', 8);
$shareRate = self::normalizeAmountScale((string) ($shareRow['share_rate'] ?? '0'), 2);
$shareDec = bcdiv($shareRate, '100', 2);
$amount = $index === $lastIndex
? bcsub($commissionTotal, $sum, 4)
: bcmul($commissionTotal, $shareDec, 4);
? bcsub($commissionTotal, $sum, 2)
: bcmul($commissionTotal, $shareDec, 2);
if ($index !== $lastIndex) {
$sum = bcadd($sum, $amount, 4);
$sum = bcadd($sum, $amount, 2);
}
$effectiveRate = bccomp($calcBaseAmount, '0', 4) <= 0 ? '0.000000' : bcdiv($amount, $calcBaseAmount, 6);
$effectiveRate = bccomp($calcBaseAmount, '0', 2) <= 0 ? '0.00' : bcdiv($amount, $calcBaseAmount, 2);
$rows[] = [
'settlement_period_id' => $periodId,
'channel_id' => $channelId,
@@ -1052,17 +1052,17 @@ class Channel extends Backend
}
$adminNames = Db::name('admin')->where('id', 'in', $adminIds)->column('username', 'id');
$sum = '0.0000';
$sum = '0.00';
$out = [];
$lastIndex = count($shareRows) - 1;
foreach ($shareRows as $index => $shareRow) {
$shareRate = self::normalizeAmountScale((string) ($shareRow['share_rate'] ?? '0'), 4);
$shareDec = bcdiv($shareRate, '100', 8);
$shareRate = self::normalizeAmountScale((string) ($shareRow['share_rate'] ?? '0'), 2);
$shareDec = bcdiv($shareRate, '100', 2);
$amount = $index === $lastIndex
? bcsub($commissionTotal, $sum, 4)
: bcmul($commissionTotal, $shareDec, 4);
? bcsub($commissionTotal, $sum, 2)
: bcmul($commissionTotal, $shareDec, 2);
if ($index !== $lastIndex) {
$sum = bcadd($sum, $amount, 4);
$sum = bcadd($sum, $amount, 2);
}
$adminId = (int) ($shareRow['admin_id'] ?? 0);
$out[] = [

View File

@@ -108,7 +108,7 @@ class Dashboard extends Backend
if ($scope !== null) {
$q->whereIn('channel_id', $scope);
}
$rows = $q->fieldRaw('COUNT(*) AS c, COALESCE(SUM(CAST(amount AS DECIMAL(18,4))),0) AS s')->find();
$rows = $q->fieldRaw('COUNT(*) AS c, COALESCE(SUM(CAST(amount AS DECIMAL(18,2))),0) AS s')->find();
if (!is_array($rows)) {
$rows = [];
}
@@ -146,7 +146,7 @@ class Dashboard extends Backend
if ($scope !== null) {
$q->whereIn('channel_id', $scope);
}
$rows = $q->fieldRaw('COUNT(*) AS c, COALESCE(SUM(CAST(total_amount AS DECIMAL(18,4))),0) AS s')->find();
$rows = $q->fieldRaw('COUNT(*) AS c, COALESCE(SUM(CAST(total_amount AS DECIMAL(18,2))),0) AS s')->find();
if (!is_array($rows)) {
$rows = [];
}
@@ -181,7 +181,7 @@ class Dashboard extends Backend
if ($scope !== null) {
$dq->whereIn('channel_id', $scope);
}
$drow = $dq->fieldRaw('COALESCE(SUM(CAST(amount AS DECIMAL(18,4))),0) AS s')->find();
$drow = $dq->fieldRaw('COALESCE(SUM(CAST(amount AS DECIMAL(18,2))),0) AS s')->find();
$dsum = is_array($drow) && isset($drow['s']) ? strval($drow['s']) : '0';
$depositAmounts[] = $this->formatMoney2($dsum);
@@ -192,7 +192,7 @@ class Dashboard extends Backend
if ($scope !== null) {
$bq->whereIn('channel_id', $scope);
}
$brow = $bq->fieldRaw('COALESCE(SUM(CAST(total_amount AS DECIMAL(18,4))),0) AS s')->find();
$brow = $bq->fieldRaw('COALESCE(SUM(CAST(total_amount AS DECIMAL(18,2))),0) AS s')->find();
$bsum = is_array($brow) && isset($brow['s']) ? strval($brow['s']) : '0';
$betAmounts[] = $this->formatMoney2($bsum);
}
@@ -264,7 +264,7 @@ class Dashboard extends Backend
{
$q = Db::name('deposit_order')
->where('status', 1)
->fieldRaw('channel_id, COALESCE(SUM(CAST(amount AS DECIMAL(18,4))),0) AS s')
->fieldRaw('channel_id, COALESCE(SUM(CAST(amount AS DECIMAL(18,2))),0) AS s')
->group('channel_id');
if ($scope !== null) {
$q->whereIn('channel_id', $scope);
@@ -308,7 +308,7 @@ class Dashboard extends Backend
$rest = array_slice($list, 8);
$other = '0';
foreach ($rest as $item) {
$other = bcadd($other, $item['value'], 4);
$other = bcadd($other, $item['value'], 2);
}
$otherFormatted = $this->formatMoney2($other);
if (bccomp($otherFormatted, '0', 2) > 0) {
@@ -366,7 +366,7 @@ class Dashboard extends Backend
if (!is_numeric($amount)) {
return '0.00';
}
$normalized = bcadd($amount, '0', 4);
$normalized = bcadd($amount, '0', 2);
return bcadd($normalized, '0', 2);
}

View File

@@ -4,7 +4,6 @@ namespace app\admin\controller\config;
use app\common\controller\Backend;
use app\common\library\game\DepositChannel as DepositChannelLib;
use app\common\library\game\DepositTier as DepositTierLib;
use app\common\library\game\FinanceCashierConfig as FinanceCashierConfigLib;
use app\common\service\GameHotDataCoordinator;
use app\common\service\GameHotDataLock;
@@ -56,7 +55,7 @@ class DepositChannel extends Backend
}
/**
* 列表baTablelist / total / remark+ registry + tier_options弹窗用
* 列表baTablelist / total / remark+ registry(弹窗展示名
*/
public function index(WebmanRequest $request): Response
{
@@ -71,7 +70,6 @@ class DepositChannel extends Backend
return $this->error(__('Parameter error'));
}
$tierOptions = $this->buildTierOptions();
$registryOut = $this->buildRegistryOut();
$parsed = DepositChannelLib::parseStoredOverridesFromDb();
@@ -136,7 +134,6 @@ class DepositChannel extends Backend
'total' => $total,
'remark' => '',
'registry' => $registryOut,
'tier_options' => $tierOptions,
'items' => $pageRows,
]);
}
@@ -308,32 +305,6 @@ class DepositChannel extends Backend
}
}
/**
* @return list<array{id: string, label: string}>
*/
private function buildTierOptions(): array
{
$tierRow = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$allTiers = DepositTierLib::parseFromConfigValue($tierRow['config_value'] ?? null);
$tierOptions = [];
foreach ($allTiers as $t) {
if (!is_array($t)) {
continue;
}
$tid = isset($t['id']) && is_string($t['id']) ? $t['id'] : '';
if ($tid === '') {
continue;
}
$title = isset($t['title']) && is_string($t['title']) ? trim($t['title']) : '';
$tierOptions[] = [
'id' => $tid,
'label' => $title !== '' ? $title . ' (' . $tid . ')' : $tid,
];
}
return $tierOptions;
}
/**
* @return array<string, array{name: string, name_en: string, sort: int}>
*/
@@ -376,12 +347,6 @@ class DepositChannel extends Backend
} else {
$form['status'] = $current['status'] ?? 0;
}
if (array_key_exists('tier_ids', $payload) && is_array($payload['tier_ids'])) {
$form['tier_ids'] = $payload['tier_ids'];
} else {
$form['tier_ids'] = isset($current['tier_ids']) && is_array($current['tier_ids']) ? $current['tier_ids'] : [];
}
return $this->normalizeChannelFormRow($form, $code);
}
@@ -398,24 +363,11 @@ class DepositChannel extends Backend
if ($st === true || $st === 1 || $st === '1') {
$status = 1;
}
$tierIds = [];
if (isset($payload['tier_ids']) && is_array($payload['tier_ids'])) {
foreach ($payload['tier_ids'] as $tid) {
if (is_string($tid)) {
$t = trim($tid);
if ($t !== '' && preg_match('/^[a-zA-Z0-9_\-]{1,32}$/', $t)) {
$tierIds[] = $t;
}
}
}
$tierIds = array_values(array_unique($tierIds));
}
return [
'code' => $code,
'sort' => $sort,
'status' => $status,
'tier_ids' => $tierIds,
'tier_ids' => [],
];
}
}

View File

@@ -3,6 +3,7 @@
namespace app\admin\controller\config;
use app\common\controller\Backend;
use app\common\library\game\FinanceCashierConfig as FinanceCashierConfigLib;
use app\common\library\game\DepositTier as DepositTierLib;
use app\common\service\GameHotDataCoordinator;
use app\common\service\GameHotDataLock;
@@ -21,6 +22,45 @@ class DepositTier extends Backend
protected array $noNeedPermission = ['index', 'save'];
/**
* 读取支付货币下拉来源game_config.finance_cashier.currencies
* 用于充值档位表单的“支付货币”选项,避免前端硬编码。
*/
public function currencyOptions(WebmanRequest $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if (!$this->hasNodePermission($request, 'index')) {
return $this->error(__('You have no permission'), [], 401);
}
if ($request->method() !== 'GET') {
return $this->error(__('Parameter error'));
}
$row = Db::name('game_config')->where('config_key', FinanceCashierConfigLib::CONFIG_KEY)->find();
$cfg = FinanceCashierConfigLib::parseFromConfigValue($row['config_value'] ?? null);
$currencies = [];
if (isset($cfg['currencies']) && is_array($cfg['currencies'])) {
foreach ($cfg['currencies'] as $item) {
if (!is_array($item)) {
continue;
}
$code = isset($item['code']) && is_string($item['code']) ? strtoupper(trim($item['code'])) : '';
if ($code === '') {
continue;
}
$currencies[] = $code;
}
}
$currencies = array_values(array_unique($currencies));
if ($currencies === []) {
$currencies = ['MYR', 'CNY', 'USD', 'USDT', 'VND', 'THB', 'SGD', 'IDR'];
}
return $this->success('', ['list' => $currencies]);
}
private function hasNodePermission(WebmanRequest $request, string $action): bool
{
if (!$this->auth) {

View File

@@ -6,7 +6,6 @@ namespace app\admin\controller\config;
use app\common\controller\Backend;
use app\common\library\game\DepositChannel as DepositChannelLib;
use app\common\library\game\DepositTier as DepositTierLib;
use app\common\library\game\FinanceCashierConfig as FinanceCashierConfigLib;
use app\common\service\GameHotDataCoordinator;
use app\common\service\GameHotDataLock;
@@ -91,7 +90,6 @@ class FinanceCashierConfig extends Backend
return $this->success('', [
'form' => $form,
'registry' => $this->buildRegistryOut(),
'tier_options' => $this->buildTierOptions(),
]);
}
@@ -176,32 +174,6 @@ class FinanceCashierConfig extends Backend
}
}
/**
* @return list<array{id: string, label: string}>
*/
private function buildTierOptions(): array
{
$tierRow = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$allTiers = DepositTierLib::parseFromConfigValue(is_array($tierRow) ? ($tierRow['config_value'] ?? null) : null);
$tierOptions = [];
foreach ($allTiers as $t) {
if (!is_array($t)) {
continue;
}
$tid = isset($t['id']) && is_string($t['id']) ? $t['id'] : '';
if ($tid === '') {
continue;
}
$title = isset($t['title']) && is_string($t['title']) ? trim($t['title']) : '';
$tierOptions[] = [
'id' => $tid,
'label' => $title !== '' ? $title . ' (' . $tid . ')' : $tid,
];
}
return $tierOptions;
}
/**
* @return array<string, array{name: string, name_en: string, sort: int}>
*/

View File

@@ -1,29 +0,0 @@
<?php
namespace app\admin\controller\order;
use app\common\library\game\DepositChannel;
/**
* 渠道充值订单仅列出已注册且启用的支付渠道pay_channel产生的充值单
*/
class DepositChannelOrder extends DepositOrder
{
/**
* @param list<array<mixed>> $where
*/
protected function appendDepositOrderIndexWhere(array &$where, string $mainShort): void
{
if ($mainShort === '') {
return;
}
$effective = DepositChannel::effectiveRowsFromDb();
$codes = DepositChannel::enabledPayChannelCodes($effective);
if ($codes === []) {
$where[] = [$mainShort . '.pay_channel', '=', '__no_pay_channel__'];
return;
}
$where[] = [$mainShort . '.pay_channel', 'in', $codes];
}
}

View File

@@ -24,7 +24,7 @@ class WithdrawOrder extends Backend
protected bool $modelSceneValidate = true;
protected string|array $quickSearchField = ['id', 'order_no', 'remark'];
protected string|array $quickSearchField = ['id', 'order_no', 'idempotency_key', 'receive_type', 'receive_account', 'remark'];
protected string|array $defaultSortField = ['id' => 'desc'];
@@ -119,16 +119,16 @@ class WithdrawOrder extends Backend
$newAmount = $this->decimalParam($request->post('amount'), '0');
$newFee = $this->decimalParam($request->post('fee'), '0');
if (bccomp($newAmount, '0', 4) <= 0) {
if (bccomp($newAmount, '0', 2) <= 0) {
return $this->error('申请金额必须大于 0');
}
if (bccomp($newFee, '0', 4) < 0) {
if (bccomp($newFee, '0', 2) < 0) {
return $this->error('手续费不能为负');
}
if (bccomp($newFee, $newAmount, 4) > 0) {
if (bccomp($newFee, $newAmount, 2) > 0) {
return $this->error('手续费不能大于申请金额');
}
$newActual = bcsub($newAmount, $newFee, 4);
$newActual = bcsub($newAmount, $newFee, 2);
$remarkRaw = $request->post('remark');
$remark = is_string($remarkRaw) ? trim($remarkRaw) : '';
@@ -149,8 +149,8 @@ class WithdrawOrder extends Backend
if ($userId <= 0) {
return $this->error('订单缺少用户信息');
}
$oldAmount = bcadd(strval($order['amount'] ?? '0'), '0', 4);
$diff = bcsub($newAmount, $oldAmount, 4);
$oldAmount = bcadd(strval($order['amount'] ?? '0'), '0', 2);
$diff = bcsub($newAmount, $oldAmount, 2);
$now = time();
$adminId = $this->intParam($this->auth->id ?? 0);
@@ -168,7 +168,7 @@ class WithdrawOrder extends Backend
Db::startTrans();
try {
// 金额调整差额处理
$cmp = bccomp($diff, '0', 4);
$cmp = bccomp($diff, '0', 2);
if ($cmp > 0) {
// 新金额更大:再冻结用户 diff
$userRow = Db::name('user')->where('id', $userId)->find();
@@ -176,12 +176,12 @@ class WithdrawOrder extends Backend
Db::rollback();
return $this->error('关联用户不存在');
}
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
if (bccomp($beforeCoin, $diff, 4) < 0) {
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 2);
if (bccomp($beforeCoin, $diff, 2) < 0) {
Db::rollback();
return $this->error('用户余额不足以补扣调整差额');
}
$afterCoin = bcsub($beforeCoin, $diff, 4);
$afterCoin = bcsub($beforeCoin, $diff, 2);
Db::name('user')->where('id', $userId)->update([
'coin' => $afterCoin,
'total_withdraw_coin' => Db::raw('total_withdraw_coin + ' . $diff),
@@ -205,14 +205,14 @@ class WithdrawOrder extends Backend
]);
} elseif ($cmp < 0) {
// 新金额更小:退回差额
$abs = bcsub('0', $diff, 4);
$abs = bcsub('0', $diff, 2);
$userRow = Db::name('user')->where('id', $userId)->find();
if (!$userRow) {
Db::rollback();
return $this->error('关联用户不存在');
}
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
$afterCoin = bcadd($beforeCoin, $abs, 4);
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 2);
$afterCoin = bcadd($beforeCoin, $abs, 2);
Db::name('user')->where('id', $userId)->update([
'coin' => $afterCoin,
'total_withdraw_coin' => Db::raw('total_withdraw_coin - ' . $abs),
@@ -301,7 +301,7 @@ class WithdrawOrder extends Backend
if ($userId <= 0) {
return $this->error('订单缺少用户信息');
}
$amount = bcadd(strval($order['amount'] ?? '0'), '0', 4);
$amount = bcadd(strval($order['amount'] ?? '0'), '0', 2);
$channelIdRaw = $order['channel_id'] ?? null;
$channelId = ($channelIdRaw === null || $channelIdRaw === '')
? null
@@ -318,8 +318,8 @@ class WithdrawOrder extends Backend
Db::rollback();
return $this->error('关联用户不存在');
}
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
$afterCoin = bcadd($beforeCoin, $amount, 4);
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 2);
$afterCoin = bcadd($beforeCoin, $amount, 2);
Db::name('user')->where('id', $userId)->update([
'coin' => $afterCoin,
'total_withdraw_coin' => Db::raw('total_withdraw_coin - ' . $amount),
@@ -413,9 +413,9 @@ class WithdrawOrder extends Backend
private function decimalParam($raw, string $default): string
{
if ($raw === null || $raw === '' || !is_numeric(strval($raw))) {
return bcadd($default, '0', 4);
return bcadd($default, '0', 2);
}
return bcadd(strval($raw), '0', 4);
return bcadd(strval($raw), '0', 2);
}
private function adminDisplayName(): string
@@ -432,14 +432,14 @@ class WithdrawOrder extends Backend
}
/**
* 把 4 位小数金额压缩成最多 2 位小数用于展示(不影响落库精度)
* 把 2 位小数金额压缩成最多 2 位小数用于展示(不影响落库精度)
*/
private function shortAmount(string $amount): string
{
if (!is_numeric($amount)) {
return $amount;
}
$normalized = bcadd($amount, '0', 4);
$normalized = bcadd($amount, '0', 2);
$negative = false;
if (str_starts_with($normalized, '-')) {
$negative = true;

View File

@@ -232,7 +232,7 @@ class User extends Backend
if ($amountText === '' || !is_numeric($amountText)) {
return $this->error('金额格式不正确');
}
if (bccomp($amountText, '0', 4) <= 0) {
if (bccomp($amountText, '0', 2) <= 0) {
return $this->error('金额必须大于0');
}
@@ -267,16 +267,16 @@ class User extends Backend
}
$before = strval($user['coin'] ?? '0');
$delta = self::normalizeAmountScale($amountText, 4);
$delta = self::normalizeAmountScale($amountText, 2);
if ($op === 'credit') {
$after = bcadd($before, $delta, 4);
$after = bcadd($before, $delta, 2);
$bizType = 'admin_credit';
$direction = 1;
} else {
if (bccomp($before, $delta, 4) < 0) {
if (bccomp($before, $delta, 2) < 0) {
return $this->error('余额不足,扣点失败');
}
$after = bcsub($before, $delta, 4);
$after = bcsub($before, $delta, 2);
$bizType = 'admin_deduct';
$direction = 2;
}
@@ -365,7 +365,7 @@ class User extends Backend
private static function formatAmountForDisplay(string $amount): string
{
$normalized = self::normalizeAmountScale($amount, 4);
$normalized = self::normalizeAmountScale($amount, 2);
$negative = false;
if (str_starts_with($normalized, '-')) {
$negative = true;