smart-dato / mondial-relay-shipping-sdk
Laravel SDK for the Mondial Relay Dual Carrier API V2 (shipments & labels)
Package info
github.com/smart-dato/mondial-relay-shipping-sdk
pkg:composer/smart-dato/mondial-relay-shipping-sdk
Fund package maintenance!
Requires
- php: ^8.4
- ext-dom: *
- ext-simplexml: *
- illuminate/contracts: ^12.0||^13.0
- spatie/laravel-data: ^4.23
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0||^10.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
README
Create Mondial Relay / InPost shipments and print labels from Laravel using the Dual Carrier API V2. Labels can be retrieved as a PDF URL, raw ZPL/IPL printer code, or QR code.
Installation
composer require smart-dato/mondial-relay-shipping-sdk
Optionally publish the config file:
php artisan vendor:publish --tag="mondial-relay-shipping-sdk-config"
Set your credentials in .env:
MONDIAL_RELAY_SHIPPING_SANDBOX=true MONDIAL_RELAY_SHIPPING_LOGIN=M1ITTEST@business-api.mondialrelay.com MONDIAL_RELAY_SHIPPING_PASSWORD=your-password MONDIAL_RELAY_SHIPPING_CUSTOMER_ID=M1ITTEST MONDIAL_RELAY_SHIPPING_CULTURE=fr-FR MONDIAL_RELAY_SHIPPING_OUTPUT_TYPE=PdfUrl MONDIAL_RELAY_SHIPPING_OUTPUT_FORMAT=10x15
While MONDIAL_RELAY_SHIPPING_SANDBOX is true, requests go to connect-api-sandbox.mondialrelay.com.
Usage
use SmartDato\MondialRelayShipping\Data\Address; use SmartDato\MondialRelayShipping\Data\Parcel; use SmartDato\MondialRelayShipping\Data\Shipment; use SmartDato\MondialRelayShipping\Enums\CollectionMode; use SmartDato\MondialRelayShipping\Enums\DeliveryMode; use SmartDato\MondialRelayShipping\Facades\MondialRelayShipping; $shipment = new Shipment( deliveryMode: DeliveryMode::PointRelais, deliveryLocation: 'FR-66974', collectionMode: CollectionMode::MerchantCollection, sender: new Address( streetname: 'Avenue Antoine Pinay', houseNo: '4', countryCode: 'FR', postCode: '59510', city: 'Hem', addressAdd1: 'My Shop', ), recipient: new Address( streetname: 'Test Street', houseNo: '10', countryCode: 'FR', postCode: '75001', city: 'Paris', firstname: 'John', lastname: 'Doe', phoneNo: '+33320202020', ), parcels: [new Parcel(weightGrams: 1000, content: 'Books')], orderNo: 'ORDER-1234', ); $created = MondialRelayShipping::createShipment($shipment); $created->shipmentNumber; // "96408887" $created->labels[0]->output; // PDF URL (or base64 printer code) $created->labels[0]->decoded(); // raw ZPL/IPL when using printer output $created->warnings(); // non-blocking API warnings
Delivery and collection modes
| Enum case | Code | Meaning |
|---|---|---|
DeliveryMode::PointRelais |
24R | Point Relais® delivery (requires deliveryLocation) |
DeliveryMode::PointRelaisXL |
24L | Point Relais® XL delivery (multi-parcel capable) |
DeliveryMode::HomeDelivery |
HOM | Home delivery (requires recipient phone) |
DeliveryMode::HomeDeliveryNextDay |
XOH | D+1 home delivery (requires EDI setup) |
DeliveryMode::MerchantDelivery |
LCC | Delivery back to the merchant (returns) |
CollectionMode::MerchantCollection |
CCC | Collected at the merchant (outbound) |
CollectionMode::PointRelaisCollection |
REL | Dropped off at a Point Relais® (returns) |
Label output
use SmartDato\MondialRelayShipping\Data\OutputOptions; use SmartDato\MondialRelayShipping\Enums\OutputFormat; use SmartDato\MondialRelayShipping\Enums\OutputType; $created = MondialRelayShipping::createShipment( $shipment, new OutputOptions(OutputType::ZplCode, OutputFormat::ZplGeneric10x15), ); $zpl = $created->labels[0]->decoded();
Batches
createShipments() accepts multiple shipments and never throws for individual failures:
$result = MondialRelayShipping::createShipments([$first, $second]); $result->successful(); // CreatedShipment[] $result->failed(); // CreatedShipment[] with their error statuses $result->errors(); // Status[] (code, level, message)
Multiple accounts
The facade uses the credentials from the config file. To ship on behalf of other accounts, instantiate clients directly — every setting is a constructor argument:
use SmartDato\MondialRelayShipping\MondialRelayShipping; $otherAccount = new MondialRelayShipping( login: 'OTHER@business-api.mondialrelay.com', password: 'other-password', customerId: 'OTHER123', culture: 'de-DE', sandbox: false, ); $otherAccount->createShipment($shipment);
Raw request & response
Every live call carries the raw HTTP exchange — on results and on all exceptions thrown after the request was built:
$result = MondialRelayShipping::createShipments([$shipment]); $result->exchange->request; // XML sent (contains credentials!) $result->exchange->sanitizedRequest(); // XML with the password masked — safe to log $result->exchange->response; // raw XML received $result->exchange->status; // HTTP status code try { MondialRelayShipping::createShipment($shipment); } catch (RequestFailedException|CriticalErrorException|ShipmentFailedException|InvalidResponseException $exception) { logger()->error('Mondial Relay call failed', [ 'request' => $exception->exchange?->sanitizedRequest(), 'response' => $exception->exchange?->response, ]); }
On a connection failure response and status are null but the request XML is still available. The exchange is excluded from toArray()/toJson() so serialized results never leak credentials.
Error handling
All exceptions extend SmartDato\MondialRelayShipping\Exceptions\MondialRelayShippingException:
InvalidShipmentException— the shipment breaks a documented constraint before any HTTP call (missing relay location, parcel under 10 g, multi-parcel on a single-parcel mode, …)InvalidConfigurationException— missing/malformed credentials, customer id, or culture; thrown on the first API call, not when the client is resolved, so tooling that instantiates all container bindings (ide-helper:generate,artisan about) works without credentialsRequestFailedException— connection failure or non-2xx HTTP responseInvalidResponseException— the API returned unparseable XMLCriticalErrorException— the API rejected the whole request (e.g. authentication); inspect$exception->statusesShipmentFailedException—createShipment()could not create the shipment; inspect$exception->statuses
API warnings never throw — read them via $created->warnings() or $result->warnings().
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.