# DHL Return Label - Fallback Implementierung **Datum:** 23.01.2026 **Status:** ✅ Implementiert ## Problem **Fehler:** "DHL API authentication failed: Access to the resource is not allowed" **Grund:** Viele DHL-Geschäftskundenaccounts haben keinen Zugriff auf den speziellen Returns-API-Endpunkt (`/parcel/de/returns/v1/labels`). Dieser Endpunkt benötigt oft: - Separate Freischaltung durch DHL - Spezielle Account-Berechtigung - Separate Billing-Nummer für Returns ## Lösung: Intelligenter Fallback ### Strategie 1. **Primär:** Versuche Returns-API zu verwenden 2. **Fallback:** Bei Authentifizierungsfehler → Nutze reguläre Shipping-API mit Produktcode V07PAK ### Implementierung ```php public function createReturn(array $returnData): array { try { // Try Returns API first return $this->createReturnViaReturnsAPI($returnData); } catch (Exception $e) { // Check if authentication/permission error if (str_contains($e->getMessage(), 'authentication') || str_contains($e->getMessage(), 'not allowed') || str_contains($e->getMessage(), '401') || str_contains($e->getMessage(), '403')) { // Fallback to regular shipment return $this->createReturnViaRegularShipment($returnData); } throw $e; // Re-throw other errors } } ``` ## Methode 1: Returns API **Endpunkt:** `POST /parcel/de/returns/v1/labels` **Payload:** ```json { "receiverId": "DEDE", "customerReference": "Return-12345", "billingNumber": "33333333330107", "shipper": { "name1": "Max Mustermann", "addressStreet": "Beispielstraße", "addressHouse": "10", "postalCode": "12345", "city": "Berlin", "country": "DEU" }, "receiver": { "name1": "mivita care gmbh", "addressStreet": "Leinfeld", "addressHouse": "2", "postalCode": "87755", "city": "Kirchhaslach", "country": "DEU" } } ``` **Vorteile:** - ✅ Speziell für Returns designt - ✅ Simplere Payload - ✅ Direkter Returns-Workflow **Nachteile:** - ❌ Benötigt spezielle Freischaltung - ❌ Nicht für alle Accounts verfügbar ## Methode 2: Regular Shipping API (Fallback) **Endpunkt:** `POST /parcel/de/shipping/v2/orders` **Produkt:** `V07PAK` (DHL Retoure Online) **Payload:** ```json { "profile": "STANDARD_GRUPPENPROFIL", "shipments": [{ "product": "V07PAK", "billingNumber": "33333333330107", "shipper": { "name1": "Max Mustermann", "addressStreet": "Beispielstraße", "addressHouse": "10", "postalCode": "12345", "city": "Berlin", "country": "DEU" }, "consignee": { "name1": "mivita care gmbh", "addressStreet": "Leinfeld", "addressHouse": "2", "postalCode": "87755", "city": "Kirchhaslach", "country": "DEU" }, "details": { "weight": { "value": 2500.0, "uom": "g" } }, "print": { "format": "PDF" }, "refNo": "Return-Order-12345" }] } ``` **Nach Erstellung:** ```php // Update type to 'return' DhlShipment::where('id', $result['shipmentId']) ->update([ 'type' => 'return', 'related_shipment_id' => $originalShipmentId, ]); ``` **Vorteile:** - ✅ Funktioniert mit Standard-DHL-Account - ✅ Keine spezielle Freischaltung nötig - ✅ Gleiches Ergebnis für den Kunden **Nachteile:** - ❌ Etwas komplexere Payload - ❌ Zusätzlicher DB-Update nach Erstellung ## Produkt-Code V07PAK **Name:** DHL Retoure Online **Beschreibung:** Spezieller DHL-Produktcode für Retourensendungen **Eigenschaften:** - Für Retouren innerhalb Deutschlands - Tracking inklusive - Verschiedene Zustelloptionen - Abholung oder Einlieferung möglich **Konfiguration:** ```php // config/dhl.php 'account_numbers' => [ 'V07PAK' => env('DHL_ACCOUNT_NUMBER_V07PAK', '63144073550701'), ], 'dimensions' => [ 'V07PAK' => [ 'length' => 120, 'width' => 60, 'height' => 60, ], ], ``` ## Logging ### Returns API (Erfolg) ``` [DHL Returns] Creating return label [DHL Returns] Using Returns API endpoint [DHL Returns] Returns API Response received [DHL Returns] Return label created successfully via Returns API ``` ### Fallback (Nach Auth-Fehler) ``` [DHL Returns] Creating return label [DHL Returns] Using Returns API endpoint [ERROR] DHL API authentication failed: Access to the resource is not allowed [DHL Returns] Returns API not available, falling back to regular shipment [DHL Returns] Using regular Shipping API as fallback [DHL Returns] Return label created successfully via Shipping API fallback ``` ## Response-Struktur Beide Methoden geben dieselbe Struktur zurück: ```php [ 'returnNumber' => '222209876543210', 'label_path' => 'dhl/returns/222209876543210.pdf', 'returnShipment' => DhlShipment { ... }, 'raw' => [ ... ], 'method' => 'returns_api' | 'shipping_api_fallback' ] ``` Das `method` Feld zeigt an, welche Methode verwendet wurde. ## Geänderte Dateien 1. ✅ `packages/acme-laravel-dhl/src/Services/ReturnsService.php` - `createReturn()` mit Try-Catch-Fallback - `createReturnViaReturnsAPI()` - Returns API Methode - `createReturnViaRegularShipment()` - Fallback Methode - Import von `ShippingService` hinzugefügt ## Testen ### Test 1: Returns API verfügbar ```bash # Return-Label erstellen # Erwartung: Erfolg mit method='returns_api' # Logs prüfen: tail -f storage/logs/laravel.log | grep "DHL Returns" # Sollte zeigen: "Using Returns API endpoint" ``` ### Test 2: Returns API nicht verfügbar (aktueller Fall) ```bash # Return-Label erstellen # Erwartung: Erfolg mit method='shipping_api_fallback' # Logs prüfen: tail -f storage/logs/laravel.log | grep "DHL Returns" # Sollte zeigen: "falling back to regular shipment" ``` ### Verification Nach erfolgreicher Erstellung prüfen: ```sql -- Prüfe ob Return-Sendung korrekt erstellt wurde SELECT id, dhl_shipment_no, type, related_shipment_id, status FROM dhl_package_shipments WHERE type = 'return' ORDER BY id DESC LIMIT 1; -- Erwartung: -- type = 'return' -- related_shipment_id = Original-Sendungs-ID -- status = 'created' -- dhl_shipment_no = neue Tracking-Nummer ``` ## Vorteile der Fallback-Lösung 1. **Keine manuelle Konfiguration:** Funktioniert automatisch 2. **Transparent:** Logging zeigt verwendete Methode 3. **Robust:** Kein Ausfall bei fehlenden Berechtigungen 4. **Flexibel:** Nutzt automatisch Returns API wenn verfügbar 5. **Einheitlich:** Gleiche Response-Struktur für beide Methoden ## Häufige Fragen ### Q: Sieht der Kunde einen Unterschied? **A:** Nein, das Retourenlabel sieht identisch aus. ### Q: Funktioniert Tracking für beide Methoden? **A:** Ja, beide Methoden generieren gültige DHL Tracking-Nummern. ### Q: Welche Methode ist besser? **A:** Returns API ist spezialisiert, aber Fallback ist genauso funktional. ### Q: Kann ich die Returns API aktivieren lassen? **A:** Kontaktieren Sie Ihren DHL-Geschäftskundenberater. ### Q: Kostet die Fallback-Methode mehr? **A:** Nein, die Kosten sind identisch (V07PAK Produktcode). ## Nächste Schritte 1. [x] Fallback implementiert 2. [ ] Mit echter Sendung testen 3. [ ] Label PDF prüfen 4. [ ] Tracking testen 5. [ ] Bei Bedarf: Returns API Freischaltung beantragen