probe($player, $currencyCode); return $probe->success ? $probe->mainBalanceMinor : null; } public function probe(Player $player, string $currencyCode): MainSiteWalletBalanceProbeResult { $config = $this->partnerSiteConfigResolver->resolveForPlayer($player); $currencyCode = trim($currencyCode) !== '' ? trim($currencyCode) : 'NPR'; if (! $config->enabled) { return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: '', httpStatus: null, message: '接入站点已停用或未配置', responseBody: null, ); } if (! $config->hasWalletApi()) { return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: '', httpStatus: null, message: '未配置主站钱包 API URL', responseBody: null, ); } $base = rtrim((string) $config->walletApiUrl, '/'); $path = $config->walletBalancePath; $url = $base.'/'.ltrim($path, '/'); $timeout = $config->walletTimeoutSeconds; $apiKey = $config->walletApiKey; $headers = ['Accept' => 'application/json']; if (is_string($apiKey) && $apiKey !== '') { $headers['Authorization'] = 'Bearer '.$apiKey; } $query = [ 'site_code' => $player->site_code, 'site_player_id' => $player->site_player_id, 'currency_code' => $currencyCode, ]; try { $response = Http::withHeaders($headers) ->timeout($timeout) ->acceptJson() ->get($url, $query); } catch (\Throwable $e) { return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: $url.'?'.http_build_query($query), httpStatus: null, message: '请求失败: '.$e->getMessage(), responseBody: null, ); } $httpStatus = $response->status(); $payload = $response->json(); $preview = is_array($payload) ? self::truncateResponsePreview($payload) : null; if (! $response->successful()) { $message = is_array($payload) && is_string($payload['message'] ?? null) ? (string) $payload['message'] : 'HTTP '.$httpStatus; return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: $url.'?'.http_build_query($query), httpStatus: $httpStatus, message: $message, responseBody: $preview, ); } if (! is_array($payload)) { return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: $url.'?'.http_build_query($query), httpStatus: $httpStatus, message: '响应不是 JSON 对象', responseBody: null, ); } $raw = data_get($payload, 'data.main_balance') ?? data_get($payload, 'main_balance'); if (! is_numeric($raw)) { return new MainSiteWalletBalanceProbeResult( success: false, mainBalanceMinor: null, currencyCode: $currencyCode, requestUrl: $url.'?'.http_build_query($query), httpStatus: $httpStatus, message: '响应缺少 main_balance 数值', responseBody: $preview, ); } return new MainSiteWalletBalanceProbeResult( success: true, mainBalanceMinor: max(0, (int) $raw), currencyCode: (string) (data_get($payload, 'data.currency_code') ?? $currencyCode), requestUrl: $url.'?'.http_build_query($query), httpStatus: $httpStatus, message: null, responseBody: $preview, ); } /** * @param array $payload * @return array */ private static function truncateResponsePreview(array $payload): array { $json = json_encode($payload, JSON_UNESCAPED_UNICODE); if (is_string($json) && strlen($json) > 512) { return ['_truncated' => true, 'preview' => substr($json, 0, 512)]; } return $payload; } }