credentialsAndBase(); } public function live(array $payload): array { return $this->request('post', '/v3/serp/google/organic/live/advanced', [$payload]); } public function submit(array $payload): array { return $this->request('post', '/v3/serp/google/organic/task_post', [$payload]); } public function collect(string $taskId): array { if (! preg_match('/^[0-9a-f-]{36}$/i', $taskId)) { throw new UnexpectedProviderResponseException('Invalid provider task id.'); } return $this->request('get', '/v3/serp/google/organic/task_get/advanced/'.$taskId); } public function userData(): array { return $this->request('get', '/v3/appendix/user_data'); } private function credentialsAndBase(): array { $login = (string) config('serp.dataforseo.login'); $password = (string) config('serp.dataforseo.password'); $base = rtrim((string) config('serp.dataforseo.base_url'), '/'); if ($login === '' || $password === '') { throw new ProviderConfigurationException('DataForSEO credentials are missing.'); }$parts = parse_url($base); if (! is_array($parts) || ($parts['scheme'] ?? null) !== 'https' || strtolower($parts['host'] ?? '') !== 'api.dataforseo.com' || isset($parts['user'],$parts['pass'],$parts['query'],$parts['fragment']) || (($parts['path'] ?? '') !== '' && ($parts['path'] ?? '') !== '/')) { throw new ProviderConfigurationException('Invalid DataForSEO base URL.'); } return [$login, $password, $base]; } private function request(string $method, string $path, ?array $json = null): array { [$login,$password,$base] = $this->credentialsAndBase(); try { $request = Http::acceptJson()->asJson()->withBasicAuth($login, $password)->connectTimeout((int) config('serp.dataforseo.connect_timeout'))->timeout((int) config('serp.dataforseo.timeout'))->withoutRedirecting(); $response = $method === 'post' ? $request->post($base.$path, $json) : $request->get($base.$path); } catch (ConnectionException $e) { throw $this->errors->connection($e); }if (! $response->successful()) { throw $this->errors->http($response->status()); }$data = $response->json(); if (! is_array($data)) { throw new UnexpectedProviderResponseException('DataForSEO returned invalid JSON.'); } return $data; } }