|
|
@@ -20,6 +20,8 @@ class ThirdGameBalanceService
|
|
|
|
|
|
private const HISTORY_HOURLY_LIMIT = 5;
|
|
|
|
|
|
+ private const REALTIME_QUERY_INTERVAL_SECONDS = 60;
|
|
|
+
|
|
|
private const GAME_TYPE_NAMES = [
|
|
|
1 => '视讯',
|
|
|
2 => '老虎机',
|
|
|
@@ -218,6 +220,54 @@ class ThirdGameBalanceService
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取最近10分钟(不含当前分钟)的实时游戏订单。
|
|
|
+ */
|
|
|
+ public function realtimeOrders(int $page = 1, int $limit = 2000): array
|
|
|
+ {
|
|
|
+ if (!$this->configured()) {
|
|
|
+ return ['ok' => false, 'msg' => '三方游戏配置缺失'];
|
|
|
+ }
|
|
|
+
|
|
|
+ $rateError = $this->acquireRealtimeQuota($page, $limit);
|
|
|
+ if ($rateError !== null) {
|
|
|
+ return ['ok' => false, 'msg' => $rateError];
|
|
|
+ }
|
|
|
+
|
|
|
+ $response = $this->request('/api/server/recordAll', [
|
|
|
+ 'currency' => (string) config('third_game.currency', 'CNY'),
|
|
|
+ 'pageNo' => (string) $page,
|
|
|
+ 'pageSize' => (string) $limit,
|
|
|
+ ]);
|
|
|
+ if (!$response instanceof Response) {
|
|
|
+ return ['ok' => false, 'msg' => $this->responseMessage($response)];
|
|
|
+ }
|
|
|
+
|
|
|
+ $body = $response->json();
|
|
|
+ if (!is_array($body) || (int) ($body['code'] ?? 0) !== self::CODE_SUCCESS) {
|
|
|
+ return ['ok' => false, 'msg' => $this->responseMessage($response)];
|
|
|
+ }
|
|
|
+ $this->rememberRealtimeSession($limit);
|
|
|
+
|
|
|
+ $providerData = is_array($body['data'] ?? null) ? $body['data'] : [];
|
|
|
+ $providerList = is_array($providerData['list'] ?? null) ? $providerData['list'] : [];
|
|
|
+ $list = [];
|
|
|
+ foreach ($providerList as $row) {
|
|
|
+ if (is_array($row)) {
|
|
|
+ $list[] = $this->formatOrder($row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'ok' => true,
|
|
|
+ 'currency' => (string) config('third_game.currency', 'CNY'),
|
|
|
+ 'total' => (int) ($providerData['total'] ?? count($list)),
|
|
|
+ 'page_no' => (int) ($providerData['pageNo'] ?? $page),
|
|
|
+ 'page_size' => (int) ($providerData['pageSize'] ?? $limit),
|
|
|
+ 'list' => $list,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 一键把用户在所有三方游戏平台的余额转出。
|
|
|
*/
|
|
|
@@ -524,6 +574,38 @@ class ThirdGameBalanceService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private function acquireRealtimeQuota(int $page, int $limit): ?string
|
|
|
+ {
|
|
|
+ $sessionKey = $this->realtimeSessionKey($limit);
|
|
|
+ if ($page > 1 && Cache::has($sessionKey)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ $prefix = $this->realtimeRatePrefix();
|
|
|
+ $lock = Cache::lock($prefix . ':lock', 5);
|
|
|
+ if (!$lock->get()) {
|
|
|
+ return '实时订单同步正在处理中,请稍后重试';
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if ($page > 1 && Cache::has($sessionKey)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ $now = time();
|
|
|
+ $lastQueryAt = (int) Cache::get($prefix . ':last_query', 0);
|
|
|
+ if ($lastQueryAt > 0 && $now - $lastQueryAt < self::REALTIME_QUERY_INTERVAL_SECONDS) {
|
|
|
+ $retryAfter = self::REALTIME_QUERY_INTERVAL_SECONDS - ($now - $lastQueryAt);
|
|
|
+ return "实时订单同步每分钟最多请求1次,请在{$retryAfter}秒后重试";
|
|
|
+ }
|
|
|
+
|
|
|
+ Cache::put($prefix . ':last_query', $now, self::REALTIME_QUERY_INTERVAL_SECONDS);
|
|
|
+ return null;
|
|
|
+ } finally {
|
|
|
+ $lock->release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private function configured(): bool
|
|
|
{
|
|
|
return config('third_game.api_url') !== ''
|
|
|
@@ -569,6 +651,11 @@ class ThirdGameBalanceService
|
|
|
return 'third_game_order_history:' . md5((string) config('third_game.sn'));
|
|
|
}
|
|
|
|
|
|
+ private function realtimeRatePrefix(): string
|
|
|
+ {
|
|
|
+ return 'third_game_order_realtime:' . md5((string) config('third_game.sn'));
|
|
|
+ }
|
|
|
+
|
|
|
private function historySessionKey(string $startTime, string $endTime, int $limit): string
|
|
|
{
|
|
|
return $this->historyRatePrefix() . ':session:' . md5($startTime . '|' . $endTime . '|' . $limit);
|
|
|
@@ -579,6 +666,16 @@ class ThirdGameBalanceService
|
|
|
Cache::put($this->historySessionKey($startTime, $endTime, $limit), true, 3600);
|
|
|
}
|
|
|
|
|
|
+ private function realtimeSessionKey(int $limit): string
|
|
|
+ {
|
|
|
+ return $this->realtimeRatePrefix() . ':session:' . $limit;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function rememberRealtimeSession(int $limit): void
|
|
|
+ {
|
|
|
+ Cache::put($this->realtimeSessionKey($limit), true, 600);
|
|
|
+ }
|
|
|
+
|
|
|
private function clearCache(string $memberId): void
|
|
|
{
|
|
|
Cache::forget($this->cacheKey($memberId));
|