laravel-courier-bd maintained by shipkit-bd
Laravel Courier BD (Shipkit) 📦
A unified Laravel package that provides a single, consistent driver-based API interface for integrating multiple Bangladeshi courier services: Steadfast, Pathao, RedX, eCourier, and Paperfly.
Built with first-class support for SaaS E-Commerce platforms, Cloud POS retail outlets, and Multi-Vendor Marketplaces.
Key Features
- 🚚 5 Unified Couriers: Steadfast, Pathao, RedX, eCourier, and Paperfly with consistent methods (
createOrder,track,cancelOrder,calculateFee). - 📍 Bangladesh Geo & Location Engine: Built-in 64 Districts, Thanas, and Postal Codes resolver with auto-mapping to Pathao/RedX numeric IDs (
CourierGeo::resolve(...)). - 🏢 SaaS Multi-Tenancy: Isolated runtime credentials per store/tenant without global config race conditions (
Courier::forTenant($tenant)). - 🏪 POS Multi-Branch Pickups: Outlet-specific pickup stores for multi-branch retail cashiers (
pickupStoreId). - 🏷️ Thermal Shipping Labels & Barcodes: Instant 4x6" sticky label PDFs and Code128 barcodes/SVGs for 80mm POS receipts (
getLabel(...)). - 🔄 Reverse Logistics & Fixed Returns: Distinct
Returned,ReturnInTransit,ReturnPendingtracking plus dedicated return orders (createReturnOrder(...)). - 📦 Bulk Order Dispatch: Dispatch 50–500 parcels in a single batch (
createBulkOrders(...)). - 🧪 Developer Testing Harness: First-class
Courier::fake()with assertion helpers (assertOrderCreated,assertOrderCancelled, etc.). - 💡 Fee Comparison Engine:
Courier::compareFees($order)dynamically queries all enabled couriers and sorts them from cheapest to most expensive. - 🔔 Multi-Tenant Webhooks: Auto-listening endpoints (
/shipkit/webhooks/{courier}and/shipkit/webhooks/{tenant_id}/{courier}) dispatching granular domain events.
Installation
Install the package via Composer:
composer require shipkit-bd/laravel-courier-bd
Publish the configuration file and database migrations:
php artisan shipkit:install
Run database migrations (optional, if automatic shipment logging is enabled):
php artisan migrate
Environment Configuration
Add your courier credentials to your .env file:
COURIER_DEFAULT_DRIVER=steadfast
COURIER_AUTO_LOG=true
# Steadfast Courier Credentials
STEADFAST_SANDBOX=false
STEADFAST_API_KEY=your_steadfast_api_key
STEADFAST_SECRET_KEY=your_steadfast_secret_key
# Pathao Courier Credentials
PATHAO_SANDBOX=true
PATHAO_CLIENT_ID=your_client_id
PATHAO_CLIENT_SECRET=your_client_secret
PATHAO_USERNAME=your_merchant_username
PATHAO_PASSWORD=your_merchant_password
PATHAO_STORE_ID=your_store_id
# RedX Courier Credentials
REDX_SANDBOX=true
REDX_API_TOKEN=your_redx_api_token
# eCourier Credentials
ECOURIER_SANDBOX=false
ECOURIER_APP_KEY=your_ecourier_app_key
ECOURIER_SECRET_KEY=your_ecourier_secret_key
ECOURIER_USER_ID=your_ecourier_user_id
# Paperfly Credentials
PAPERFLY_SANDBOX=false
PAPERFLY_USERNAME=your_paperfly_username
PAPERFLY_PASSWORD=your_paperfly_password
PAPERFLY_KEY=your_paperfly_key
Usage Guide
1. Creating a Shipment Order
use Shipkit\CourierBD\Facades\Courier;
use Shipkit\CourierBD\DTOs\OrderRequest;
$order = new OrderRequest(
merchantOrderId: 'INV-2026-001',
recipientName: 'Abul Hossain',
recipientPhone: '01711223344',
recipientAddress: 'House 12, Road 5, Dhanmondi, Dhaka',
district: 'Dhaka',
thana: 'Dhanmondi',
postalCode: '1205',
amountToCollect: 1500.00, // COD Amount
itemWeight: 1.0, // kg
itemDescription: 'Cotton Polo Shirt x 2',
specialInstruction: 'Handle with care'
);
// Create shipment with default driver
$response = Courier::createOrder($order);
echo $response->consignmentId; // e.g. ST100200
echo $response->status->label(); // Pending
echo $response->trackingUrl; // Tracking URL
2. Multi-Branch POS Pickup
For physical retail POS outlets, specify which branch warehouse the rider must pick up from:
$order = new OrderRequest(
merchantOrderId: 'POS-DHK-101',
recipientName: 'Karim Ullah',
recipientPhone: '01811223344',
recipientAddress: 'Agrabad, Chattogram',
amountToCollect: 2400.00,
pickupStoreId: $outlet->pathao_store_id // Overrides default store
);
$response = Courier::via('pathao')->createOrder($order);
3. Thermal Label & Barcode Generation (AWB)
Instant 4x6" PDF label or inline SVG barcode for POS receipts:
$label = Courier::getLabel($consignmentId);
echo $label->pdfUrl; // Link to printable PDF label
echo $label->barcodeSvg; // Inline SVG ready for 80mm/58mm thermal POS slips
4. Reverse Logistics & Returns
Create customer return/exchange shipments:
use Shipkit\CourierBD\DTOs\ReturnOrderRequest;
$returnReq = new ReturnOrderRequest(
merchantOrderId: 'RET-001',
customerName: 'Rahim',
customerPhone: '01711000000',
customerAddress: 'Mirpur 10, Dhaka',
originalConsignmentId: 'ST100200',
reason: 'Size exchange requested'
);
$returnResponse = Courier::createReturnOrder($returnReq);
echo $returnResponse->returnConsignmentId;
5. Multi-Tenant SaaS Integration
Supply isolated tenant credentials at runtime:
// Using tenant model implementing HasCourierCredentials
$response = Courier::forTenant($tenantStore)
->via('steadfast')
->createOrder($order);
// Or using on-the-fly config array
$customDriver = Courier::withConfig([
'api_key' => $vendor->steadfast_api_key,
'secret_key' => $vendor->steadfast_secret_key,
], 'steadfast');
6. Bangladesh Geo & Location Engine
use Shipkit\CourierBD\Facades\CourierGeo;
$resolved = CourierGeo::resolve(
district: 'Chattogram',
thana: 'Panchlaish',
postalCode: '4203'
);
echo $resolved->pathaoCityId; // 2
echo $resolved->pathaoZoneId; // 101
echo $resolved->redxAreaId; // 201
echo $resolved->isInsideDhaka ? 'Yes' : 'No'; // No
7. Fee Comparison Engine ⭐
Find the cheapest courier for an order dynamically:
$rates = Courier::compareFees($order);
// Automatically dispatch with cheapest courier!
$cheapest = $rates[0]['courier'];
$response = Courier::via($cheapest)->createOrder($order);
8. Testing with Courier::fake()
Test your checkout flows without making real HTTP requests:
use Shipkit\CourierBD\Facades\Courier;
public function test_checkout_creates_shipment(): void
{
Courier::fake([
'steadfast' => ['consignmentId' => 'CID-FAKE-01']
]);
// Run your application checkout logic...
Courier::assertOrderCreated('steadfast', function ($order) {
return $order->amountToCollect === 1500.00;
});
Courier::assertOrderNotCreated('pathao');
}
Courier Feature Matrix
| Feature | Steadfast | Pathao | RedX | eCourier | Paperfly |
|---|---|---|---|---|---|
| Order Creation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Parcel Tracking | ✅ | ✅ | ✅ | ✅ | ✅ |
| Cancellation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Fee Calculation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Label / AWB | ✅ | ✅ | ✅ | ✅ | ✅ |
| Bulk Dispatch | ✅ | 🔄 | 🔄 | 🔄 | 🔄 |
| Reverse Returns | 🔄 | 🔄 | 🔄 | ✅ | 🔄 |
| Balance / COD | ✅ | 🔄 | 🔄 | 🔄 | 🔄 |
| Coverage | 64 Districts | 64 Districts | 64 Districts | 64 Districts | 64 Districts |
(Legend: ✅ Fully supported via API | 🔄 Driver proxy / in development)
Testing
Run tests with PHPUnit:
vendor/bin/phpunit
License
The MIT License (MIT). Please see License File for more information.