diff --git a/src/v4/Endpoint/Booking/BookingRequest.php b/src/v4/Endpoint/Booking/BookingRequest.php index 9df8f77..a022d27 100644 --- a/src/v4/Endpoint/Booking/BookingRequest.php +++ b/src/v4/Endpoint/Booking/BookingRequest.php @@ -70,14 +70,31 @@ public static function single( /** @return array */ public function toArray(): array { + // Bring's Booking API expects customerNumber inside each + // consignment's product object — not at the request root. Posting + // it at the root produces a per-consignment BOOK-INPUT-019 + // ("Customer number must be provided") even though the SDK + // constructor enforces a non-empty value, because Bring reads it + // from the product slot and finds nothing there. + // + // We model customerNumber once on the request (it's per-request in + // practice) and inject it into each consignment's product at + // serialization time, so the public SDK shape stays unchanged. + $customerNumber = $this->customerNumber; + $consignments = array_map( + static function (Consignment $c) use ($customerNumber): array { + $arr = $c->toArray(); + $arr['product']['customerNumber'] = $customerNumber; + + return $arr; + }, + $this->consignments, + ); + return [ 'schemaVersion' => $this->schemaVersion, - 'consignments' => array_map( - static fn (Consignment $c): array => $c->toArray(), - $this->consignments, - ), + 'consignments' => $consignments, 'testIndicator' => $this->testIndicator, - 'customerNumber' => $this->customerNumber, ]; } } diff --git a/tests/v4/Endpoint/Booking/BookingApiTest.php b/tests/v4/Endpoint/Booking/BookingApiTest.php index 500c1ed..5c74c72 100644 --- a/tests/v4/Endpoint/Booking/BookingApiTest.php +++ b/tests/v4/Endpoint/Booking/BookingApiTest.php @@ -64,7 +64,8 @@ public function testBookSerialisesAndPostsToCorrectUrl(): void $body = json_decode((string) $req->getBody(), true); self::assertSame('1', $body['schemaVersion']); - self::assertSame('PARCELS_NORWAY-10001234567', $body['customerNumber']); + self::assertArrayNotHasKey('customerNumber', $body, 'customerNumber must not be at request root — Bring expects it under consignments[].product'); + self::assertSame('PARCELS_NORWAY-10001234567', $body['consignments'][0]['product']['customerNumber']); self::assertTrue($body['testIndicator']); self::assertSame(Product::HOME_DELIVERY_PARCEL->value, $body['consignments'][0]['product']['id']); self::assertSame('EVARSLING', $body['consignments'][0]['product']['additionalServices'][0]['id']);