config['url'] ?? config('services.metered.url'); $apiKey = $this->config['key'] ?? config('services.metered.key'); $timeout = (int) ($this->config['timeout'] ?? 5); $cacheTtl = (int) ($this->config['cache_ttl'] ?? 600); if (empty($baseUrl)) { throw new RuntimeException('Metered ICE provider URL is not configured.'); } $url = $baseUrl; if ($apiKey && ! str_contains($url, 'apiKey=')) { $separator = str_contains($url, '?') ? '&' : '?'; $url .= $separator.'apiKey='.urlencode($apiKey); } $cacheKey = 'metered_credentials_cache_'.md5($url); $data = Cache::remember($cacheKey, now()->addSeconds($cacheTtl), function () use ($url, $timeout) { $response = Http::timeout($timeout)->get($url); if (! $response->successful()) { Log::error('Metered API error response', [ 'status' => $response->status(), 'body' => $response->body(), ]); throw new RuntimeException('Metered API Error: '.$response->status()); } $json = $response->json(); return IceResponseValidator::validate($json, 'Metered'); }); return IceCandidatesDto::fromArray($data); } }