Browse project documentation

Cookbook

Ersalv0.2.0-beta.2View sourceEnglish / Persian

Compare multiple carriers

$ersal = new Ersal();
$request = new QuoteRequest(origin: $o, destination: $d, parcel: $p);

$cheapest = null;

foreach ([
    ['tipax', new TipaxConfig('tipax-token')],
    ['chapar', new ChaparConfig('chapar-key')],
    ['post', new PostConfig(username: 'u', password: 'p', contractCode: 'c')],
] as [$alias, $config]) {
    $provider = $ersal->create($alias, $config);

    try {
        foreach ($provider->quote($request) as $quote) {
            if ($cheapest === null || $quote->cost->lessThan($cheapest->cost)) {
                $cheapest = $quote;
            }
        }
    } catch (ProviderException $e) {
        // this carrier doesn't service the route — skip
    }
}

echo "Cheapest: {$cheapest->providerName} — {$cheapest->cost->inToman()} Toman";

Book with cash-on-delivery

if ($provider instanceof SupportsCOD) {
    $booking = (new BookingRequest(
        origin: $o,
        destination: $d,
        parcel: $p,
        orderId: 'ORDER-123',
    ))->withCashOnDelivery(Amount::fromToman(250_000));

    $shipment = $provider->createShipment($booking);
}

Schedule a pickup

if ($provider instanceof SupportsPickup) {
    $pickup = new PickupRequest(
        windowStart: new DateTimeImmutable('tomorrow 10:00'),
        windowEnd: new DateTimeImmutable('tomorrow 12:00'),
        instructions: 'در زدن کافی است، پلاک 100 واحد 3',
    );

    $shipment = $provider->schedulePickup($shipment->getId(), $pickup);
}

Download a label

if ($provider instanceof SupportsLabel) {
    $label = $provider->getLabel($shipment->getId());

    if ($label->hasBytes()) {
        file_put_contents("labels/{$shipment->getId()}.{$label->format}", $label->bytes);
    } elseif ($label->hasUrl()) {
        header('Location: ' . $label->url);
    }
}

Find the nearest branch

if ($provider instanceof SupportsBranches) {
    $branches = $provider->listBranches('تهران');

    foreach ($branches as $branch) {
        printf("%s — %s\n", $branch->name, $branch->address);
    }
}

Poll until delivered

use Eram\Ersal\Shipment\ShipmentStatus;

while (true) {
    $shipment = $provider->track($shipmentId);

    if ($shipment->getStatus()->isTerminal()) {
        break;
    }

    sleep(900); // 15 minutes — respect carrier rate limits
}

if ($shipment->getStatus() === ShipmentStatus::Delivered) {
    $this->notifyCustomerOfDelivery($shipment);
}

Compute chargeable weight

$parcel = new Parcel(
    weightGrams: 500,             // light but bulky
    lengthMm: 500, widthMm: 400, heightMm: 300,
);

echo $parcel->weightGrams;              // 500
echo $parcel->volumetricWeightGrams();  // 12,000
echo $parcel->chargeableWeightGrams();  // 12,000 — you'll be billed for the bulk

Framework integration (Laravel example)

// config/services.php
return [
    'tipax' => ['token' => env('TIPAX_TOKEN')],
];

// In a service provider
$this->app->singleton(Ersal::class, function () {
    return new Ersal(
        logger: new MonologAdapter($this->app['log']),
        eventDispatcher: new LaravelDispatcher($this->app['events']),
    );
});

// In a controller
public function ship(Request $request, Ersal $ersal)
{
    $provider = $ersal->create('tipax', new TipaxConfig(
        token: config('services.tipax.token'),
    ));
    // ...
}

Search documentation

Search across all projects. Close this window to return to your guide.

Tab to navigate · Enter to openEsc to close