<?php
 namespace App\Modules\Fraud\MaxMind; use App\Services\Fraud\Contracts\FraudModuleResponse; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; class Request { protected ?string $accountId = null; protected ?string $licenseKey = null; protected string $serviceType = 'score'; const URL = 'https://minfraud.maxmind.com/minfraud/v2.0/'; public function setAccountId(string $accountId): self { $this->accountId = $accountId; return $this; } public function setLicenseKey(string $licenseKey): self { $this->licenseKey = $licenseKey; return $this; } public function setServiceType(string $serviceType): self { $serviceType = strtolower($serviceType); if (!in_array($serviceType, ['score', 'insights', 'factors'])) { throw new \Exception("Invalid service type: {$serviceType}"); } $this->serviceType = $serviceType; return $this; } public function call(array $data): FraudModuleResponse { $url = $this->getApiEndpointUrl(); try { $response = Http::withBasicAuth($this->accountId, $this->licenseKey) ->timeout(10) ->post($url, $data); $statusCode = $response->status(); $body = $response->json(); Log::info('MaxMind API Request', [ 'url' => $url, 'status' => $statusCode, 'payload_hash' => substr(hash('sha256', json_encode($data) ?: ''), 0, 12), 'sections' => array_keys($data), 'response_code' => is_array($body) ? ($body['code'] ?? null) : null, ]); if (!$body) { throw new \Exception('Empty response from MaxMind API'); } $successful = $statusCode === 200 && !isset($body['code']); return new FraudModuleResponse($body, $statusCode, $successful); } catch (\Exception $e) { Log::error('MaxMind API Error', [ 'error' => $e->getMessage(), 'url' => $url, ]); throw $e; } } protected function getApiEndpointUrl(): string { return self::URL . $this->serviceType; } } 