27-05-2026 DHL Modul v2.1 / Optimierung tracking
This commit is contained in:
parent
036595be94
commit
2bdc9ada3c
33 changed files with 2367 additions and 2086 deletions
|
|
@ -8,6 +8,7 @@ use Acme\Dhl\Jobs\CreateShipmentJob;
|
|||
use Acme\Dhl\Models\DhlShipment;
|
||||
use Acme\Dhl\Support\DhlClient;
|
||||
use App\Services\DhlProductResolver;
|
||||
use App\Services\DhlShipmentService;
|
||||
use App\Services\DhlShipmentWeightCalculator;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -34,7 +35,7 @@ class ShippingService
|
|||
*/
|
||||
public function createLabel(array $orderData): array
|
||||
{
|
||||
Log::info('createLabel', $orderData);
|
||||
Log::info('[DHL Shipping] createLabel called', DhlShipmentService::sanitizeOrderDataForLog($orderData));
|
||||
$validatedData = $this->validateOrderData($orderData);
|
||||
if (config('dhl.use_queue')) {
|
||||
CreateShipmentJob::dispatch($validatedData);
|
||||
|
|
@ -45,12 +46,7 @@ class ShippingService
|
|||
return DB::transaction(function () use ($validatedData) {
|
||||
$payload = $this->buildShipmentPayload($validatedData);
|
||||
|
||||
// Debug logging: Log the exact payload being sent to DHL API
|
||||
Log::info('[DHL API] Sending payload to DHL', [
|
||||
'endpoint' => '/parcel/de/shipping/v2/orders',
|
||||
'payload' => $payload,
|
||||
'payload_json' => json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE),
|
||||
]);
|
||||
Log::info('[DHL API] Sending payload to DHL', $this->buildPayloadLogContext($payload, $validatedData));
|
||||
|
||||
try {
|
||||
// Build query parameters for print format
|
||||
|
|
@ -62,9 +58,7 @@ class ShippingService
|
|||
|
||||
$response = $this->client->request('post', '/parcel/de/shipping/v2/orders', $payload, $query);
|
||||
|
||||
Log::info('[DHL API] Response received', [
|
||||
'response' => $response,
|
||||
]);
|
||||
Log::info('[DHL API] Response received', $this->buildResponseLogContext($response));
|
||||
$this->assertSuccessfulShipmentResponse($response, $this->shouldUseMustEncode($validatedData));
|
||||
} catch (DhlValidationException $e) {
|
||||
if ($this->shouldUseMustEncode($validatedData) && $this->looksLikeAddressValidationError($e->getMessage())) {
|
||||
|
|
@ -73,10 +67,10 @@ class ShippingService
|
|||
|
||||
throw $e;
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL API] Request failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'payload' => $payload,
|
||||
]);
|
||||
Log::error('[DHL API] Request failed', array_merge(
|
||||
$this->buildPayloadLogContext($payload, $validatedData),
|
||||
['error' => $e->getMessage()]
|
||||
));
|
||||
throw $e;
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +198,53 @@ class ShippingService
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a redacted DHL request log context.
|
||||
*
|
||||
* Logs only routing-relevant metadata and never the full payload, since
|
||||
* the payload contains personal address data and billing numbers.
|
||||
*
|
||||
* @param array<string, mixed> $payload
|
||||
* @param array<string, mixed> $validatedData
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildPayloadLogContext(array $payload, array $validatedData): array
|
||||
{
|
||||
$billingNumber = data_get($payload, 'shipments.0.billingNumber');
|
||||
|
||||
return [
|
||||
'endpoint' => '/parcel/de/shipping/v2/orders',
|
||||
'order_id' => $validatedData['order_id'] ?? null,
|
||||
'product_code' => data_get($payload, 'shipments.0.product'),
|
||||
'billing_number_suffix' => is_string($billingNumber) ? mb_substr($billingNumber, -4) : null,
|
||||
'weight_grams' => data_get($payload, 'shipments.0.details.weight.value'),
|
||||
'consignee_country' => data_get($payload, 'shipments.0.consignee.country'),
|
||||
'has_reference' => ! empty(data_get($payload, 'shipments.0.refNo')),
|
||||
'must_encode' => $this->shouldUseMustEncode($validatedData),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a redacted DHL response log context.
|
||||
*
|
||||
* Drops the base64 label payload, which is large and not useful in logs.
|
||||
*
|
||||
* @param array<string, mixed> $response
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildResponseLogContext(array $response): array
|
||||
{
|
||||
return [
|
||||
'shipment_number' => $this->extractShipmentNumber($response),
|
||||
'has_label' => $this->extractLabelData($response) !== null,
|
||||
'routing_code' => $this->extractRoutingCode($response),
|
||||
'item_status_code' => data_get($response, 'items.0.sstatus.statusCode')
|
||||
?? data_get($response, 'status.statusCode'),
|
||||
'item_status_title' => data_get($response, 'items.0.sstatus.title')
|
||||
?? data_get($response, 'status.title'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate required order data according to DHL API v2 specification
|
||||
*/
|
||||
|
|
@ -380,20 +421,30 @@ class ShippingService
|
|||
$addressData['houseNumber'] = $parsed['houseNumber'];
|
||||
|
||||
Log::info('Parsed German address', [
|
||||
'original' => $street,
|
||||
'parsed_street' => $parsed['street'],
|
||||
'parsed_houseNumber' => $parsed['houseNumber'],
|
||||
'original_street_length' => strlen($street),
|
||||
'parsed_street_length' => strlen($parsed['street']),
|
||||
'parsed_house_number_length' => strlen($parsed['houseNumber']),
|
||||
]);
|
||||
} elseif (! $parsed['houseNumber']) {
|
||||
// If we can't parse house number, use a default
|
||||
$addressData['houseNumber'] = '1';
|
||||
|
||||
Log::warning('Could not parse house number from address, using default', [
|
||||
'street' => $street,
|
||||
]);
|
||||
return $addressData;
|
||||
}
|
||||
|
||||
return $addressData;
|
||||
// No house number could be parsed from the street. We must not invent
|
||||
// one (the previous `'1'` default caused parcels to be delivered to
|
||||
// the wrong address) and the DHL API rejects shipments without a
|
||||
// house number anyway. Surface a validation error so the operator can
|
||||
// fix the address before we ever hit DHL.
|
||||
Log::warning('Could not parse house number from address', [
|
||||
'street_length' => strlen($street),
|
||||
'country' => $addressData['country'] ?? null,
|
||||
'postal_prefix' => isset($addressData['postalCode']) && is_string($addressData['postalCode'])
|
||||
? mb_substr($addressData['postalCode'], 0, 2)
|
||||
: null,
|
||||
]);
|
||||
|
||||
throw new InvalidArgumentException(
|
||||
'Hausnummer fehlt in der Adresse und konnte nicht automatisch aus dem Strassenfeld ermittelt werden. Bitte Strasse und Hausnummer separat erfassen.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue