kazistm/vargo
Composer 安装命令:
composer require kazistm/vargo
包简介
A unified Laravel integration package for 90+ Algerian delivery providers (Yalidine, EcoTrack, Procolis, ZR Express, Maystro, Noest, MDM, Zimou). Standardizes shipment creation, tracking, and location normalization with a single consistent API.
关键字:
README 文档
README
Vargo is a unified Laravel package for integrating Algerian delivery providers. It gives you a single, consistent API to create shipments, track packages, manage locations, and access advanced provider features — regardless of which carrier is underneath.
Supports 90+ providers across Yalidine, EcoTrack, Procolis, ZR Express, Maystro, MDM, Zimou Express, Near Delivery, and many more Algerian delivery networks.
Table of Contents
- Requirements
- Installation
- Configuration
- Quick Start
- Helper Functions
- Service Manager & Facade
- Available Providers
- Core Concepts
- Universal API
- Advanced Provider Features
- DTOs Reference
- Enums Reference
- Status Normalization
- Checking Capabilities
- Connection Validation
- Error Handling
- Request Tracing (X-Trace-Id)
- Authentication Fields
- Architecture Overview
- Testing with Vargo
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | ^11.0 | ^12.0 | ^13.0 |
kazistm/algeria-geo |
^2.0 |
Installation
composer require kazistm/vargo
The service provider is auto-discovered. You can publish the configuration and public logo assets using their respective tags:
# Publish configuration file php artisan vendor:publish --tag=vargo-config # Publish logo assets php artisan vendor:publish --tag=vargo-assets
Or publish both at once by referencing the service provider class:
php artisan vendor:publish --provider="KaziSTM\Vargo\VargoServiceProvider"
Database & Location Data Prerequisite
Vargo uses kazistm/algeria-geo for geographic data (wilayas/communes). Make sure to publish and run migrations/seeders for the algeria-geo package to populate these tables in your database:
php artisan algeria-geo:install --force # or run its migrations & seeders manually
Configuration
The published config/delivery.php file controls which providers are available and their base URLs:
// config/delivery.php return [ 'default' => env('DELIVERY_PROVIDER', 'elogistia'), 'providers' => [ 'elogistia' => [ 'driver' => ElogistiaDriver::class, 'base_url' => env('ELOGISTIA_BASE_URL', 'https://api.elogistia.com'), ], 'yalidine' => [ 'driver' => YalidineExpressDriver::class, 'base_url' => env('YALIDINE_EXPRESS_BASE_URL', 'https://api.yalidine.app'), ], // Clone providers use alias_of to point to their parent driver 'samex' => [ 'driver' => SamexDriver::class, 'alias_of' => 'ecotrack', 'base_url' => env('SAMEX_BASE_URL', 'https://samex.ecotrack.dz'), ], // ... all 80+ providers ], ];
Clone Providers — providers like Samex, Guepex, or Yalitec are built on top of a parent platform (EcoTrack or Yalidine). They share the same underlying API but use a different
base_url. Thealias_ofkey declares this relationship, anddriver->isAlias()returnstruefor these.
Quick Start
Using the delivery() Helper
use KaziSTM\Vargo\Enums\DeliveryProviders; // Get the service manager $manager = delivery(); // Instantiate a driver with credentials $driver = delivery_driver(DeliveryProviders::ELOGISTIA, [ 'api_key' => 'your-api-key', ]); // Create a shipment $result = $driver->createShipment([ 'recipientFirstName' => 'Ahmed', 'recipientLastName' => 'Benali', 'recipientPhone' => '0550000000', 'recipientAddress' => '12 Rue de la Paix', 'destinationCommune' => 'Bab El Oued', 'destinationWilaya' => 'Alger', 'originWilaya' => 'Alger', 'codAmount' => 3500, ]); echo $result->trackingNumber; // e.g. "ELG-20241234" echo $result->success; // true
Using the Facade
use KaziSTM\Vargo\Facades\DeliveryManager; $driver = DeliveryManager::using(DeliveryProviders::NOEST, [ 'api_token' => 'noest-token', 'user_guid' => 'your-guid', ]);
Switching Providers at Runtime
// All providers share the same interface — swap freely foreach ([DeliveryProviders::ELOGISTIA, DeliveryProviders::NOEST] as $provider) { $driver = delivery_driver($provider, $credentials[$provider->value]); $shipment = $driver->createShipment($payload); }
Service Manager & Facade
Fluent Service Manager
The DeliveryServiceManager supports a fluent interface for fine-grained control:
use KaziSTM\Vargo\Services\DeliveryServiceManager; $manager = delivery(); // Check if a provider is configured $manager->supports('elogistia'); // bool $manager->supports(DeliveryProviders::NOEST); // bool // List all configured provider keys $providers = $manager->availableProviders(); // ['yalidine', 'elogistia', ...] // Fluent chaining $driver = $manager ->provider(DeliveryProviders::ZR_EXPRESS) ->withCredentials(['api_key' => '...', 'tenant_id' => '...']) ->driver(); // One-line shorthand (equivalent) $driver = $manager->using(DeliveryProviders::ZR_EXPRESS, ['api_key' => '...', 'tenant_id' => '...']);
Facade
use KaziSTM\Vargo\Facades\DeliveryManager; // All DeliveryServiceManager methods available statically DeliveryManager::supports('elogistia'); // bool DeliveryManager::availableProviders(); // array DeliveryManager::using($provider, $creds); // DeliveryDriver DeliveryManager::provider($provider) // DeliveryServiceManager (chainable) ->withCredentials($creds) ->driver(); // Get capabilities for all or a specific provider DeliveryManager::getProviderCapabilities(); // ['yalidine' => ['createShipment', ...], ...] DeliveryManager::getProviderCapabilities('yalidine'); // ['createShipment', 'getTracking', ...]
Helper Functions
Two global helpers are registered automatically:
/** * Returns the DeliveryServiceManager singleton. */ function delivery(): DeliveryServiceManager; /** * Instantiates a driver for the given provider with credentials. * * @param DeliveryProviders|string $provider Enum case or string value (e.g. 'elogistia') * @param array $credentials Provider-specific credentials */ function delivery_driver(DeliveryProviders|string $provider, array $credentials): AbstractDriver;
Example:
$driver = delivery_driver('zr-express', [ 'api_key' => 'zr-key', 'tenant_id' => 'zr-tenant', ]);
Available Providers
Provider Families
| Family | Base Technology | Providers |
|---|---|---|
| Yalidine | Yalidine API | Yalidine Express, Guepex, Yalitec, Economiqua, Easy & Speed, We Can |
| EcoTrack | EcoTrack API | EcoTrack + 60 clone providers |
| Procolis | Procolis API | ABEX, Leopard Express, Colilog, Flash Delivery |
| Independent | Own APIs | Elogistia, Noest, ZR Express, Maystro, MDM, EcomDelivery, Near Delivery, Zimou Express |
Full Provider List
| Enum Case | Value | Label | Auth Fields |
|---|---|---|---|
YALIDINE_EXPRESS |
yalidine |
Yalidine Express | api_id, api_token |
ELOGISTIA |
elogistia |
Elogistia | api_key |
NOEST |
noest |
Noest Express | api_token, user_guid |
ECOTRACK |
ecotrack |
EcoTrack | api_token |
ECOM_DELIVERY |
ecom-delivery |
E-COM Delivery | api_token, api_key |
MAYSTRO_DELIVERY |
maystro-delivery |
Maystro Delivery | access_token, store_id |
ZR_EXPRESS |
zr-express |
ZR Express | api_key, tenant_id |
MDM_EXPRESS |
mdm |
MDM Express | api_token |
NEAR_DELIVERY |
near-delivery |
Near Delivery | api_key, api_secret |
ZIMOU_EXPRESS |
zimou-express |
Zimou Express | api_token |
SAMEX (Ecotrack clone) |
samex |
Samex | api_token |
GUEPEX (Yalidine clone) |
guepex |
GuepEx Express | api_id, api_token |
YALITEC (Yalidine clone) |
yalitec |
Yalitec | api_id, api_token |
ABEX (Procolis clone) |
abex |
ABEX Express | api_token |
LEOPARD_EXPRESS (Procolis clone) |
leopard-express |
Leopard Express | api_token |
| ... | ... | ... | ... |
Tip: All 80+ provider enum cases are defined in
KaziSTM\Vargo\Enums\DeliveryProviders. See COVERED-DRIVERS.md for a complete reference of all 89 supported providers and their API capabilities. UseDeliveryProviders::cases()to get all of them at runtime.
use KaziSTM\Vargo\Enums\DeliveryProviders; // Get a human-readable label echo DeliveryProviders::ELOGISTIA->getLabel(); // "Elogistia" // Get the logo URL echo DeliveryProviders::YALIDINE_EXPRESS->getLogo(); // asset('assets/logo/yalidine.png')
Core Concepts
Driver Capabilities
Not all providers support the same features. Vargo tracks this via the DriverCapability enum (113 cases). Check whether a driver supports a specific operation before calling it:
use KaziSTM\Vargo\Enums\DriverCapability; $driver = delivery_driver(DeliveryProviders::NOEST, $credentials); // Check a single capability if (in_array(DriverCapability::VALIDATE_ORDER, $driver->getCapabilities())) { $driver->validateShipment('TRACKING-123'); } // Calling an unsupported method throws UnsupportedDriverFeatureException
Common capabilities:
| Capability | Method |
|---|---|
CREATE_ORDER |
createShipment() |
CREATE_BULK |
createBulkShipments() |
UPDATE_ORDER |
updateShipment() |
DELETE_ORDER |
deleteShipment() |
BULK_DELETE_ORDER |
bulkDeleteShipments() |
GET_TRACKING |
getTracking() |
GET_SHIPMENT |
getShipment() |
LIST_SHIPMENT |
listShipments() |
GET_SHIPMENT_HISTORIES |
getShipmentHistories() |
LABEL |
downloadShipmentLabel() |
VALIDATE_ORDER |
validateShipment() |
VALIDATE_BULK_ORDER |
validateShipments() |
REQUEST_RETURN |
requestReturn() |
REQUEST_EXCHANGE |
requestExchange() |
ADD_REMARK |
addRemark() |
GET_REMARKS |
getShipmentUpdates() |
GET_STATES |
getStates() |
GET_COMMUNES |
getMunicipalities() |
GET_OFFICES |
getOffices() |
GET_PRICES |
fetchPrices() |
FILTER_ORDERS_STATUS |
filterShipmentsByStatus() |
Delivery Modes
use KaziSTM\Vargo\Enums\DeliveryMode; DeliveryMode::HOME; // value: 1 — home delivery DeliveryMode::STOP_DESK; // value: 2 — desk/stop-desk pickup
Each driver normalizes its own internal representation to this common enum. Use the normalization helpers on any driver:
// Provider integer → Vargo DeliveryMode $mode = $driver->normalizeDeliveryMode(1); // DeliveryMode::HOME // Vargo DeliveryMode → Provider integer $raw = $driver->denormalizeDeliveryMode(DeliveryMode::STOP_DESK); // provider-specific int
Delivery Statuses
Vargo maps every provider's raw status to one of five canonical values:
use KaziSTM\Vargo\Enums\DeliveryStatuses; DeliveryStatuses::IN_PREPARATION; // 'in_preparation' — shipment created, not yet picked up DeliveryStatuses::SHIPPED; // 'shipped' — in transit DeliveryStatuses::DELIVERED; // 'delivered' — successfully delivered DeliveryStatuses::DELIVERY_FAILED; // 'delivery_failed' — delivery attempt failed DeliveryStatuses::UNKNOWN; // 'unknown' — unmapped/unrecognized status
These normalized values appear in ShipmentTrackingData::$status, ShipmentSummaryData::$status, and ShipmentEventData::$status. The $providerStatus property on the same DTOs always contains the raw, provider-specific value.
Universal API
All drivers share these methods through the InteractsWithPackages, InteractsWithLocations and related contracts.
Shipments
Create a Shipment
Accepts either a CreateShipmentData DTO or a plain array:
use KaziSTM\Vargo\DTOs\CreateShipmentData; // Using the DTO (type-safe) $result = $driver->createShipment(new CreateShipmentData( originWilaya: 'Alger', recipientId: null, recipientFirstName: 'Fatima', recipientLastName: 'Zahra', recipientEmail: 'fatima@example.com', recipientPhone: '0661234567', recipientAddress: '5 Rue des Oliviers, Hydra', destinationCommune: 'Hydra', destinationWilaya: 'Alger', codAmount: 5000, notes: 'Leave with the concierge', stopdesk: false, fragile: true, )); // Using a plain array (auto-converted to DTO) $result = $driver->createShipment([ 'originWilaya' => 'Oran', 'recipientFirstName' => 'Karim', 'recipientLastName' => 'Hadj', 'recipientPhone' => '0770000000', 'recipientAddress' => '10 Blvd Mokhtar', 'destinationCommune' => 'Oran Centre', 'destinationWilaya' => 'Oran', 'codAmount' => 2800, ]); // Result $result->success; // bool $result->trackingNumber; // string|null $result->reference; // string|null $result->message; // string|null $result->raw; // array — raw provider response
Update a Shipment
$result = $driver->updateShipment('TRACKING-123', [ 'codAmount' => 3200, 'recipientPhone' => '0551234567', ]);
Delete a Shipment
$result = $driver->deleteShipment('TRACKING-123'); // or with DTO $result = $driver->deleteShipment(new TrackShipmentData('TRACKING-123'));
List Shipments
$shipments = $driver->listShipments([ 'page' => 1, 'status' => 'delivered', ]); foreach ($shipments as $shipment) { echo $shipment->trackingNumber; echo $shipment->status; }
Get a Shipment
$shipment = $driver->getShipment('TRACKING-123'); $shipment->trackingNumber; $shipment->status; $shipment->recipientName;
Tracking
Get Tracking
$tracking = $driver->getTracking('TRACKING-123'); $tracking->trackingNumber; $tracking->status; // normalized status string $tracking->events; // array of tracking events
Get Shipment History
$history = $driver->getShipmentHistory('TRACKING-123');
Get Multiple Histories (Batch)
$histories = $driver->getShipmentHistories([ 'TRACKING-001', 'TRACKING-002', 'TRACKING-003', ]);
Locations
States / Wilayas
$states = $driver->getStates(); foreach ($states as $state) { $state->id; // wilaya ID $state->name; // wilaya name }
Municipalities / Communes
// All communes $communes = $driver->getMunicipalities(); // Filtered by wilaya $communes = $driver->getMunicipalities(stateId: 16); // Wilaya 16 = Alger
Stop Desk Offices
$offices = $driver->getOffices(wilayaId: 31); // Oran offices foreach ($offices as $office) { $office->id; $office->name; $office->address; $office->wilayaId; }
Delivery Prices
$prices = $driver->fetchPrices([ 'from_wilaya_id' => 16, 'to_wilaya_id' => 31, ]); foreach ($prices as $price) { $price->wilayaId; $price->homePrice; $price->deskPrice; }
Labels
// Download label as HTTP response (contains PDF/ZPL binary) $response = $driver->downloadShipmentLabel('TRACKING-123'); // With a format hint (provider-specific, e.g. 'pdf', 'zpl') $response = $driver->downloadShipmentLabel('TRACKING-123', format: 'pdf'); // Stream to browser return response($response->body(), 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="label.pdf"', ]);
Validation
Some providers require an explicit confirmation step after creating a shipment:
// Validate a single shipment $result = $driver->validateShipment('TRACKING-123'); // Validate multiple shipments at once $results = $driver->validateShipments([ 'TRACKING-001', 'TRACKING-002', ]);
Returns
$result = $driver->requestReturn('TRACKING-123'); // Some providers accept a payload array instead of just a tracking number $result = $driver->requestReturn([ 'tracking_number' => 'TRACKING-123', 'reason' => 'Customer refused delivery', ]);
Remarks
// Add an agent remark to a shipment $result = $driver->addRemark('TRACKING-123', 'Customer not reachable, retry tomorrow'); // Get all remarks/updates for a shipment $updates = $driver->getShipmentUpdates('TRACKING-123');
Filter by Status
For providers that support it (FILTER_ORDERS_STATUS capability), filter a list of tracking numbers down to those matching specific statuses:
$matches = $driver->filterShipmentsByStatus( trackings: ['TRACKING-001', 'TRACKING-002', 'TRACKING-003'], statuses: ['delivered', 'returned'], ); // Returns array<int, ShipmentTrackingData> foreach ($matches as $tracking) { echo $tracking->trackingNumber . ': ' . $tracking->status; }
Advanced Provider Features
ZR Express
ZR Express is the most feature-rich driver, supporting the full API surface: shipments, catalog, clients, claims, treasury, webhooks, pickup bags, and reports.
Authentication:
$driver = delivery_driver(DeliveryProviders::ZR_EXPRESS, [ 'api_key' => 'your-api-key', 'tenant_id' => 'your-tenant-id', ]);
Catalog:
// Search products $products = $driver->searchProducts(['search' => 'shirt', 'page' => 1]); // Get a product $product = $driver->getProduct('prod-uuid'); // Update product $driver->updateProduct('prod-uuid', ['price' => 2500]); // Update price $driver->updateProductPrice('prod-uuid', 2500.00); // Update stock $driver->updateProductStock('prod-uuid', 100); // Create stock movement $movementId = $driver->createStockMovement([ ['product_id' => 'prod-uuid', 'quantity' => 10], ]);
Clients:
$clients = $driver->searchClients(['phone' => '0550000000']); $client = $driver->getClient('client-uuid'); $id = $driver->createClient(['name' => 'Ali', 'phone' => '0550000000']); $driver->updateClient('client-uuid', ['name' => 'Ali Updated']); $driver->deleteClient('client-uuid'); // Addresses $addrId = $driver->addClientAddress('client-uuid', ['wilaya_id' => 16, ...]); $driver->updateClientAddress('client-uuid', $addrId, ['address' => '...']); $driver->deleteClientAddress('client-uuid', $addrId);
Claims:
$claims = $driver->searchClaims(['status' => 'open']); $claim = $driver->getClaim('claim-uuid'); $id = $driver->createClaim(['tracking_number' => 'ZR-001', 'reason' => '...']); $driver->updateClaim('claim-uuid', ['status' => 'resolved']); $history = $driver->getClaimHistory('claim-uuid'); $driver->createClaimComment('claim-uuid', 'Investigating now'); $comments = $driver->searchClaimComments('claim-uuid'); $categories = $driver->searchClaimCategories();
Treasury:
$payments = $driver->searchSupplierPayments(['page' => 1]); $payment = $driver->getSupplierPaymentDetails('payment-uuid'); $driver->acceptSupplierPayment('payment-uuid'); $stats = $driver->getTransactionStats(); $balance = $driver->getSupplierBalance(); $export = $driver->exportSupplierPayments(['format' => 'csv']);
Pickup Bags:
$bag = $driver->createPickupBag(['wilaya_id' => 16]); $bags = $driver->searchPickupBags(); $bag = $driver->getPickupBag('bag-uuid'); $driver->addParcelToBag('bag-uuid', 'TRACKING-123'); $driver->removeParcelFromBag('bag-uuid', 'TRACKING-123'); $label = $driver->printPickupBag('bag-uuid'); $driver->deletePickupBag('bag-uuid');
Webhooks:
$endpoint = $driver->createWebhookEndpoint([ 'url' => 'https://myapp.com/webhooks/zr', 'events' => ['shipment.delivered', 'shipment.returned'], ]); $endpoints = $driver->listWebhookEndpoints(); $endpoint = $driver->getWebhookEndpoint('endpoint-uuid'); $driver->updateWebhookEndpoint('endpoint-uuid', ['url' => 'https://...']); $driver->deleteWebhookEndpoint('endpoint-uuid'); $headers = $driver->getWebhookEndpointHeaders('endpoint-uuid'); $secret = $driver->getWebhookEndpointSecret('endpoint-uuid');
Reports:
$reports = $driver->searchReports(); $report = $driver->downloadReport('report-uuid');
Maystro
Authentication:
$driver = delivery_driver(DeliveryProviders::MAYSTRO_DELIVERY, [ 'access_token' => 'your-access-token', 'store_id' => 'your-store-uuid', ]);
Catalog:
$products = $driver->listProducts(); $product = $driver->getProduct('prod-uuid'); $driver->createProduct([...]); $driver->updateProduct('prod-uuid', [...]); $driver->deleteProduct('prod-uuid');
Webhooks:
$driver->createWebhookEndpoint(['url' => 'https://myapp.com/webhooks/maystro']); $driver->listWebhookEndpoints(); $driver->deleteWebhookEndpoint('endpoint-uuid');
MDM Express
MDM is a full-featured e-commerce and delivery platform with stores, product variants, offers, and media management.
Authentication:
$driver = delivery_driver(DeliveryProviders::MDM_EXPRESS, [ 'api_token' => 'your-api-token', ]);
Stores:
$driver->createStore([...]); $stores = $driver->searchStores(); $store = $driver->getStore('store-uuid'); $driver->updateStore('store-uuid', [...]); $metadata = $driver->getStoreMetadata();
Catalog (Products, Variants, Offers):
$products = $driver->listProducts(); $driver->createProduct([...]); $driver->updateProductPrice('prod-uuid', 1500.0); $driver->updateProductDiscount('prod-uuid', ['percentage' => 10]); $driver->addProductImage('prod-uuid', $imageData); // Variants $variants = $driver->searchProductVariants('prod-uuid'); $driver->createProductVariant('prod-uuid', [...]); $driver->updateProductVariant('prod-uuid', 'variant-uuid', [...]); // Offers $offers = $driver->searchProductOffers('prod-uuid'); $driver->createProductOffer('prod-uuid', [...]); $driver->updateProductOffer('prod-uuid', 'offer-uuid', [...]); // Categories $categories = $driver->searchCategories(); $driver->updateProductCategory('cat-uuid', [...]);
Stats & Auth:
$stats = $driver->getParcelStats(); $meta = $driver->getAuthMetadata(); $profile = $driver->getMyProfile(); $media = $driver->getMedia('media-uuid');
Zimou Express
Zimou is the most feature-complete fully-integrated driver, covering orders, employees, payments, products (incl. dropship & warehouse), stores, and miscellaneous platform utilities.
Authentication:
$driver = delivery_driver(DeliveryProviders::ZIMOU_EXPRESS, [ 'api_token' => 'your-api-token', ]);
Standard Parcel Operations (shared with all drivers):
$driver->createShipment($payload); $driver->getTracking('ZM-001'); $driver->downloadShipmentLabel('ZM-001'); $driver->validateShipment('ZM-001'); $driver->validateShipments(['ZM-001', 'ZM-002']); $driver->requestReturn('ZM-001'); $driver->filterShipmentsByStatus(['ZM-001'], ['delivered', 'returned']); $driver->addRemark('ZM-001', 'Customer called, delay requested'); $updates = $driver->getShipmentUpdates('ZM-001');
Orders (Zimou-native):
$orders = $driver->listZimouOrders(['page' => 1]); $order = $driver->getZimouOrder('order-id'); $driver->createZimouOrder([...]); $driver->updateZimouOrder('order-id', [...]); $driver->deleteZimouOrder('order-id'); $driver->updateZimouOrderStatus('order-id', 'confirmed'); $stats = $driver->getZimouOrdersStatsByStatus(); $pkg = $driver->convertZimouOrderToPackage('order-id');
Products (Standard, Dropship & Warehouse):
// Standard products $products = $driver->listZimouProducts(); $driver->createZimouProduct([...]); $driver->updateZimouProduct('id', [...]); $driver->deleteZimouProduct('id'); $quantities = $driver->getZimouProductsQuantities(['id1', 'id2']); // Dropship $dropship = $driver->listZimouDropshipProducts(); $driver->getZimouDropshipProduct(42); $driver->getZimouDropshipProductsQuantities([...]); $driver->listZimouDropships(); // Warehouse $wh = $driver->listZimouWarehouseProducts(); $driver->createZimouWarehouseProduct([...]); $driver->updateZimouWarehouseProduct(42, [...]); $driver->deleteZimouWarehouseProduct(42); $driver->createZimouWarehouseProductDeliveries([...]);
Stores:
$stores = $driver->listZimouDeliveryStores(); $store = $driver->getZimouDeliveryStore(1); $driver->updateZimouDeliveryStore(1, 'active'); $driver->printZimouDeliveryStore(1); $myStores = $driver->listZimouMyStores(); $delivTypes = $driver->listZimouMyDeliveryTypes(); $stopdesks = $driver->listZimouStoreStopdesks(); $comparators = $driver->getZimouComparators('commune-id');
Payments:
$payments = $driver->listZimouPayments(); $driver->createZimouPayment([...]); $payment = $driver->getZimouPayment(1); $driver->confirmZimouPayment(1); $driver->exportZimouPayments(); $stats = $driver->getZimouPaymentsStatsByPackageStatus();
Employees:
$employees = $driver->listZimouEmployees(); $driver->createZimouEmployee([...]); $employee = $driver->getZimouEmployee(1); $driver->updateZimouEmployee(1, [...]); $driver->deleteZimouEmployee(1, $credentials);
Platform Utilities:
// Stats & reporting $stats = $driver->getZimouPackagesStatsByStatus(); $stats = $driver->getZimouPackagesStatsBySituation(); $stats = $driver->getZimouStatistics(['from' => '2024-01-01']); $driver->exportZimouPackages(); $driver->printZimouPackages(['ZM-001', 'ZM-002']); // Status lookups $statuses = $driver->listZimouPackageStatuses(); $situations = $driver->listZimouPackageSituations(); $reasons = $driver->listZimouReasons(); // Bulk & pricing $driver->createZimouPackageBulk([...]); $price = $driver->calculateZimouPackagePrice([...]); $driver->createZimouPackagePriceChange('package-id', [...]); $driver->markZimouPackagesAsDispatched([...]); // Imports $imports = $driver->listZimouPackageImportations(); $driver->createZimouPackageImportation([...]); // Warehouses $warehouses = $driver->listZimouWarehouses(); // Auth $token = $driver->loginZimou('email', 'password'); $token = $driver->generateNewZimouToken();
DTOs Reference
CreateShipmentData
use KaziSTM\Vargo\DTOs\CreateShipmentData; new CreateShipmentData( originWilaya: string, // required — sender's wilaya name recipientId: ?string, // optional — provider-side recipient UUID recipientFirstName: string, // required recipientLastName: string, // required recipientEmail: ?string, // optional recipientPhone: string, // required recipientAddress: string, // required destinationCommune: string, // required — commune name destinationWilaya: string, // required — wilaya name codAmount: int|float, // required — cash on delivery amount (DZD) deliveryFee: int|float|null = null, externalId: ?string = null, // your internal order ID items: ?array = null, // product items insured: ?bool = null, declaredValue: int|float|null = null, height: int|float|null = null, // cm width: int|float|null = null, // cm length: int|float|null = null, // cm weight: int|float|null = null, // kg freeShipping: ?bool = null, stopdesk: ?bool = null, // true = stop desk delivery stopdeskId: mixed = null, // office ID exchange: ?bool = null, // true = exchange shipment exchangeItems: mixed = null, fragile: ?bool = null, liquid: ?bool = null, openable: ?bool = null, // can be opened on delivery notes: ?string = null, );
TrackShipmentData
use KaziSTM\Vargo\DTOs\TrackShipmentData; new TrackShipmentData(trackingNumber: 'ELG-001234'); // All tracking methods accept either the DTO or a plain string: $driver->getTracking('ELG-001234'); $driver->getTracking(new TrackShipmentData('ELG-001234'));
Response DTOs
ShipmentActionResultData
Returned by createShipment(), deleteShipment(), validateShipment(), etc.
$result->provider; // string — provider key $result->action; // string — action name (e.g. 'createShipment') $result->success; // bool $result->trackingNumber; // ?string $result->reference; // ?string — provider's internal reference $result->message; // ?string — success or error message from provider $result->code; // int|string|null — provider error code $result->raw; // array — full raw provider response
ShipmentTrackingData
Returned by getTracking(), getShipmentHistory(), getShipmentHistories().
$tracking->trackingNumber; // string $tracking->status; // string — normalized (DeliveryStatuses value) $tracking->providerStatus; // string — raw provider status $tracking->isDelivered; // bool $tracking->isFailed; // bool $tracking->events; // array<int, ShipmentEventData> $tracking->raw; // array
ShipmentEventData
Individual timeline entry within ShipmentTrackingData::$events.
$event->status; // string — normalized status $event->providerStatus;// string — raw status $event->label; // string — human-readable description $event->location; // ?string $event->occurredAt; // ?\DateTimeInterface $event->meta; // ?array — additional provider data
ShipmentSummaryData
Returned by listShipments(), getShipment().
$shipment->trackingNumber; // string $shipment->status; // string — normalized $shipment->providerStatus; // string — raw $shipment->reference; // ?string $shipment->recipientName; // ?string $shipment->recipientPhone; // ?string $shipment->recipientPhone2; // ?string $shipment->recipientAddress; // ?string $shipment->destinationCommune; // ?string $shipment->destinationWilayaId; // int|string|null $shipment->destinationWilayaName; // ?string $shipment->codAmount; // int|float|null $shipment->deliveryFee; // int|float|null $shipment->returnFee; // int|float|null $shipment->createdAt; // ?\DateTimeInterface $shipment->raw; // array
CityData (Wilaya)
$city->id; // int $city->code; // string — e.g. '16' $city->name; // string — e.g. 'Alger' $city->arabicName; // string $city->slug; // string $city->longitude; // ?float $city->latitude; // ?float
CommuneData
$commune->id; // int $commune->wilayaId; // int $commune->postalCode; // string $commune->name; // string $commune->arabicName; // string $commune->slug; // string $commune->longitude; // ?float $commune->latitude; // ?float
ProviderOfficeData (Stop-desk)
$office->name; // string $office->code; // ?string $office->address; // ?string $office->commune; // ?string $office->wilayaId; // int|string|null $office->wilayaName; // ?string $office->phones; // array<int, string> $office->email; // ?string $office->map; // ?string — map URL $office->raw; // array
DeliveryPriceData
$price->wilayaId; // int|string|null $price->wilayaName; // ?string $price->communeId; // int|string|null $price->communeName; // ?string $price->fromWilayaId; // int|string|null $price->toWilayaId; // int|string|null $price->zone; // ?int $price->homePrice; // int|float|null $price->stopDeskPrice; // int|float|null $price->type; // DeliveryType enum $price->level; // ?DeliveryServiceLevel enum $price->raw; // array
Enums Reference
DeliveryStatuses — normalized status vocabulary
DeliveryStatuses::IN_PREPARATION // 'in_preparation' DeliveryStatuses::SHIPPED // 'shipped' DeliveryStatuses::DELIVERED // 'delivered' DeliveryStatuses::DELIVERY_FAILED // 'delivery_failed' DeliveryStatuses::UNKNOWN // 'unknown'
DeliveryMode — delivery type
DeliveryMode::HOME; // 1 DeliveryMode::STOP_DESK; // 2
DeliveryServiceLevel — pricing tiers
DeliveryServiceLevel::EXPRESS_HOME; // 'express_home' DeliveryServiceLevel::EXPRESS_DESK; // 'express_desk' DeliveryServiceLevel::ECONOMIC_HOME; // 'economic_home' DeliveryServiceLevel::ECONOMIC_DESK; // 'economic_desk'
DeliveryType — shipment type
DeliveryType::DELIVERY; // 'delivery' DeliveryType::PICKUP; // 'pickup' DeliveryType::RETURN; // 'return' DeliveryType::EXCHANGE; // 'exchange' DeliveryType::COLLECTION; // 'collection'
HttpMethods — used internally
HttpMethods::GET; HttpMethods::POST; HttpMethods::PUT; HttpMethods::PATCH; HttpMethods::DELETE;
Status Normalization
Vargo normalizes each provider's raw shipment status into a consistent DeliveryStatuses value. Get the normalizer class for the active driver:
$normalizerClass = $driver->getPackageStatusNormalizer(); // e.g. KaziSTM\Vargo\Services\Elogistia\Normalizers\ElogistiaPackageStatusNormalizer // Get all raw statuses the provider uses $statuses = $driver->getPackageStatuses(); // e.g. array of ElogistiaPackagesStatus enum cases
Each provider has a dedicated
*PackagesStatusenum and a corresponding*PackageStatusNormalizerclass that maps raw provider status values to the 5 canonicalDeliveryStatusesvalues.
Checking Capabilities
Always check driver capabilities before calling optional methods:
use KaziSTM\Vargo\Enums\DriverCapability; $capabilities = $driver->getCapabilities(); // Using in_array if (in_array(DriverCapability::REQUEST_RETURN, $capabilities)) { $driver->requestReturn('TRACKING-123'); } // Check before webhook operations if (in_array(DriverCapability::CREATE_WEBHOOK_ENDPOINT, $capabilities)) { $driver->createWebhookEndpoint([...]); }
Calling an unsupported method throws
KaziSTM\Vargo\Exceptions\UnsupportedDriverFeatureException.
Connection Validation
Test whether a driver's credentials are valid against the live provider API:
$driver = delivery_driver(DeliveryProviders::ELOGISTIA, [ 'api_key' => 'possible-invalid-key', ]); if ($driver->validateConnection()) { // credentials are valid, proceed } else { // show configuration error to user }
This fires a real lightweight HTTP request to the provider. Use sparingly (e.g., when saving credentials in your admin panel).
Error Handling
Vargo throws typed exceptions:
| Exception | When |
|---|---|
ProviderRequestException |
HTTP request to provider failed |
ProviderTransportException |
Network-level transport error |
ProviderNotSupportedException |
Provider key not found in config |
UnsupportedDriverFeatureException |
Method not supported by driver |
use KaziSTM\Vargo\Exceptions\ProviderRequestException; use KaziSTM\Vargo\Exceptions\UnsupportedDriverFeatureException; try { $result = $driver->createShipment($payload); } catch (ProviderRequestException $e) { // The provider returned an error response Log::error('Delivery provider error', ['message' => $e->getMessage()]); } catch (UnsupportedDriverFeatureException $e) { // Method not available for this driver abort(422, $e->getMessage()); }
Request Tracing (X-Trace-Id)
To help with debugging and tracing API requests across delivery providers, Vargo automatically generates and injects a unique trace UUID into the headers of every outgoing HTTP request:
X-Trace-Id: A unique UUID generated per HTTP request.X-Provider: The slug name of the active provider.
You can inspect these headers or use them for request correlation in your logging system.
Authentication Fields
Use getAuthenticationFields() to dynamically build credential forms in your admin panel:
$fields = $driver->getAuthenticationFields(); // Example output for Yalidine: // [ // 'api_id' => [ // 'type' => 'text', // 'label' => 'API ID', // 'rules' => ['required', 'string'], // ], // 'api_token' => [ // 'type' => 'password', // 'label' => 'API Token', // 'rules' => ['required', 'string'], // ], // ]
This allows a single dynamic form component to handle all providers.
Testing with Vargo
Vargo is built for testability. Use Laravel's Http::fake() to mock provider responses in your tests:
use Illuminate\Support\Facades\Http; Http::fake([ 'api.elogistia.com/*' => Http::response([ 'success' => true, 'tracking_number' => 'ELG-TEST-001', ], 200), ]); $driver = delivery_driver(DeliveryProviders::ELOGISTIA, [ 'api_key' => 'test-key', ]); $result = $driver->createShipment([...]); expect($result->trackingNumber)->toBe('ELG-TEST-001'); expect($result->success)->toBeTrue();
Package Test Helpers
The package's own test suite provides reusable helpers in tests/Support/:
// Configure all providers for testing configureDeliveryProviders(); // Refresh location fixtures (wilayas/communes) refreshDeliveryLocationFixtures();
Architecture Overview
For a detailed guide on the design principles, codebase structure, and trait organization, see the Vargo Architecture Guide.
Application
│
▼
delivery() / DeliveryManager facade
│
▼
DeliveryServiceManager
├─ supports() availableProviders()
├─ provider()->withCredentials()->driver()
└─ resolveDriver() ──reads──▶ config('delivery.providers')
│
reads driver class + base_url
resolves alias_of if clone
│
▼
AbstractDriver (base class)
│
┌──────────┼──────────────┐
▼ ▼ ▼
EcotrackDriver YalidineDriver ProcolisDriver
(+74 clones) (+5 clones) (+4 clones)
ElogistiaDriver NoestDriver EcomDeliveryDriver
MaystroDriver NearDeliveryDriver
ZimouExpressDriver ZrExpressDriver MdmDriver
Clone Pattern: 83 drivers subclass a base driver, overriding only getName() and getCompanyLogo(). All API logic is in service traits (Services/{Provider}/Traits/).
Factory Pattern: CreateShipmentDataFactory / TrackShipmentDataFactory accept both camelCase and snake_case keys and are idempotent (pass-through if already a DTO).
Capability Declaration: Each driver declares protected array $capabilities. Calling an unsupported method auto-throws UnsupportedDriverFeatureException via the HandleUnsupportedActions trait.
Location Resolution: LocationNormalizer uses a bundled LocationIndex of Algeria's 1541 communes and 58 wilayas to canonically resolve provider location strings/IDs to CityData/CommuneData.
Credential Validation: validateCredentialStructure() runs at construction time using each driver's getAuthenticationFields() rules. validateConnection() fires a lightweight live API ping, cached for 10 minutes.
Provider Capability Matrix
| Provider | Create | Track | List | Label | Validate | Return | Locations | Prices | Webhooks | Catalog |
|---|---|---|---|---|---|---|---|---|---|---|
| Yalidine | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Elogistia | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Noest | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| EcoTrack | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| EcoTrack clones | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Maystro | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| ZR Express | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| MDM Express | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ |
| Near Delivery | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Zimou Express | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| E-COM Delivery | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Procolis clones | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
License
MIT — see LICENSE for details.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-17