apiUrl = rtrim($value !== '' ? $value : self::DEFAULT_API_URL, '/'); $this->authUserId = (string) config('mailinfra.registrar_auth_userid'); $this->apiKey = (string) config('mailinfra.registrar_api_key'); } /** * @return array{ * configured: bool, * api_url: string, * email: string, * initial_customer_id: string, * resolved_customer_id: string, * probes: array, * http_status: string, * summary: string * }> * } */ public function run(string $email, ?string $customerId, string $ipAddress): array { $email = strtolower(trim($email)); $customerId = trim((string) $customerId); $probes = []; if ($this->authUserId === '' || $this->apiKey === '') { $probes[] = $this->probeResult( 'Configuration', 'error', 'LOCAL', 'configuration', [], null, 'ResellerClub credentials are missing.' ); return [ 'configured' => false, 'api_url' => $this->apiUrl, 'email' => $email, 'initial_customer_id' => $customerId, 'resolved_customer_id' => '', 'probes' => $probes, ]; } $probes[] = $this->probeResult( 'Configuration', 'success', 'LOCAL', 'configuration', ['api-url' => $this->apiUrl, 'auth-userid' => $this->maskValue($this->authUserId)], null, 'ResellerClub credentials are configured.' ); $resolvedCustomerId = $customerId; if ($email !== '') { $lookup = $this->probeLookup($email); $probes[] = $lookup['probe']; if (($lookup['customer_id'] ?? '') !== '') { $resolvedCustomerId = (string) $lookup['customer_id']; } } if ($resolvedCustomerId !== '') { $probes[] = $this->probeGenerateToken($resolvedCustomerId, $ipAddress); } return [ 'configured' => true, 'api_url' => $this->apiUrl, 'email' => $email, 'initial_customer_id' => $customerId, 'resolved_customer_id' => $resolvedCustomerId, 'probes' => $probes, ]; } /** * @return array{ * probe: array{ * label: string, * status: string, * method: string, * endpoint: string, * request: array, * http_status: string, * summary: string * }, * customer_id?: string * } */ private function probeLookup(string $email): array { $endpoint = $this->apiUrl.'/customers/details.json'; $request = [ 'auth-userid' => $this->maskValue($this->authUserId), 'username' => $email, ]; try { $response = Http::timeout(15)->get($endpoint, [ 'auth-userid' => $this->authUserId, 'api-key' => $this->apiKey, 'username' => $email, ]); $data = $response->json(); $summary = $this->summarizeResponse($data, (string) $response->body()); $customerId = is_array($data) ? (string) ($data['customerid'] ?? $data['customer-id'] ?? '') : ''; return [ 'probe' => $this->probeResult( 'Customer lookup', $response->successful() ? 'success' : 'error', 'GET', $endpoint, $request, $response->status(), $summary !== '' ? $summary : 'No response summary returned.' ), 'customer_id' => $customerId, ]; } catch (\Throwable $e) { Log::warning('ResellerClub connectivity diagnostics: customer lookup failed', [ 'email' => $email, 'error' => $e->getMessage(), ]); return [ 'probe' => $this->probeResult( 'Customer lookup', 'error', 'GET', $endpoint, $request, null, $this->sanitizeText($e->getMessage()) ), ]; } } /** * @return array{ * label: string, * status: string, * method: string, * endpoint: string, * request: array, * http_status: string, * summary: string * } */ private function probeGenerateToken(string $customerId, string $ipAddress): array { $endpoint = $this->apiUrl.'/customers/generate-login-token.json'; $request = [ 'auth-userid' => $this->maskValue($this->authUserId), 'customer-id' => $customerId, 'ip' => $ipAddress, ]; try { $response = Http::timeout(15)->get($endpoint, [ 'auth-userid' => $this->authUserId, 'api-key' => $this->apiKey, 'customer-id' => $customerId, 'ip' => $ipAddress, ]); $data = $response->json(); $summary = $this->summarizeResponse($data, (string) $response->body()); return $this->probeResult( 'Generate login token', $response->successful() ? 'success' : 'error', 'GET', $endpoint, $request, $response->status(), $summary !== '' ? $summary : 'No response summary returned.' ); } catch (\Throwable $e) { Log::warning('ResellerClub connectivity diagnostics: token generation failed', [ 'customer_id' => $customerId, 'error' => $e->getMessage(), ]); return $this->probeResult( 'Generate login token', 'error', 'GET', $endpoint, $request, null, $this->sanitizeText($e->getMessage()) ); } } /** * @param array|mixed $data */ private function summarizeResponse(mixed $data, string $body): string { if (is_array($data)) { foreach (['message', 'error', 'description', 'msg'] as $key) { $value = $this->sanitizeText((string) ($data[$key] ?? '')); if ($value !== '') { return $value; } } if (($data['customerid'] ?? null) !== null) { return 'Customer found: '.(string) $data['customerid']; } if (($data['token'] ?? null) !== null || ($data['loginid'] ?? null) !== null || ($data['userLoginId'] ?? null) !== null) { return 'Login token generated successfully.'; } } return $this->sanitizeText($body); } private function sanitizeText(string $value): string { $value = trim($value); if ($value === '') { return ''; } if ($this->looksLikeHtmlDocument($value)) { return 'HTML error page from upstream. ResellerClub temporarily blocked or rejected the request.'; } $plain = trim(preg_replace('/\s+/', ' ', strip_tags($value)) ?? ''); return mb_strimwidth($plain, 0, 240, '...'); } private function looksLikeHtmlDocument(string $value): bool { $normalized = strtolower(ltrim($value)); return str_starts_with($normalized, ' $request * @return array{ * label: string, * status: string, * method: string, * endpoint: string, * request: array, * http_status: string, * summary: string * } */ private function probeResult( string $label, string $status, string $method, string $endpoint, array $request, ?int $httpStatus, string $summary ): array { return [ 'label' => $label, 'status' => $status, 'method' => $method, 'endpoint' => $endpoint, 'request' => $request, 'http_status' => $httpStatus !== null ? (string) $httpStatus : 'n/a', 'summary' => $summary, ]; } private function maskValue(string $value): string { $value = trim($value); if ($value === '') { return 'missing'; } if (strlen($value) <= 4) { return str_repeat('*', strlen($value)); } return substr($value, 0, 2).str_repeat('*', max(strlen($value) - 4, 2)).substr($value, -2); } }