feat(admin): 统一后台 API 资源鉴权并完善投注风控快照与回补
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Models\Draw;
|
||||
use App\Models\Player;
|
||||
use App\Lottery\ErrorCode;
|
||||
use App\Models\TicketItem;
|
||||
use App\Models\WalletTxn;
|
||||
use App\Lottery\DrawStatus;
|
||||
use App\Models\TicketOrder;
|
||||
use App\Models\PlayerWallet;
|
||||
@@ -31,6 +32,22 @@ final class TicketPlacementService
|
||||
public function place(Player $player, array $payload): array
|
||||
{
|
||||
$currencyCode = strtoupper((string) $payload['currency_code']);
|
||||
$clientTraceId = isset($payload['client_trace_id']) && $payload['client_trace_id'] !== ''
|
||||
? (string) $payload['client_trace_id']
|
||||
: null;
|
||||
|
||||
if ($clientTraceId !== null) {
|
||||
$existing = TicketOrder::query()
|
||||
->where('player_id', $player->id)
|
||||
->where('client_trace_id', $clientTraceId)
|
||||
->whereIn('status', ['placed', 'partial_failed'])
|
||||
->first();
|
||||
|
||||
if ($existing !== null) {
|
||||
return $this->responseForOrder($existing, null);
|
||||
}
|
||||
}
|
||||
|
||||
$expectedVersions = $payload['expected_config_versions'] ?? null;
|
||||
if (is_array($expectedVersions)) {
|
||||
$expectedVersions = [
|
||||
@@ -59,7 +76,7 @@ final class TicketPlacementService
|
||||
throw new TicketOperationException('draw_closed', ErrorCode::DrawClosed->value);
|
||||
}
|
||||
|
||||
$this->catalogResolver->lockActiveConfigVersionsForPlacement($expectedVersions);
|
||||
$configVersions = $this->catalogResolver->lockActiveConfigVersionsForPlacement($expectedVersions);
|
||||
|
||||
$evaluatedLines = [];
|
||||
$totalBet = 0;
|
||||
@@ -137,6 +154,9 @@ final class TicketPlacementService
|
||||
'status' => 'pending',
|
||||
'submit_source' => 'h5',
|
||||
'client_trace_id' => $payload['client_trace_id'] ?? null,
|
||||
'play_config_version_no' => $configVersions['play_config_version_no'],
|
||||
'odds_version_no' => $configVersions['odds_version_no'],
|
||||
'risk_cap_version_no' => $configVersions['risk_cap_version_no'],
|
||||
]);
|
||||
|
||||
$successfulItems = [];
|
||||
@@ -297,6 +317,7 @@ final class TicketPlacementService
|
||||
}
|
||||
|
||||
$order->forceFill(['status' => 'refunded'])->save();
|
||||
$this->ticketWalletService->reverseBetDeduct($order);
|
||||
});
|
||||
|
||||
throw $e;
|
||||
@@ -304,6 +325,24 @@ final class TicketPlacementService
|
||||
|
||||
$order = TicketOrder::query()->whereKey($order->id)->firstOrFail();
|
||||
|
||||
return $this->responseForOrder($order, $balanceAfter);
|
||||
}
|
||||
|
||||
private function responseForOrder(TicketOrder $order, ?int $balanceAfter): array
|
||||
{
|
||||
$order = TicketOrder::query()->whereKey($order->id)->firstOrFail();
|
||||
$draw = Draw::query()->whereKey((int) $order->draw_id)->firstOrFail();
|
||||
$successCount = TicketItem::query()->where('order_id', $order->id)->where('status', 'success')->count();
|
||||
$failureCount = TicketItem::query()->where('order_id', $order->id)->where('status', 'failed')->count();
|
||||
if ($balanceAfter === null) {
|
||||
$walletTxn = WalletTxn::query()
|
||||
->where('biz_type', 'bet_deduct')
|
||||
->where('biz_no', $order->order_no)
|
||||
->latest('id')
|
||||
->first();
|
||||
$balanceAfter = $walletTxn === null ? null : (int) $walletTxn->balance_after;
|
||||
}
|
||||
|
||||
return [
|
||||
'order_no' => $order->order_no,
|
||||
'draw' => [
|
||||
@@ -315,8 +354,8 @@ final class TicketPlacementService
|
||||
'total_rebate_amount' => (int) $order->total_rebate_amount,
|
||||
'total_actual_deduct' => (int) $order->total_actual_deduct,
|
||||
'total_estimated_payout' => (int) $order->total_estimated_payout,
|
||||
'success_count' => TicketItem::query()->where('order_id', $order->id)->where('status', 'success')->count(),
|
||||
'failure_count' => TicketItem::query()->where('order_id', $order->id)->where('status', 'failed')->count(),
|
||||
'success_count' => $successCount,
|
||||
'failure_count' => $failureCount,
|
||||
],
|
||||
'balance_after' => $balanceAfter,
|
||||
'items' => TicketItem::query()
|
||||
|
||||
Reference in New Issue
Block a user