Looking to hire Laravel developers? Try LaraJobs

laravel-gls maintained by beziworld

Description
GLS Poland (ADE-Plus WebAPI) client for Laravel: consignments, labels, pickup confirmations, ParcelShop search, services and tracking over SOAP, without ext-soap.
Last update
2026/11/04 18:18 (dev-master)
License
Downloads
1

Comments
comments powered by Disqus

Laravel GLS

tests Latest Version License

GLS Poland ADE-Plus WebAPI 2 client for Laravel:

  • consignments in the preparing box with a typed, immutable builder: receiver, parcels with weights and references, COD, ShopDelivery to a ParcelShop, 10:00 / 12:00 / Saturday delivery and the other ADE services
  • labels (roll PDF, A4 PDF one or four per page, ZPL 203/300 dpi, DPL), per consignment, per parcel or in bulk
  • pickup confirmations ("potwierdzenie nadania") with the printable receipt, courier orders
  • ParcelShop search (with point type: shop, locker), postal code checks, allowed and guaranteed services
  • tracking helpers: public tracking link, TrackID, proof of delivery
  • session handling: one login per process (or shared through a cache store), transparent re-login when ADE reports an expired session, logout
  • multiple GLS accounts (named connections and runtime credentials)
  • SOAP without ext-soap: requests go through the Laravel HTTP client, so they can be faked in tests

Polska wersja dokumentacji

Other GLS packages on Packagist are a thin Laravel 7 wrapper around ext-soap (kerogos/gls-polska) and a framework agnostic SDK from 2014 (webit/gls-ade). This package adds typed DTOs, a consignment builder, automatic session renewal, multiple accounts, fakeable transport and support for Laravel 12 and 13.

Installation

composer require beziworld/laravel-gls
php artisan vendor:publish --tag=gls-config   # optional
GLS_USERNAME=...              # ADE-Plus user with WebAPI access
GLS_PASSWORD=...
GLS_SANDBOX=false             # true = ade-test.gls-poland.com (separate accounts)
GLS_INTEGRATOR=               # optional integrator key (adeLoginIntegrator)
GLS_LABEL_MODE=roll_160x100_pdf
GLS_RECEIPT_MODE=condensed
GLS_SESSION_STORE=            # optional cache store shared by workers, e.g. redis

WebAPI access is enabled for an ADE-Plus user by GLS Poland (ask your GLS sales representative). Production requests go to https://adeplus.gls-poland.com/adeplus/pm1/ade_webapi2.php, test requests to https://ade-test.gls-poland.com/adeplus/pm1/ade_webapi2.php.

Consignment workflow

ADE works in three steps: a consignment is added to the preparing box, labels are printed (parcels receive their 11-digit numbers at that moment) and a pickup confirmation hands the consignments over to the courier. Creating a pickup confirmation cannot be undone.

use Beziworld\Gls\Data\Address;
use Beziworld\Gls\Data\Consignment;
use Beziworld\Gls\Facades\Gls;

$id = Gls::createConsignment(
    Consignment::to(new Address(
        name: 'Anna Kowalska',
        zipcode: '30-001',
        city: 'Kraków',
        street: 'Długa 5/3',
        phone: '600700800',
        contact: 'anna@example.com',
    ))
        ->withParcel(2.5, 'BOX-1')        // weight in kg, reference printed on the label
        ->withParcel(1.0, 'BOX-2')
        ->withReferences('ORDER-1')       // up to 25 characters
        ->withCod(149.99)                 // cash on delivery, PLN
        ->withDeliveryBy12(),
);

$label = Gls::labels($id);                // Document: content (binary), format, mimeType(), extension()
Storage::put("labels/{$id}.{$label->extension()}", $label->content);

$consignment = Gls::consignment($id);     // parcels now carry their numbers
$consignment->parcelNumbers();            // ['12345678901', '12345678902']

Builder methods: withParcel(), withParcels(), withReferences(), withNotes(), withDate(), withPfc() (cost centre), from() (sender address allowed for the account), withCod(), toParcelShop(), withDeliveryBy10(), withDeliveryBy12(), withSaturdayDelivery(), receiverPays() (EXW), withDocumentReturn() (ROD), withShopReturn() (SRS), withDeliveryAtWork() (DAW) and withServices(new Services(...)) for any other flag. Obvious mistakes (no parcel, weight below 0.01 kg, references longer than 25 characters, COD without an amount, ShopDelivery without a point or a receiver phone/e-mail) throw InvalidConsignment before any request is sent.

ADE WebAPI has no declared value (insurance) field; insurance is part of the GLS contract.

Other preparing box calls: consignmentIds() (all pages), deleteConsignment($id), deleteConsignmentByParcel($number). Deleting a consignment whose parcels already have numbers consumes those numbers.

Labels

Gls::labels($id);                                   // one file, configured mode
Gls::labels($id, 'four_labels_on_a4_pdf');
Gls::parcelLabels($id, 'roll_160x100_zebra');       // list<Document>, one per parcel, with ->number
Gls::consignmentsLabels([$id1, $id2]);              // several consignments in one file

Modes: roll_160x100_pdf, roll_160x100_vertical_pdf, roll_160x100_zebra (ZPL), roll_160x100_zebra_300 (ZPL 300 dpi), roll_160x100_datamax (DPL), one_label_on_a4_pdf, one_label_on_a4_lt_pdf, one_label_on_a4_rt_pdf, one_label_on_a4_lb_pdf, one_label_on_a4_rb_pdf, four_labels_on_a4_pdf, four_labels_on_a4_right_pdf. GLS allows reprinting labels for 60 days.

Pickup confirmations

$pickupId = Gls::createPickup([$id1, $id2], 'Evening pickup');   // description up to 40 characters

$receipt = Gls::pickupReceipt($pickupId);           // with_barcodes | condensed | condensed_description_of_pickup
Gls::pickupLabels($pickupId);                       // labels of every consignment on the confirmation
Gls::pickup($pickupId);                             // Pickup: description, quantity, weight, createdAt

$map = Gls::pickupConsignmentMap($pickupId);        // [preparing box id => pickup consignment id]
Gls::pickupConsignment($map[$id1]);                 // Consignment with parcel numbers
Gls::pickupConsignmentLabels($map[$id1]);
Gls::parcelsLabels(['12345678901']);                // labels by parcel number, any confirmation
Gls::findParcel('12345678901');                     // consignment containing a parcel
Gls::pickupIds();
Gls::pickupConsignmentIds($pickupId);

Gls::orderCourier(parcels: 3, date: '2026-11-05');  // only without regular pickups, one order per day

Consignments receive new identifiers on the pickup confirmation; pickupConsignmentMap() translates them.

ParcelShops

$points = Gls::parcelShops('30-001', street: 'Długa');   // up to 15 points within 50 km
$points[0]->id;              // pass to Consignment::toParcelShop()
$points[0]->type;            // ParcelShop::TYPE_SHOP, TYPE_LOCKER, TYPE_SHOP_IN_SHOP, TYPE_KEEPER
$points[0]->isLocker();
$points[0]->openingHours;    // [1 => ['open' => '08:00', 'close' => '20:00'], ...] (1 = Monday)
$points[0]->latitude;

Gls::parcelShop('PL12345');           // ?ParcelShop
Gls::parcelShopsInCountry('PL');      // every point (large response, cache it)
Gls::shopDeliveryCountries();         // ['PL', 'DE', ...]

ParcelShop search supports AT, BE, DE, DK and PL. ShopDelivery requires the receiver phone or e-mail.

Services and postal codes

Gls::allowedServices()->enabled();              // ['cod', 'exw', 'rod', 'sds', ...]
Gls::guaranteedServices('30-001')->saturday;    // 10:00, 12:00 and Saturday availability
Gls::maxCod();                                  // float, PLN
Gls::maxParcelWeights()->national;              // kg
Gls::city('30-001');                            // 'Kraków' or null
Gls::cities('30-001');

Tracking

Gls::trackingUrl('12345678901');          // https://gls-group.com/PL/pl/sledzenie-paczek/?match=12345678901
Gls::trackingUrl('12345678901', 'en');
Gls::trackId('12345678901');              // TrackID or null
Gls::proofOfDelivery('12345678901');      // Document (PDF)

ADE WebAPI does not return tracking events; use the public tracking page or the GLS Track and Trace API.

Sessions

The client logs in on the first call and keeps the session identifier for the lifetime of the process. ADE keeps a session valid for 30 minutes after the last call and allows 10 sessions per user (the oldest is dropped). When ADE answers err_sess_expired or err_sess_not_found, the client logs in again and repeats the call once; such a fault means the operation was not executed. Set GLS_SESSION_STORE to share one session between queue workers. Gls::logout() ends the session, Gls::logoutAll() ends every resolved connection.

Multiple accounts

// config/gls.php
'connections' => [
    'default' => ['username' => env('GLS_USERNAME'), 'password' => env('GLS_PASSWORD')],
    'warehouse-2' => ['username' => env('GLS_W2_USERNAME'), 'password' => env('GLS_W2_PASSWORD')],
],

Gls::connection('warehouse-2')->createConsignment($consignment);
Gls::using(['username' => $tenant->gls_user, 'password' => $tenant->gls_password])->labels($id);

Options outside connections (sandbox, timeout, modes, session store) are shared and can be overridden per connection.

Errors

Every exception extends Beziworld\Gls\Exceptions\GlsException, whose errorCode() returns the ADE error code.

Exception When
ApiException SOAP fault (errorCode() such as err_cons_receiver_zipcode_is_invalid, faultString() with the rejected values, detail(), operation(), httpStatus()), unexpected HTTP status
AuthenticationException rejected login: wrong credentials, blocked account, no WebAPI access (extends ApiException)
ConnectionException ADE cannot be reached; the call is never repeated
InvalidConsignment consignment data rejected locally, before any request
InvalidConfiguration missing credentials or unknown connection
try {
    Gls::createConsignment($consignment);
} catch (ApiException $e) {
    $e->errorCode();   // 'err_cons_srv_sds_parcelshop_id_not_found'
    $e->isNotFound();
}

Lookups return null or [] instead of throwing for unknown postal codes, ParcelShops and TrackIDs. Any other operation is available through Gls::call('adeProfile_GetIDs').

Testing your application

Http::fake(['adeplus.gls-poland.com/*' => Http::response($soapEnvelope)]);

Development

composer install
composer ci   # pint --test, phpstan (level 8), pest

Author

Created and maintained by Kamil Ćwiertnia, beziworld.eu.

Need a shipping integration for your shop? Get in touch through beziworld.eu.

Other packages by the author

laravel-inpost · laravel-dpd · laravel-dhl-parcel · laravel-orlen-paczka · laravel-furgonetka · laravel-apaczka

License

MIT. See LICENSE.md. This package is not affiliated with GLS.