Installation
composer require pralhadstha/nepalcan-laravel
The package uses auto-discovery, so no manual service provider registration is needed.
Publish Configuration
php artisan vendor:publish --provider="OmniCargo\NepalCan\NepalCanServiceProvider" --tag="config"
This generates .env keys:
NEPALCAN_API_TOKEN=your_api_token_here
NEPALCAN_API_BASE_URL=https://api.nepalcanmove.com
First Use Case: Create a Shipment
use OmniCargo\NepalCan\Facades\NepalCan;
$shipment = NepalCan::shipments()->create([
'pickup' => [
'address' => 'Kathmandu, Nepal',
'contact' => '012345678',
],
'delivery' => [
'address' => 'Pokhara, Nepal',
'contact' => '987654321',
],
'items' => [
['name' => 'Laptop', 'weight' => 1.5, 'value' => 10000],
],
'service' => 'standard',
]);
Inject the Client directly into services for type safety:
use OmniCargo\NepalCan\Client;
class OrderShipperService {
public function __construct(private Client $nepalCanClient) {}
public function shipOrder(Order $order) {
$this->nepalCanClient->shipments()->create($order->toShipmentArray());
}
}
$rate = NepalCan::rates()->calculate($from, $to, $weight);
Register a listener for shipment.created:
use OmniCargo\NepalCan\Events\WebhookReceived;
class HandleNepalCanWebhooks {
public function handle(WebhookReceived $event) {
if ($event->type === 'shipment.created') {
// Process webhook data
}
}
}
The package auto-registers a webhook route at /nepalcan/webhook with middleware for user-agent validation.
$rates = NepalCan::rates()->calculate(
from: 'Kathmandu',
to: 'Dharan',
weight: 2.3,
service: 'express'
);
$tracking = NepalCan::trackings()->get('NCM123456789');
.env overrides for staging/production API tokens.try {
$shipment = NepalCan::shipments()->create(...);
} catch (\OmniCargo\NepalCan\Exceptions\ApiException $e) {
Log::error('NCM API Error: ' . $e->getMessage());
return response()->json(['error' => 'Shipping failed'], 500);
}
Client directly in tests to mock responses:
$client = $this->app->make(Client::class);
$client->shouldReceive('createShipment')->once()->andReturn($mockShipment);
Webhook Verification
User-Agent header for webhooks. If testing locally, ensure your request includes:
User-Agent: NepalCanWebhook/1.0
SIGNATURE_VERIFICATION_FAILED errors.Rate Limits
use Symfony\Component\HttpClient\RetryableHttpClient;
$client = new RetryableHttpClient(
$baseClient,
[
'max_retries' => 3,
'delay_factor' => 200,
]
);
COD (Cash on Delivery) Handling
cod_amount, cod_currency). Validate these before submission:
$data['cod'] = [
'amount' => $order->amount,
'currency' => 'NPR',
];
Timezone Mismatches
config/app.php timezone matches expectations (e.g., Asia/Kathmandu).Enable API Debugging:
Add to .env:
NEPALCAN_DEBUG=true
This logs raw API requests/responses to storage/logs/nepalcan.log.
Webhook Testing:
Use Laravel’s artisan serve with --host=0.0.0.0 to test webhook callbacks locally. Forward the webhook URL via ngrok:
ngrok http 8000
Custom Webhook Routes Override the default webhook route by binding a custom controller:
NepalCan::extend(function ($service) {
$service->webhookRoute(function () {
return Route::post('/custom-webhook', [CustomWebhookController::class, 'handle']);
});
});
Add New Services
Extend the Client to support additional NCM services (e.g., returns, labels):
NepalCan::extend(function ($client) {
$client->returns = new ReturnsService($client);
});
Mocking for Tests
Use the MockClient for unit tests:
$mockClient = new MockClient();
$mockClient->shouldReceive('createShipment')->andReturn($mockResponse);
$this->app->instance(Client::class, $mockClient);
NepalCan::setBaseUrl(config('services.nepalcan.staging_url'));
.env and restarting the queue worker (if using delayed jobs).How can I help you explore Laravel packages today?