Small fixes + Postcodelookup fallback
This commit is contained in:
parent
f05152c626
commit
bf84540401
@ -1,12 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Postcode Service - Handles postcode lookup via postcode.tech API
|
* Postcode Service - Handles postcode lookup via postcode.tech API
|
||||||
|
* with fallback to openpostcode.nl API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PostcodeService
|
class PostcodeService
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Lookup address by postcode and house number
|
* Lookup address by postcode and house number
|
||||||
|
* Uses postcode.tech as primary, falls back to openpostcode.nl
|
||||||
*
|
*
|
||||||
* @param string $postcode
|
* @param string $postcode
|
||||||
* @param string $number
|
* @param string $number
|
||||||
@ -14,7 +16,7 @@ class PostcodeService
|
|||||||
*/
|
*/
|
||||||
public static function lookup(string $postcode, string $number): array
|
public static function lookup(string $postcode, string $number): array
|
||||||
{
|
{
|
||||||
$postcode = str_replace(' ', '', $postcode);
|
$postcode = strtoupper(str_replace(' ', '', $postcode));
|
||||||
|
|
||||||
if (empty($postcode) || empty($number)) {
|
if (empty($postcode) || empty($number)) {
|
||||||
return [
|
return [
|
||||||
@ -24,6 +26,26 @@ class PostcodeService
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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}";
|
$url = "https://postcode.tech/api/v1/postcode?postcode={$postcode}&number={$number}";
|
||||||
|
|
||||||
$ch = curl_init($url);
|
$ch = curl_init($url);
|
||||||
@ -42,21 +64,16 @@ class PostcodeService
|
|||||||
if ($curlError || $httpCode >= 500) {
|
if ($curlError || $httpCode >= 500) {
|
||||||
return [
|
return [
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'error' => 'Postcode service niet bereikbaar, vul straat en woonplaats zelf in',
|
'error' => 'Postcode.tech service niet bereikbaar',
|
||||||
'details' => $curlError,
|
'details' => $curlError,
|
||||||
'http_code' => 503
|
'http_code' => 503
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($httpCode >= 400) {
|
if ($httpCode >= 400) {
|
||||||
$decoded = json_decode($response, true);
|
|
||||||
$errorMessage = ($decoded && isset($decoded['error']))
|
|
||||||
? $decoded['error']
|
|
||||||
: 'Postcode niet gevonden of ongeldige invoer, vul straat en woonplaats zelf in';
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'error' => $errorMessage,
|
'error' => self::translateErrorMessage($response, $httpCode),
|
||||||
'http_code' => $httpCode
|
'http_code' => $httpCode
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -69,4 +86,123 @@ class PostcodeService
|
|||||||
'http_code' => 200
|
'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.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
index.html
32
index.html
@ -200,10 +200,25 @@
|
|||||||
</template>
|
</template>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div x-show="recommendedOptions.length > 0" x-cloak class="mt-8 space-y-3">
|
||||||
|
<p class="text-[10px] font-black text-red-500 uppercase tracking-widest italic px-2 text-center">
|
||||||
|
Wellicht ook interessant</p>
|
||||||
|
|
||||||
|
<template x-for="u in recommendedOptions" :key="u.id">
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between p-4 border rounded-2xl bg-slate-50 hover:bg-white transition-all shadow-sm">
|
||||||
|
<span class="text-xs font-bold text-slate-700"
|
||||||
|
x-text="u.name + ' (€' + u.price + ')'"></span>
|
||||||
|
<button @click="toggleUpsell(u)" :class="isInCart(u.id) ? 'bg-red-500' : 'bg-green-600'"
|
||||||
|
class="text-white px-6 py-2 rounded-xl text-[10px] font-black uppercase shadow-md"
|
||||||
|
x-text="isInCart(u.id) ? 'Verwijder' : 'Voeg toe'">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
<div class="mt-8 border-t pt-6">
|
<div class="mt-8 border-t pt-6">
|
||||||
<h2 class="font-bold mb-4 text-slate-400 uppercase text-[10px] tracking-widest italic text-center">
|
<h2 class="font-bold mb-4 text-slate-400 uppercase text-[10px] tracking-widest italic text-center">
|
||||||
Extra's</h2>
|
Voeg extra product toe</h2>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<!-- Custom searchable dropdown for extra products -->
|
<!-- Custom searchable dropdown for extra products -->
|
||||||
<div class="relative flex-1" x-data="{ openExtra: false }" @click.away="openExtra = false">
|
<div class="relative flex-1" x-data="{ openExtra: false }" @click.away="openExtra = false">
|
||||||
@ -244,22 +259,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div x-show="recommendedOptions.length > 0" x-cloak class="mt-8 space-y-3">
|
|
||||||
<p class="text-[10px] font-black text-red-500 uppercase tracking-widest italic px-2 text-center">
|
|
||||||
Aanbevolen</p>
|
|
||||||
|
|
||||||
<template x-for="u in recommendedOptions" :key="u.id">
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between p-4 border rounded-2xl bg-slate-50 hover:bg-white transition-all shadow-sm">
|
|
||||||
<span class="text-xs font-bold text-slate-700"
|
|
||||||
x-text="u.name + ' (€' + u.price + ')'"></span>
|
|
||||||
<button @click="toggleUpsell(u)" :class="isInCart(u.id) ? 'bg-red-500' : 'bg-green-600'"
|
|
||||||
class="text-white px-6 py-2 rounded-xl text-[10px] font-black uppercase shadow-md"
|
|
||||||
x-text="isInCart(u.id) ? 'Verwijder' : 'Voeg toe'">
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-12 lg:col-span-3">
|
<div class="col-span-12 lg:col-span-3">
|
||||||
|
|||||||
@ -58,8 +58,8 @@ const FormsComponent = {
|
|||||||
const data = await ApiService.lookupPostcode(this.form.postcode, this.form.houseno);
|
const data = await ApiService.lookupPostcode(this.form.postcode, this.form.houseno);
|
||||||
|
|
||||||
if (data.street) {
|
if (data.street) {
|
||||||
this.form.street = data.street.toUpperCase();
|
this.form.street = data.street;
|
||||||
this.form.city = data.city.toUpperCase();
|
this.form.city = data.city;
|
||||||
} else if (data.error) {
|
} else if (data.error) {
|
||||||
this.addressError = data.error;
|
this.addressError = data.error;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user