texhub / laklak-b2b
LakLak B2B delivery API SDK for any PHP framework with first-class Laravel support: cities, parcel terminals, pickup points, shipments, label printing and delivery webhooks.
Requires
- php: ^8.2
- ext-curl: *
- ext-hash: *
- ext-json: *
Requires (Dev)
- illuminate/support: ^11.0 || ^12.0 || ^13.0
- phpunit/phpunit: ^11.0 || ^12.0
Suggests
- illuminate/support: Required to use the package inside a Laravel application (service provider, facade, config publishing).
README
π English Β· Π ΡΡΡΠΊΠΈΠΉ
A clean, framework-agnostic PHP SDK for the LakLak B2B delivery API β cities, parcel terminals & pickup points, shipments, label printing and delivery webhooks β with first-class Laravel support.
What's new in v1.0.1
- Parcel terminals & pickup points now include
visible_id(e.g.PT-102,PP-042) and aclusterobject (id,name) β read them with$item['visible_id']/$response->get('cluster.name').- New delivery status
expired(andon_the_way) inDeliveryStatus;isFinal()now coversdeliveredandexpired.- The delivery address changed webhook now carries the full
drop_off_locationβ read it via$event->dropOffLocation().
β¨ Features
- π Addresses β cities, parcel terminals, pickup points (with search)
- π¦ Shipments β create, update payment status & weight, label print URL
- π Webhooks β verify
X-Webhook-Key+ timestamp, parse delivery status & address changes - π’ Test / Production switch Β·
X-API-Keyauth Β· typed enums & responses - β Fully unit-tested
π¦ Installation
composer require texhub/laklak-b2b
Requirements: PHP β₯ 8.2 with curl, json, hash.
π Quick start
use TexHub\LaklakB2b\LakLak; use TexHub\LaklakB2b\Enums\Environment; $laklak = LakLak::make('YOUR_API_KEY', Environment::Test); // Environment::Production when live // Addresses $cities = $laklak->addresses()->cities('Dush'); $terminals = $laklak->addresses()->parcelTerminals(cityId: 39720); $pickups = $laklak->addresses()->pickupPoints(cityId: 39720); foreach ($cities->data() as $city) { echo $city['id'] . ' ' . $city['name'] . PHP_EOL; }
π¦ Shipments
use TexHub\LaklakB2b\Requests\ShipmentRequest; use TexHub\LaklakB2b\Enums\DeliveryType; use TexHub\LaklakB2b\Enums\PaymentStatus; $shipment = $laklak->shipments()->create( ShipmentRequest::make( externalOrderId: 'ORD-100032', customerPhone: '+992900123456', deliveryType: DeliveryType::ParcelTerminal, dropOffLocationId: 2, paymentStatus: PaymentStatus::Unpaid, )->customerName('Anu Lily') ); echo $shipment->get('tracking_number'); // B2B-CODE-100001 echo $shipment->get('label_print_url'); // QR label to print & attach // Update payment status (+ weight when paid): $updated = $laklak->shipments()->updatePaymentStatus('ORD-100032', PaymentStatus::Paid, '2.5 KG'); echo $updated->get('parcel_terminal_password'); // Print labels for several shipments: $laklak->shipments()->labelPrintUrl(['B2B-CODE-100001', 'B2B-CODE-100002']);
When
payment_statusispaid, a packageweightis required (validated by the SDK).
π Webhooks (LakLak β you)
LakLak calls your URL with headers X-Webhook-Key (the secret you gave them) and X-Webhook-Timestamp.
use TexHub\LaklakB2b\Enums\DeliveryStatus; // Verify, then parse: $laklak->webhooks()->assertValid( $_SERVER['HTTP_X_WEBHOOK_KEY'] ?? null, $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? null, ); $event = $laklak->webhooks()->parse(file_get_contents('php://input')); if ($event->isDeliveryStatusChanged()) { $event->trackingNumber(); $event->externalOrderId(); $event->deliveryStatus(); // DeliveryStatus enum: pending|picked_up|on_the_way|ready_to_pick|delivered|expired $event->deliveryStatus()->isFinal(); // true for delivered/expired $event->parcelTerminalPassword(); } if ($event->isDeliveryAddressChanged()) { $event->deliveryType(); // DeliveryType enum $event->dropOffLocationId(); $event->dropOffLocation(); // full location array: id, visible_id, type, cluster, β¦ } http_response_code(200); // acknowledge
βοΈ Error handling
use TexHub\LaklakB2b\Exceptions\ApiException; try { $laklak->shipments()->create($request); } catch (ApiException $e) { $e->httpStatus; $e->isValidationError(); // 422 $e->errors; // ['field' => ['message', ...]] $e->isUnauthorized(); // 401/403 }
π§© Laravel
Auto-discovered. Publish config:
php artisan vendor:publish --tag=laklak-b2b-config
.env:
LAKLAK_ENVIRONMENT=test LAKLAK_API_KEY=your_api_key LAKLAK_WEBHOOK_SECRET=your_webhook_secret
Facade:
use TexHub\LaklakB2b\Laravel\LakLak; $cities = LakLak::addresses()->cities(); LakLak::shipments()->create($request);
Exclude your webhook route from CSRF (
VerifyCsrfToken::$except).
π§ͺ Testing
use TexHub\LaklakB2b\LakLak; use TexHub\LaklakB2b\Config; use TexHub\LaklakB2b\Tests\Support\FakeTransport; $t = (new FakeTransport())->push(['success' => true, 'data' => []]); $laklak = new LakLak(new Config('KEY'), $t); $laklak->addresses()->cities(); // assert on $t->last()
composer install && composer test
π Architecture
src/
βββ LakLak.php # entry β addresses()/shipments()/webhooks()
βββ Config.php # immutable configuration
βββ Enums/ # Environment, DeliveryType, PaymentStatus, DeliveryStatus
βββ Http/ # Transport, CurlTransport, HttpClient, RawResponse
βββ Requests/ShipmentRequest # fluent shipment builder
βββ Resources/ # Addresses, Shipments
βββ Webhook/ # WebhookHandler (verify + parse), WebhookEvent
βββ Responses/ # Response (ArrayAccess), ListResponse (paginated)
βββ Exceptions/ # ApiException, TransportException, β¦
βββ Laravel/ # ServiceProvider + Facade
License
MIT Β© TexHub Pro β built by Mahmudi Shodmehr.