1.优化中奖事件统一使用bet.win订阅中奖消息

This commit is contained in:
2026-05-26 14:55:10 +08:00
parent 24f30b5ef2
commit 1b26539ac5
7 changed files with 98 additions and 46 deletions

View File

@@ -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仍空则返回空串调用方自行兜底
*