209 lines
6.9 KiB
PHP
209 lines
6.9 KiB
PHP
<?php
|
|
/**
|
|
* Postcode Service - Handles postcode lookup via postcode.tech API
|
|
* with fallback to openpostcode.nl API
|
|
*/
|
|
|
|
class PostcodeService
|
|
{
|
|
/**
|
|
* Lookup address by postcode and house number
|
|
* Uses postcode.tech as primary, falls back to openpostcode.nl
|
|
*
|
|
* @param string $postcode
|
|
* @param string $number
|
|
* @return array
|
|
*/
|
|
public static function lookup(string $postcode, string $number): array
|
|
{
|
|
$postcode = strtoupper(str_replace(' ', '', $postcode));
|
|
|
|
if (empty($postcode) || empty($number)) {
|
|
return [
|
|
'success' => 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.';
|
|
}
|
|
}
|