# 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
