false, 'error' => 'Postcode en huisnummer zijn verplicht', 'http_code' => 400 ]; } // Try primary service (postcode.tech) $result = self::lookupPostcodeTech($postcode, $number); // If primary service fails (server error or timeout), try fallback if (!$result['success'] && $result['http_code'] >= 500) { $result = self::lookupOpenPostcode($postcode, $number); } return $result; } /** * Lookup via postcode.tech API (primary) * * @param string $postcode * @param string $number * @return array */ private static function lookupPostcodeTech(string $postcode, string $number): array { $url = "https://postcode.tech/api/v1/postcode?postcode={$postcode}&number={$number}"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer " . $_ENV['POSTCODE_TECH_KEY'] ]); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($curlError || $httpCode >= 500) { return [ 'success' => false, 'error' => 'Postcode.tech service niet bereikbaar', 'details' => $curlError, 'http_code' => 503 ]; } if ($httpCode >= 400) { return [ 'success' => false, 'error' => self::translateErrorMessage($response, $httpCode), 'http_code' => $httpCode ]; } $data = json_decode($response, true); return [ 'success' => true, 'data' => $data, 'http_code' => 200 ]; } /** * Lookup via openpostcode.nl API (fallback) * No authentication required * * @param string $postcode * @param string $number * @return array */ private static function lookupOpenPostcode(string $postcode, string $number): array { $url = "https://openpostcode.nl/api/address?postcode={$postcode}&huisnummer={$number}"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($curlError || $httpCode >= 500) { return [ 'success' => false, 'error' => 'Postcode service niet bereikbaar, vul straat en woonplaats zelf in', 'details' => $curlError, 'http_code' => 503 ]; } if ($httpCode >= 400) { return [ 'success' => false, 'error' => self::translateErrorMessage($response, $httpCode), 'http_code' => $httpCode ]; } $data = json_decode($response, true); // Transform openpostcode.nl response to match postcode.tech format $transformedData = self::transformOpenPostcodeResponse($data); return [ 'success' => true, 'data' => $transformedData, 'http_code' => 200 ]; } /** * Transform openpostcode.nl response to match postcode.tech format * * openpostcode.nl returns: * - postcode, huisnummer, straat, buurt, wijk, woonplaats, gemeente, provincie, latitude, longitude * * postcode.tech returns: * - postcode, number, street, city, municipality, province, geo (lat, lng) * * @param array $data * @return array */ private static function transformOpenPostcodeResponse(array $data): array { return [ 'postcode' => $data['postcode'] ?? '', 'number' => $data['huisnummer'] ?? '', 'street' => $data['straat'] ?? '', 'city' => $data['woonplaats'] ?? '', 'municipality' => $data['gemeente'] ?? '', 'province' => $data['provincie'] ?? '', 'geo' => [ 'lat' => $data['latitude'] ?? null, 'lng' => $data['longitude'] ?? null ] ]; } /** * Translate API error messages to user-friendly Dutch messages * * @param string $response Raw API response * @param int $httpCode HTTP status code * @return string User-friendly error message in Dutch */ private static function translateErrorMessage(string $response, int $httpCode): string { $decoded = json_decode($response, true); $apiError = ($decoded && isset($decoded['error'])) ? strtolower($decoded['error']) : ''; // Map common API error messages to Dutch user-friendly messages if (strpos($apiError, 'huisnummer not found') !== false || strpos($apiError, 'house number not found') !== false || strpos($apiError, 'number not found') !== false) { return 'Dit huisnummer is niet gevonden bij deze postcode. Controleer het huisnummer of vul het adres handmatig in.'; } if (strpos($apiError, 'postcode not found') !== false || strpos($apiError, 'invalid postcode') !== false) { return 'Deze postcode is niet gevonden. Controleer de postcode of vul het adres handmatig in.'; } if (strpos($apiError, 'invalid') !== false) { return 'Ongeldige invoer. Controleer de postcode en het huisnummer.'; } if ($httpCode === 404) { return 'Adres niet gevonden. Controleer de postcode en het huisnummer of vul het adres handmatig in.'; } if ($httpCode === 429) { return 'Te veel verzoeken. Probeer het later opnieuw of vul het adres handmatig in.'; } // Default message return 'Adres niet gevonden. Vul straat en woonplaats handmatig in.'; } }