ekyna/dpd
Laravel package adding DPD (Dynamic Parcel Distribution) shipping features: API integration for label creation, shipment tracking, pickup/dispatch options, and related helpers/config to connect your app to DPD delivery services.
Installation
composer require ekyna/dpd
Ensure your project uses PHP 7.4+ and Laravel 7+ (check composer.json for compatibility).
First Use Case: Create a Shipment
use Ekyna\Dpd\Client;
use Ekyna\Dpd\Shipment;
$client = new Client(config('dpd.api_key'), config('dpd.api_secret'));
$shipment = new Shipment($client);
$shipment->setSender([
'name' => 'John Doe',
'company' => 'My Company',
'address' => '123 Main St',
'city' => 'New York',
'postcode' => '10001',
'country' => 'US',
]);
$shipment->setRecipient([
'name' => 'Jane Smith',
'address' => '456 Oak Ave',
'city' => 'Los Angeles',
'postcode' => '90001',
'country' => 'US',
]);
$shipment->setPackage([
'weight' => 1.5, // in kg
'length' => 30, // in cm
'width' => 20, // in cm
'height' => 20, // in cm
]);
$response = $shipment->create();
Configuration
Add to .env:
DPD_API_KEY=your_api_key
DPD_API_SECRET=your_api_secret
DPD_BASE_URL=https://api.dpd.com/shipment/v1
Publish the config (if available):
php artisan vendor:publish --provider="Ekyna\Dpd\DpdServiceProvider"
Creating Shipments in Laravel Controllers
public function createShipment(Request $request)
{
$validated = $request->validate([
'sender_name', 'sender_address', 'recipient_name', 'recipient_address',
'weight', 'length', 'width', 'height',
]);
$shipment = new Shipment($this->dpdClient);
$shipment->setSender($validated['sender_*']);
$shipment->setRecipient($validated['recipient_*']);
$shipment->setPackage($validated['package_*']);
$response = $shipment->create();
return response()->json($response);
}
Retrieving Tracking Information
public function getTrackingInfo($trackingNumber)
{
$tracking = new Tracking($this->dpdClient);
$info = $tracking->get($trackingNumber);
return view('tracking', compact('info'));
}
Handling Webhooks
Register a webhook route in routes/web.php:
Route::post('/dpd/webhook', [DpdWebhookController::class, 'handle']);
Controller:
public function handle(Request $request)
{
$webhook = new Webhook($this->dpdClient);
$webhook->verify($request->all());
// Process webhook data (e.g., update order status)
}
Batch Processing Shipments Use Laravel Queues for async processing:
public function dispatchShipments()
{
foreach ($orders as $order) {
Dispatch(new ShipOrderJob($order))->onQueue('dpd');
}
}
Job:
public function handle()
{
$shipment = new Shipment($this->dpdClient);
$shipment->setSender($this->order->sender);
// ... set other data
$shipment->create();
}
Laravel Service Container
Bind the client in AppServiceProvider:
$this->app->singleton(Client::class, function ($app) {
return new Client(config('dpd.api_key'), config('dpd.api_secret'));
});
Inject via constructor:
public function __construct(private Client $dpdClient) {}
API Rate Limiting Implement middleware to handle DPD API rate limits:
public function handle($request, Closure $next)
{
if ($this->isRateLimited()) {
return response()->json(['error' => 'Rate limit exceeded'], 429);
}
return $next($request);
}
Logging Log API responses for debugging:
$response = $shipment->create();
\Log::debug('DPD API Response', ['data' => $response]);
API Key/Secret Handling
.env and config/services.php.Data Validation
weight must be numeric, postcode must match country-specific formats).$validated['weight'] = (float) $validated['weight'];
Webhook Verification
$webhook->verify($request->all(), config('dpd.webhook_secret'));
Error Handling
try {
$response = $shipment->create();
} catch (\Ekyna\Dpd\Exception\ApiException $e) {
\Log::error('DPD API Error: ' . $e->getMessage());
return response()->json(['error' => 'Failed to create shipment'], 500);
}
Timeouts
$client = new Client(..., [
'timeout' => 60, // seconds
]);
Enable Debug Mode
Set DPD_DEBUG=true in .env to log API requests/responses.
Test with Sandbox Use DPD's sandbox environment for testing:
DPD_BASE_URL=https://sandbox.api.dpd.com/shipment/v1
Common Errors
api_key/api_secret.recipient fields).Custom Response Handling
Extend the Client class to modify responses:
class CustomClient extends Client
{
public function createShipment(array $data)
{
$response = parent::createShipment($data);
return $this->transformResponse($response);
}
protected function transformResponse($response)
{
// Custom logic (e.g., map DPD fields to your app's schema)
return $response;
}
}
Add New Endpoints
If the package lacks an endpoint (e.g., getShipmentDetails), extend the Client:
public function getShipmentDetails($shipmentId)
{
return $this->request('GET', "/shipments/{$shipmentId}");
}
Queue Failed Jobs Retry failed API calls using Laravel Queues:
public function handle()
{
try {
$this->dpdClient->createShipment($this->data);
} catch (Exception $e) {
$this->release(5); // Retry after 5 seconds
throw $e;
}
}
Localization Override country-specific address formats in your app's config:
'dpd' => [
'address_formats' => [
'US' => '{postcode} {city}',
'DE' => '{postcode} {city}',
],
],
How can I help you explore Laravel packages today?