sabitahmad / laravel-steadfast
Laravel package for SteadFast Courier API integration with order creation, tracking, returns, and optional bulk processing
Fund package maintenance!
Requires
- php: ^8.1
- illuminate/console: ^10.0||^11.0||^12.0
- illuminate/contracts: ^10.0||^11.0||^12.0
- illuminate/database: ^10.0||^11.0||^12.0
- illuminate/http: ^10.0||^11.0||^12.0
- illuminate/queue: ^10.0||^11.0||^12.0
- illuminate/support: ^10.0||^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
README
Laravel integration for the SteadFast Courier API with typed DTOs for orders, tracking, returns, balance checks, optional bulk processing, bulk lifecycle events, caching, and database-backed request logging.
Features
- Create single and bulk orders
- Track shipments by consignment ID, invoice, or tracking code
- Create and fetch return requests
- Check account balance
- Typed request and response DTOs
- Queue-backed bulk processing
- Bulk lifecycle events
- Configurable caching for balance and status lookups
- Optional fraud checking through the SteadFast merchant panel
- Optional request logging and usage statistics
- Built-in artisan commands for testing, statistics, and cleanup
Installation
composer require sabitahmad/laravel-steadfast php artisan steadfast:install
Add your credentials to .env:
STEADFAST_API_KEY=your_api_key_here STEADFAST_SECRET_KEY=your_secret_key_here
Optional settings:
STEADFAST_BASE_URL=https://portal.packzy.com/api/v1 STEADFAST_TIMEOUT=30 STEADFAST_CONNECT_TIMEOUT=10 STEADFAST_BULK_QUEUE=true STEADFAST_BULK_CHUNK_SIZE=500 STEADFAST_QUEUE_NAME=default STEADFAST_QUEUE_CONNECTION= STEADFAST_BULK_MAX_ATTEMPTS=3 STEADFAST_BULK_BACKOFF=60 STEADFAST_RETRY_TIMES=3 STEADFAST_RETRY_SLEEP=1000 STEADFAST_CACHE_ENABLED=false STEADFAST_CACHE_TTL=300 STEADFAST_CACHE_PREFIX=steadfast STEADFAST_CACHE_STORE= STEADFAST_LOGGING=true STEADFAST_LOG_REQUESTS=false STEADFAST_LOG_RESPONSES=true STEADFAST_CLEANUP_LOGS=true STEADFAST_KEEP_LOGS_DAYS=30 STEADFAST_FRAUD_CHECKER_ENABLED=false STEADFAST_FRAUD_CHECKER_EMAIL=your-merchant-email@example.com STEADFAST_FRAUD_CHECKER_PASSWORD=your-merchant-password
Verify the setup:
php artisan steadfast:test
Usage
Create an Order
use SabitAhmad\SteadFast\DTO\OrderRequest; use SabitAhmad\SteadFast\SteadFast; $steadfast = new SteadFast(); $order = new OrderRequest( invoice: 'INV-2025-001', recipient_name: 'John Doe', recipient_phone: '01712345678', recipient_address: 'House 1, Road 2, Dhanmondi, Dhaka-1209', cod_amount: 1500.00, note: 'Handle with care' ); $response = $steadfast->createOrder($order); echo $response->getTrackingCode();
You can also use optional order fields when needed:
$order = new OrderRequest( invoice: 'INV-2025-002', recipient_name: 'Jane Doe', recipient_phone: '01812345678', recipient_address: 'Banani, Dhaka', cod_amount: 2200, alternative_phone: '01912345678', recipient_email: 'jane@example.com', item_description: 'Skin care products', total_lot: 2, delivery_type: 0 );
Use the Facade
use SabitAhmad\SteadFast\Facades\SteadFast; $balance = SteadFast::getBalance();
Bulk Orders
$orders = [ new OrderRequest('INV-001', 'John Doe', '01712345678', 'Address 1', 1000), new OrderRequest('INV-002', 'Jane Smith', '01787654321', 'Address 2', 1500), OrderRequest::fromArray([ 'invoice' => 'INV-003', 'recipient_name' => 'Bob Wilson', 'recipient_phone' => '01611111111', 'recipient_address' => 'Address 3', 'cod_amount' => 2000, 'delivery_type' => 1, ]), ]; $queued = $steadfast->bulkCreate($orders, true); $processed = $steadfast->bulkCreate($orders, false);
Bulk responses include helper methods:
echo $processed->getSuccessRate(); if ($processed->hasErrors()) { $failedOrders = $processed->getFailedOrders(); }
Track an Order
$status = $steadfast->checkStatusByTrackingCode('ABC123XYZ'); if ($status->isDelivered()) { echo 'Delivered'; } echo $status->getStatusDescription();
You can also track by invoice or consignment ID:
$steadfast->checkStatusByInvoice('INV-001'); $steadfast->checkStatusByConsignmentId(12345);
Return Requests
use SabitAhmad\SteadFast\DTO\ReturnRequest; $request = ReturnRequest::byInvoice('INV-001', 'Customer requested return'); $response = $steadfast->createReturnRequest($request); $single = $steadfast->getReturnRequest(123); $all = $steadfast->getReturnRequests();
You can also create return requests by consignment ID or tracking code:
ReturnRequest::byConsignmentId(12345, 'Damaged item'); ReturnRequest::byTrackingCode('ABC123', 'Wrong item delivered');
Balance
$balance = $steadfast->getBalance(); echo $balance->getFormattedBalance();
Response Helpers
The DTOs expose helper methods so your application code stays clean:
$orderResponse->getConsignmentId(); $orderResponse->getTrackingCode(); $orderResponse->getInvoice(); $status->isPending(); $status->isCancelled(); $status->isOnHold(); $returnResponse->isPending(); $returnResponse->isCompleted();
Fraud Check
This feature logs into the SteadFast merchant panel and is slower than the normal API calls. Enable it only if you need it.
try { $fraud = $steadfast->checkFraud('01712345678'); echo $fraud->success; echo $fraud->cancel; echo $fraud->getRiskLevel(); } catch (\SabitAhmad\SteadFast\Exceptions\SteadfastException $e) { report($e); }
Accepted phone formats are normalized automatically, including 01712345678, 8801712345678, +8801712345678, and values with spaces or dashes.
Fraud responses also include helper methods:
$fraud->getSuccessRate(); $fraud->getCancelRate(); $fraud->isRisky(); $fraud->getRiskDescription();
Events
Bulk processing dispatches these events:
SabitAhmad\SteadFast\Events\BulkOrderStartedSabitAhmad\SteadFast\Events\BulkOrderCompletedSabitAhmad\SteadFast\Events\BulkOrderFailed
Example listener registration:
use Illuminate\Support\Facades\Event; use SabitAhmad\SteadFast\Events\BulkOrderCompleted; use SabitAhmad\SteadFast\Events\BulkOrderFailed; use SabitAhmad\SteadFast\Events\BulkOrderStarted; Event::listen(BulkOrderStarted::class, function (BulkOrderStarted $event) { logger()->info('Bulk order processing started', [ 'order_count' => count($event->orders), 'unique_id' => $event->uniqueId, ]); }); Event::listen(BulkOrderCompleted::class, function (BulkOrderCompleted $event) { logger()->info('Bulk order processing completed', [ 'success_count' => $event->response->success_count, 'error_count' => $event->response->error_count, 'unique_id' => $event->uniqueId, ]); }); Event::listen(BulkOrderFailed::class, function (BulkOrderFailed $event) { logger()->error('Bulk order processing failed', [ 'error' => $event->exception->getMessage(), 'unique_id' => $event->uniqueId, ]); });
Caching
Balance and status lookups can be cached:
STEADFAST_CACHE_ENABLED=true STEADFAST_CACHE_TTL=300 STEADFAST_CACHE_PREFIX=steadfast STEADFAST_CACHE_STORE=redis
Clear cached entries when needed:
$steadfast->clearCache('balance'); $steadfast->clearCache();
Error Handling
use SabitAhmad\SteadFast\Exceptions\SteadfastException; try { $steadfast->createOrder($order); } catch (SteadfastException $e) { match ($e->getCode()) { 401 => report('Invalid credentials'), 422 => report($e->getContext()['validation_errors'] ?? []), 429 => report('Rate limited'), 503 => report('Service unavailable'), default => report($e->getMessage()), }; }
Logging and Statistics
If logging is enabled, requests are stored in the steadfast_logs table.
Useful scopes on the SteadfastLog model:
use SabitAhmad\SteadFast\Models\SteadfastLog; $recentErrors = SteadfastLog::errors()->recent(24)->get(); $successful = SteadfastLog::successful()->recent(24)->get(); $bulkOperations = SteadfastLog::bulkOperations()->get(); $stats = SteadfastLog::getStats(24);
Artisan Commands
Available commands:
php artisan steadfast:test php artisan steadfast:stats php artisan steadfast:stats --hours=168 php artisan steadfast:cleanup php artisan steadfast:cleanup --force
What they do:
steadfast:test: validates config and checks API connectivitysteadfast:stats: shows request volume, success rate, bulk usage, and top endpointssteadfast:cleanup: removes old log records fromsteadfast_logs
API Coverage
| Endpoint | Method | Purpose |
|---|---|---|
/create_order |
POST |
Create a single order |
/create_order/bulk-order |
POST |
Create bulk orders |
/status_by_cid/{id} |
GET |
Check status by consignment ID |
/status_by_invoice/{invoice} |
GET |
Check status by invoice |
/status_by_trackingcode/{code} |
GET |
Check status by tracking code |
/get_balance |
GET |
Get account balance |
/create_return_request |
POST |
Create a return request |
/get_return_request/{id} |
GET |
Get one return request |
/get_return_requests |
GET |
Get all return requests |