承接 kazistm/vargo 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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

Latest Version on Packagist Total Downloads License Laravel Compatibility

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

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. The alias_of key declares this relationship, and driver->isAlias() returns true for 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. Use DeliveryProviders::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 *PackagesStatus enum and a corresponding *PackageStatusNormalizer class that maps raw provider status values to the 5 canonical DeliveryStatuses values.

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

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-17

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固