139 lines
5.4 KiB
PHP
Executable File
139 lines
5.4 KiB
PHP
Executable File
<?php
|
|
namespace App\Controllers\Web;
|
|
|
|
use App\Core\WebBaseController;
|
|
use Db\Database;
|
|
|
|
class BetController extends WebBaseController {
|
|
|
|
public function placeBet() {
|
|
$this->checkWebLogin();
|
|
header('Content-Type: application/json');
|
|
|
|
$userId = $this->getCurrentUserId();
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (empty($data['bets']) || empty($data['period_number']) || empty($data['game_id'])) {
|
|
echo json_encode(['success' => false, 'message' => 'Missing required fields']);
|
|
return;
|
|
}
|
|
|
|
$gameId = (int)$data['game_id'];
|
|
$periodNumber = $data['period_number'];
|
|
$bets = $data['bets'];
|
|
$db = new Database();
|
|
|
|
// 验证期号
|
|
$period = $db->get('periods', '*', ['period_number' => $periodNumber, 'game_id' => $gameId]);
|
|
if (!$period || $period['status'] !== 'pending') {
|
|
echo json_encode(['success' => false, 'message' => 'Period is not open for betting']);
|
|
return;
|
|
}
|
|
|
|
// 赔率映射
|
|
$oddsList = $db->select('game_odds', '*', ['game_id' => $gameId]);
|
|
$oddsMap = [];
|
|
foreach ($oddsList as $o) {
|
|
$oddsMap[$o['type'] . '_' . $o['target']] = (float)$o['odds'];
|
|
}
|
|
|
|
// 用户信息
|
|
$user = $db->get('users', '*', ['id' => $userId]);
|
|
$isVirtual = (int)($user['is_virtual'] ?? 0);
|
|
|
|
// 代理专属赔率覆盖
|
|
if (!empty($user['agent_id'])) {
|
|
$agentOdds = $db->select('agent_odds', '*', ['agent_id' => $user['agent_id'], 'game_id' => $gameId]);
|
|
foreach ($agentOdds as $ao) {
|
|
$oddsMap[$ao['bet_type'] . '_' . $ao['bet_target']] = (float)$ao['odds'];
|
|
}
|
|
}
|
|
|
|
// 限额
|
|
$limitsRaw = $db->select('bet_limits', '*', ['game_id' => $gameId]);
|
|
$limits = [];
|
|
foreach ($limitsRaw as $l) { $limits[$l['bet_type']] = $l; }
|
|
|
|
// 验证投注
|
|
$totalAmount = 0;
|
|
$validBets = [];
|
|
foreach ($bets as $bet) {
|
|
$type = $bet['type'] ?? '';
|
|
$target = $bet['value'] ?? $bet['target'] ?? '';
|
|
$amount = floatval($bet['amount'] ?? 0);
|
|
if ($amount <= 0) continue;
|
|
|
|
$key = $type . '_' . $target;
|
|
$odds = $oddsMap[$key] ?? null;
|
|
if ($odds === null) {
|
|
echo json_encode(['success' => false, 'message' => "Invalid bet: $key"]);
|
|
return;
|
|
}
|
|
|
|
// 限额检查
|
|
if (isset($limits[$type])) {
|
|
if ($amount < (float)$limits[$type]['min_amount']) {
|
|
echo json_encode(['success' => false, 'message' => "Min bet for $type: " . $limits[$type]['min_amount']]);
|
|
return;
|
|
}
|
|
if ($amount > (float)$limits[$type]['max_amount']) {
|
|
echo json_encode(['success' => false, 'message' => "Max bet for $type: " . $limits[$type]['max_amount']]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
$totalAmount += $amount;
|
|
$validBets[] = ['type' => $type, 'target' => $target, 'amount' => $amount, 'odds' => $odds];
|
|
}
|
|
|
|
if (empty($validBets)) {
|
|
echo json_encode(['success' => false, 'message' => 'No valid bets']);
|
|
return;
|
|
}
|
|
|
|
// 事务
|
|
try {
|
|
$db->medoo->pdo->beginTransaction();
|
|
|
|
$stmt = $db->medoo->pdo->prepare("SELECT balance FROM users WHERE id = :id FOR UPDATE");
|
|
$stmt->execute([':id' => $userId]);
|
|
$userRow = $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
$currentBalance = (float)$userRow['balance'];
|
|
|
|
if ($currentBalance < $totalAmount) {
|
|
$db->medoo->pdo->rollBack();
|
|
echo json_encode(['success' => false, 'message' => 'Insufficient balance']);
|
|
return;
|
|
}
|
|
|
|
$newBalance = $currentBalance - $totalAmount;
|
|
$db->update('users', ['balance' => $newBalance], ['id' => $userId]);
|
|
|
|
$db->insert('transactions', [
|
|
'user_id' => $userId, 'type' => 'bet', 'amount' => -$totalAmount,
|
|
'balance_before' => $currentBalance, 'balance_after' => $newBalance,
|
|
'related_id' => $period['id'], 'description' => ($db->get('games', 'name', ['id' => $gameId]) ?: 'Game') . ' Bet - ' . $periodNumber,
|
|
'is_virtual' => $isVirtual, 'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
foreach ($validBets as $vb) {
|
|
$db->insert('bets', [
|
|
'user_id' => $userId, 'game_id' => $gameId,
|
|
'period_number' => $periodNumber, 'period_id' => $period['id'],
|
|
'bet_type' => $vb['type'], 'bet_value' => $vb['target'],
|
|
'amount' => $vb['amount'], 'odds' => $vb['odds'],
|
|
'status' => 'pending', 'is_virtual' => $isVirtual,
|
|
'agent_id' => $user['agent_id'] ?? null,
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
}
|
|
|
|
$db->medoo->pdo->commit();
|
|
echo json_encode(['success' => true, 'message' => 'Bet placed successfully', 'new_balance' => $newBalance]);
|
|
} catch (\Throwable $e) {
|
|
if ($db->medoo->pdo->inTransaction()) $db->medoo->pdo->rollBack();
|
|
echo json_encode(['success' => false, 'message' => 'System error']);
|
|
}
|
|
}
|
|
}
|