1.优化中奖事件统一使用bet.win订阅中奖消息
This commit is contained in:
@@ -22,9 +22,11 @@ final class GameBetSettleService
|
||||
|
||||
public const CONFIG_KEY_JACKPOT_MAX_AMOUNT = 'jackpot_max_amount';
|
||||
|
||||
/** 小奖(非大奖档)中奖:移动端弹窗/通知专用 */
|
||||
/** 本期中奖(含小奖/大奖档):移动端弹窗/通知统一入口,以 is_jackpot 区分 */
|
||||
public const TOPIC_BET_WIN = 'bet.win';
|
||||
|
||||
public const TOPIC_JACKPOT_HIT = 'jackpot.hit';
|
||||
|
||||
/**
|
||||
* 对指定期次按开奖号码结算所有「待开奖」注单;同一注单幂等(仅 status=1 会更新)。
|
||||
*
|
||||
@@ -59,8 +61,8 @@ final class GameBetSettleService
|
||||
/** @var array<int, true> */
|
||||
$jackpotNotify = [];
|
||||
|
||||
/** @var array<int, array{user_id: int, period_id: int, period_no: string, result_number: int, total_win: string, balance_after: string, bets: list<array{bet_id: int, win_amount: string}>}> */
|
||||
$smallWinByUser = [];
|
||||
/** @var array<int, array{user_id: int, period_id: int, period_no: string, result_number: int, total_win: string, balance_after: string, is_jackpot: bool, bets: list<array{bet_id: int, win_amount: string}>}> */
|
||||
$winByUser = [];
|
||||
|
||||
foreach ($bets as $bet) {
|
||||
$betId = (int) ($bet['id'] ?? 0);
|
||||
@@ -116,26 +118,32 @@ final class GameBetSettleService
|
||||
if ($paid !== null) {
|
||||
$balanceAfter = $paid;
|
||||
}
|
||||
}
|
||||
|
||||
if (bccomp($win, '0', 2) > 0) {
|
||||
$streakAtBet = (int) ($bet['streak_at_bet'] ?? 0);
|
||||
if ($paid !== null && !StreakWinReward::isJackpotForStreakAtBet($streakAtBet)) {
|
||||
if (!isset($smallWinByUser[$userId])) {
|
||||
$smallWinByUser[$userId] = [
|
||||
'user_id' => $userId,
|
||||
'period_id' => $recordId,
|
||||
'period_no' => (string) ($bet['period_no'] ?? ''),
|
||||
'result_number' => $resultNumber,
|
||||
'total_win' => '0.00',
|
||||
'balance_after' => $balanceAfter,
|
||||
'bets' => [],
|
||||
];
|
||||
}
|
||||
$smallWinByUser[$userId]['total_win'] = bcadd($smallWinByUser[$userId]['total_win'], $win, 2);
|
||||
$smallWinByUser[$userId]['balance_after'] = $balanceAfter;
|
||||
$smallWinByUser[$userId]['bets'][] = [
|
||||
'bet_id' => $betId,
|
||||
'win_amount' => $win,
|
||||
$isJackpotTier = StreakWinReward::isJackpotForStreakAtBet($streakAtBet);
|
||||
if (!isset($winByUser[$userId])) {
|
||||
$winByUser[$userId] = [
|
||||
'user_id' => $userId,
|
||||
'period_id' => $recordId,
|
||||
'period_no' => (string) ($bet['period_no'] ?? ''),
|
||||
'result_number' => $resultNumber,
|
||||
'total_win' => '0.00',
|
||||
'balance_after' => $balanceAfter,
|
||||
'is_jackpot' => false,
|
||||
'bets' => [],
|
||||
];
|
||||
}
|
||||
if ($isJackpotTier) {
|
||||
$winByUser[$userId]['is_jackpot'] = true;
|
||||
}
|
||||
$winByUser[$userId]['total_win'] = bcadd($winByUser[$userId]['total_win'], $win, 2);
|
||||
$winByUser[$userId]['balance_after'] = $balanceAfter;
|
||||
$winByUser[$userId]['bets'][] = [
|
||||
'bet_id' => $betId,
|
||||
'win_amount' => $win,
|
||||
];
|
||||
}
|
||||
|
||||
$periodNo = (string) ($bet['period_no'] ?? '');
|
||||
@@ -199,18 +207,19 @@ final class GameBetSettleService
|
||||
];
|
||||
}
|
||||
|
||||
$betWins = array_values($smallWinByUser);
|
||||
$betWins = array_values($winByUser);
|
||||
|
||||
return ['jackpot_hits' => $jackpotHits, 'bet_wins' => $betWins];
|
||||
}
|
||||
|
||||
/**
|
||||
* 事务提交后推送小奖中奖(bet.win)。
|
||||
* 事务提交后推送本期中奖(bet.win,小奖/大奖统一;data.is_jackpot 区分档位)。
|
||||
*
|
||||
* @param list<array<string, mixed>> $betWins
|
||||
*/
|
||||
public static function publishBetWinsAfterCommit(array $betWins): void
|
||||
{
|
||||
$now = time();
|
||||
foreach ($betWins as $payload) {
|
||||
if (!is_array($payload) || empty($payload['user_id'])) {
|
||||
continue;
|
||||
@@ -219,14 +228,47 @@ final class GameBetSettleService
|
||||
if ($userId === false || $userId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$isJackpot = !empty($payload['is_jackpot']);
|
||||
$data = array_merge($payload, [
|
||||
'is_jackpot' => false,
|
||||
'server_time' => time(),
|
||||
'is_jackpot' => $isJackpot,
|
||||
'server_time' => $now,
|
||||
]);
|
||||
GameWebSocketEventBus::publish(self::TOPIC_BET_WIN, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 大奖档命中时额外推送公共频道 jackpot.hit(与 bet.win 同一结算时刻,先后发出)。
|
||||
*
|
||||
* @param list<array<string, mixed>> $jackpotHits
|
||||
*/
|
||||
public static function publishJackpotHitsAfterCommit(array $jackpotHits, int $periodId, string $periodNo, int $resultNumber): void
|
||||
{
|
||||
if ($jackpotHits === [] || $periodId <= 0 || $resultNumber < 1) {
|
||||
return;
|
||||
}
|
||||
GameWebSocketEventBus::publish(self::TOPIC_JACKPOT_HIT, [
|
||||
'period_id' => $periodId,
|
||||
'period_no' => $periodNo,
|
||||
'result_number' => $resultNumber,
|
||||
'hits' => $jackpotHits,
|
||||
'server_time' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算提交后统一推送:先 bet.win(全员中奖),再 jackpot.hit(仅大奖档)。
|
||||
*
|
||||
* @param array{jackpot_hits?: list<array<string, mixed>>, bet_wins?: list<array<string, mixed>>} $settleOut
|
||||
*/
|
||||
public static function publishSettlementWinsAfterCommit(array $settleOut, int $periodId, string $periodNo, int $resultNumber): void
|
||||
{
|
||||
$betWins = is_array($settleOut['bet_wins'] ?? null) ? $settleOut['bet_wins'] : [];
|
||||
$jackpotHits = is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [];
|
||||
self::publishBetWinsAfterCommit($betWins);
|
||||
self::publishJackpotHitsAfterCommit($jackpotHits, $periodId, $periodNo, $resultNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量读取用户展示名:nickname 优先;空则 fallback 到 username;仍空则返回空串(调用方自行兜底)。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user