feat(admin): 统一后台 API 资源鉴权并完善投注风控快照与回补

This commit is contained in:
2026-05-19 09:11:50 +08:00
parent 6ef41cee76
commit 4cf561cd57
26 changed files with 1079 additions and 36 deletions

View File

@@ -69,6 +69,53 @@ final class TicketWalletService
return $after;
}
public function reverseBetDeduct(TicketOrder $order): void
{
$deductTxn = WalletTxn::query()
->where('biz_type', 'bet_deduct')
->where('biz_no', $order->order_no)
->where('status', self::TXN_POSTED)
->first();
if ($deductTxn === null) {
return;
}
$idempotentKey = 'bet-reverse:'.$order->order_no;
if (WalletTxn::query()->where('biz_type', 'bet_reverse')->where('idempotent_key', $idempotentKey)->exists()) {
return;
}
$wallet = PlayerWallet::query()
->whereKey($deductTxn->wallet_id)
->lockForUpdate()
->firstOrFail();
$amount = (int) $deductTxn->amount;
$before = (int) $wallet->balance;
$after = $before + $amount;
$wallet->forceFill([
'balance' => $after,
'version' => (int) $wallet->version + 1,
])->save();
WalletTxn::query()->create([
'txn_no' => $this->newTxnNo(),
'player_id' => (int) $deductTxn->player_id,
'wallet_id' => (int) $deductTxn->wallet_id,
'biz_type' => 'bet_reverse',
'biz_no' => $order->order_no,
'direction' => self::TXN_DIR_IN,
'amount' => $amount,
'balance_before' => $before,
'balance_after' => $after,
'status' => self::TXN_POSTED,
'external_ref_no' => null,
'idempotent_key' => $idempotentKey,
'remark' => 'post_deduct_confirmation_failed',
]);
}
/**
* 结算派彩入账(产品文档:派彩写入钱包流水;幂等键按结算批次 + 玩家)。
*/