1.ws优化bet.win订阅
This commit is contained in:
@@ -171,8 +171,7 @@ final class GameBetSettleService
|
||||
}
|
||||
|
||||
if (bccomp($win, '0', 2) > 0) {
|
||||
$streakAtBet = (int) ($bet['streak_at_bet'] ?? 0);
|
||||
$isJackpotTier = StreakWinReward::isJackpotForStreakAtBet($streakAtBet);
|
||||
$jackpotFlags = self::betWinJackpotFlagsForOrder($bet, $win, $needReview);
|
||||
if (!isset($winByUser[$userId])) {
|
||||
$winByUser[$userId] = [
|
||||
'user_id' => $userId,
|
||||
@@ -182,12 +181,16 @@ final class GameBetSettleService
|
||||
'total_win' => '0.00',
|
||||
'balance_after' => $balanceAfter,
|
||||
'is_jackpot' => false,
|
||||
'payout_pending_review' => false,
|
||||
'bets' => [],
|
||||
];
|
||||
}
|
||||
if ($isJackpotTier) {
|
||||
if ($jackpotFlags['is_jackpot']) {
|
||||
$winByUser[$userId]['is_jackpot'] = true;
|
||||
}
|
||||
if ($jackpotFlags['payout_pending_review']) {
|
||||
$winByUser[$userId]['payout_pending_review'] = true;
|
||||
}
|
||||
$winByUser[$userId]['total_win'] = bcadd($winByUser[$userId]['total_win'], $win, 2);
|
||||
$winByUser[$userId]['balance_after'] = $balanceAfter;
|
||||
$winByUser[$userId]['bets'][] = [
|
||||
@@ -263,6 +266,7 @@ final class GameBetSettleService
|
||||
'total_win' => (string) ($agg['total_win'] ?? '0.00'),
|
||||
'balance_after' => (string) ($agg['balance_after'] ?? '0'),
|
||||
'is_jackpot' => $isJackpotTier,
|
||||
'payout_pending_review' => false,
|
||||
'bets' => [],
|
||||
];
|
||||
Log::warning('bet.win fallback emitted for settled winner', [
|
||||
@@ -328,9 +332,11 @@ final class GameBetSettleService
|
||||
continue;
|
||||
}
|
||||
$isJackpot = !empty($payload['is_jackpot']);
|
||||
$payoutPendingReview = !empty($payload['payout_pending_review']);
|
||||
$data = GameWebSocketPayloadHelper::mergeUserStreakInto(array_merge($payload, [
|
||||
'is_jackpot' => $isJackpot,
|
||||
'is_win' => true,
|
||||
'payout_pending_review' => $payoutPendingReview,
|
||||
'server_time' => $now,
|
||||
]), $userId);
|
||||
GameWebSocketEventBus::publish(self::TOPIC_BET_WIN, $data);
|
||||
@@ -368,6 +374,9 @@ final class GameBetSettleService
|
||||
if ($userId === false || $userId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$orderStatus = filter_var($bet['status'] ?? 0, FILTER_VALIDATE_INT);
|
||||
$needReview = $orderStatus === self::PLAY_STATUS_PENDING_REVIEW;
|
||||
$jackpotFlags = self::betWinJackpotFlagsForOrder($bet, $win, $needReview);
|
||||
if (!isset($winByUser[$userId])) {
|
||||
$coin = Db::name('user')->where('id', $userId)->value('coin');
|
||||
$winByUser[$userId] = [
|
||||
@@ -378,12 +387,16 @@ final class GameBetSettleService
|
||||
'total_win' => '0.00',
|
||||
'balance_after' => (string) ($coin ?? '0'),
|
||||
'is_jackpot' => false,
|
||||
'payout_pending_review' => false,
|
||||
'bets' => [],
|
||||
];
|
||||
}
|
||||
if (StreakWinReward::isJackpotForStreakAtBet((int) ($bet['streak_at_bet'] ?? 0))) {
|
||||
if ($jackpotFlags['is_jackpot']) {
|
||||
$winByUser[$userId]['is_jackpot'] = true;
|
||||
}
|
||||
if ($jackpotFlags['payout_pending_review']) {
|
||||
$winByUser[$userId]['payout_pending_review'] = true;
|
||||
}
|
||||
$winByUser[$userId]['total_win'] = bcadd((string) $winByUser[$userId]['total_win'], $win, 2);
|
||||
$betId = filter_var($bet['id'] ?? 0, FILTER_VALIDATE_INT);
|
||||
$winByUser[$userId]['bets'][] = [
|
||||
@@ -396,7 +409,7 @@ final class GameBetSettleService
|
||||
}
|
||||
|
||||
/**
|
||||
* 大奖档命中时额外推送公共频道 jackpot.hit(与 bet.win 同一结算时刻,先后发出)。
|
||||
* 大奖档命中时额外推送公共频道 jackpot.hit(全站公告;个人中奖通知仍以 bet.win 为准,不可替代)。
|
||||
*
|
||||
* @param list<array<string, mixed>> $jackpotHits
|
||||
*/
|
||||
@@ -622,6 +635,7 @@ final class GameBetSettleService
|
||||
FILTER_VALIDATE_INT
|
||||
);
|
||||
if ($periodId !== false && $periodId > 0 && $resultNumber !== false && $resultNumber > 0 && bccomp($winAmount, '0', 2) > 0) {
|
||||
$jackpotFlags = self::betWinJackpotFlagsForOrder($row, $winAmount, false);
|
||||
self::publishBetWinsAfterCommit([[
|
||||
'user_id' => $userId,
|
||||
'period_id' => $periodId,
|
||||
@@ -629,7 +643,8 @@ final class GameBetSettleService
|
||||
'result_number' => $resultNumber,
|
||||
'total_win' => $winAmount,
|
||||
'balance_after' => is_string($balanceAfter ?? null) ? $balanceAfter : (string) (Db::name('user')->where('id', $userId)->value('coin') ?? '0'),
|
||||
'is_jackpot' => StreakWinReward::isJackpotForStreakAtBet((int) ($row['streak_at_bet'] ?? 0)),
|
||||
'is_jackpot' => $jackpotFlags['is_jackpot'],
|
||||
'payout_pending_review' => false,
|
||||
'bets' => [['bet_id' => $playRecordId, 'win_amount' => $winAmount]],
|
||||
]], $periodId);
|
||||
}
|
||||
@@ -902,4 +917,21 @@ final class GameBetSettleService
|
||||
}
|
||||
return bccomp($winAmount, $threshold, 2) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bet.win 展示用大奖标记:连胜大奖档 或 触发后台大奖审核阈值,均视为「中大奖」并走 bet.win 通知。
|
||||
*
|
||||
* @param array<string, mixed> $bet
|
||||
* @return array{is_jackpot: bool, payout_pending_review: bool}
|
||||
*/
|
||||
private static function betWinJackpotFlagsForOrder(array $bet, string $winAmount, bool $needReview): array
|
||||
{
|
||||
$streakJackpot = StreakWinReward::isJackpotForStreakAtBet((int) ($bet['streak_at_bet'] ?? 0));
|
||||
$amountJackpot = self::shouldRequireJackpotReview($winAmount, self::jackpotMaxAmount());
|
||||
|
||||
return [
|
||||
'is_jackpot' => $streakJackpot || $amountJackpot || $needReview,
|
||||
'payout_pending_review' => $needReview,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -840,8 +840,9 @@
|
||||
- `data.total_win`:本期该用户派彩合计(已入账部分;若触发**后台大奖审核**(`win_amount >= game_config.jackpot_max_amount`)且注单为待审核,可能尚未入账,但仍会推送本事件)
|
||||
- `data.balance_after`:推送时用户余额(已派彩则为派彩后余额)
|
||||
- `data.bets[]`:`{ bet_id, win_amount }` 明细
|
||||
- **`data.is_jackpot`**:`bool`,`true` 表示该用户本期中奖注单含**大奖档**(`streak_win_reward` 中 `is_jackpot=true` 的档位,与下注时 `streak_at_bet` 对应),`false` 为普通档
|
||||
- **`data.is_jackpot`**:`bool`,`true` 表示**中大奖**(满足任一:连胜**大奖档**、或派彩金额达 `jackpot_max_amount` 需后台审核)。**客户端用此字段做大奖样式,勿仅依赖 `jackpot.hit`**
|
||||
- **`data.is_win`**:`bool`,固定为 `true`(便于与 `user.streak` 的 `extra.is_win` 对齐)
|
||||
- **`data.payout_pending_review`**:`bool`,`true` 表示已中奖但派彩待后台大奖审核,尚未入账(仍应展示中奖 UI)
|
||||
- **合并赔率字段**(与 §7.1.2A 一致):`current_streak`、`streak_level`、`odds_factor`、`is_jackpot`
|
||||
- `data.server_time`:Unix 秒
|
||||
- **服务端去重**:Redis Key `dfw:v1:ws:betwin:{period_id}:{user_id}`(TTL 86400s),**每期每用户至多推送一次**;与 `user.streak` / `wallet.changed` 的整期去重键 `dfw:v1:settle:notify:{period_id}` **分离**,避免后者先占位导致 `bet.win` 被吞。
|
||||
|
||||
Reference in New Issue
Block a user