ages/shipping-gateway
Composer 安装命令:
composer require ages/shipping-gateway
包简介
Unified shipping carrier API for CzechPost, GLS, PPL
README 文档
README
Unified PHP library for shipping carrier integrations — GLS, PPL, Czech Post, Gebrüder Weiss.
Single entry point, config-driven credentials and pickup address, compatible with Nette + Nextras.
API Documentation
| Dopravce | Odkaz |
|---|---|
| GLS | https://api.mygls.hu/index_cz.html |
| PPL | https://ppl-cpl-api.apidog.io/ |
| Česká pošta | https://www.postaonline.cz/dokumentaceapi/b2b/ |
| Gebrüder Weiss | https://developer.my.gw-world.com/#/apis |
Requirements
- PHP 8.4+
- Nette Utils
^4.0 - Guzzle
^7.9 - mPDF
^8.3
Installation
composer require ages/shipping-gateway
Or add a path repository for local development:
{
"repositories": [
{
"type": "path",
"url": "../shipping-gateway"
}
],
"require": {
"ages/shipping-gateway": "*"
}
}
Configuration (Nette / neon)
All credentials and pickup address are configured in config.neon — nothing is hardcoded.
services: pickupAddress: Ages\ShippingGateway\Common\PickupAddress( name: 'MyShop s.r.o.' street: Ulice city: Město zip: '12345' country: CZ phone: '+420 123 456 789' email: 'info@myshop.cz' houseNumber: '10' # company: 'my-company-code' # volitelne, pouziva se jen pro GW tracking URL ) glsConfig: Ages\ShippingGateway\Gls\Config\GlsConfig( username: 'user@example.com' password: secret clientNumber: 12345678 pickupAddress: @pickupAddress # url: https://api.test.mygls.cz/ParcelService.svc/json/ # test endpoint ) pplConfig: Ages\ShippingGateway\Ppl\Config\PplConfig( clientId: CLIENT_ID clientSecret: CLIENT_SECRET pickupAddress: @pickupAddress # url: https://api-dev.dhl.com/ecs/ppl/myapi2/ # test endpoint ) czechPostConfig: Ages\ShippingGateway\CzechPost\Config\CzechPostConfig( apiToken: api-token-here secretKey: secret-key-here idContract: 123456789 customerId: L12345 postCode: '53307' locationNumber: 1 certificatePath: %wwwDir%/cert/postsignum-bundle.pem # packageLimit: 5 ) gwConfig: Ages\ShippingGateway\GebruderWeiss\Config\GebruderWeissConfig( clientId: CLIENT_ID clientSecret: CLIENT_SECRET customerId: 12345 branchCode: PRG pickupAddress: @pickupAddress ssccPrefix: '22260000' # číselný prefix pro generování SSCC kódů # product: GW_PRO_LINE # incoterm: DAP # goodsDescription: Goods # logoPath: %wwwDir%/img/logo-gw.png # čtvercové logo na etiketu (volitelné) ) - Ages\ShippingGateway\ShippingGateway
Certifikát České pošty (
postsignum-bundle.pem) je třeba umístit ručně do projektu.
Cesta se nastavuje přescertificatePath— nikdy se nekopíruje do balíčku.
Gebrüder Weiss —
clientId/clientSecretodpovídají hodnotám Consumer Key a Consumer Secret z portáludeveloper.my.gw-world.com(záložka vaší aplikace po subscribe na API).
Je třeba mít subscribe na obě API:TRANSPORT_ORDER_CREATEiTRACKNTRACE.
Gebrüder Weiss —
ssccPrefixje povinný číselný řetězec (doporučeno 6–10 číslic) sloužící jako základ pro automatické generování SSCC kódů (18 číslic dle GS1).
Podpora jej sdělí nebo si zvolte vlastní firemní prefix, např.22260000.
VolitelnýlogoPathpřijímá absolutní cestu k obrázku — ten se zobrazí v levém horním rohu štítku ve čtvercové oblasti cca 24 × 24 mm.
Usage
Unified shipment creation
Předáš ShipmentRequest, označíš dopravce a dostaneš ShipmentLabel[] — jeden štítek per balík.
use Ages\ShippingGateway\Common\Carrier; use Ages\ShippingGateway\Common\Shipment\CashOnDelivery; use Ages\ShippingGateway\Common\Shipment\Parcel; use Ages\ShippingGateway\Common\Shipment\RecipientAddress; use Ages\ShippingGateway\Common\Shipment\ShipmentRequest; use Ages\ShippingGateway\Common\Shipment\ShipmentValue; $request = new ShipmentRequest( reference: '2025-00123', recipient: RecipientAddress::fromFullName( name: 'Jan Novák', street: 'Hlavní', houseNumber: '42', city: 'Praha', zip: '10000', country: 'CZ', phone: '+420600123456', email: 'jan@example.com', ), parcels: [ new Parcel(weight: 2.5), new Parcel(weight: 1.8), ], value: new ShipmentValue(amount: 1490.0), cod: new CashOnDelivery(amount: 1490.0, variableSymbol: '2025001'), note: 'Poznámka pro přepravu', // Pro výdejní místa: // parcelShopCode: 'B69623', // parcelShopZip: '69623', // u České pošty explicitně PSČ provozovny ); /** @var \Ages\ShippingGateway\ShippingGateway $gateway */ $labels = $gateway->createShipment(Carrier::Gls, $request); foreach ($labels as $label) { echo $label->trackingNumber; // číslo zásilky file_put_contents('label.pdf', $label->labelPdf); // raw PDF bytes }
Dostupné hodnoty Carrier: Carrier::Gls, Carrier::Ppl, Carrier::CzechPost, Carrier::GebruderWeiss.
RecipientAddress
// Ze jména — rozdělí podle první mezery (Jan / Novák) RecipientAddress::fromFullName('Jan Novák', $street, $city, $zip, $country, $phone, $email); // Nebo přímo s firstName / lastName new RecipientAddress( firstName: 'Jan', lastName: 'Novák', street: 'Hlavní', city: 'Praha', zip: '10000', country: 'CZ', phone: '+420600123456', email: 'jan@example.com', company: 'Firma s.r.o.', // volitelné houseNumber: '42', // volitelné type: RecipientType::Company, // Person (výchozí) nebo Company );
Parcel — typy zásilek
use Ages\ShippingGateway\Common\Shipment\Dimensions; use Ages\ShippingGateway\Common\Shipment\ParcelType; new Parcel(weight: 2.5); // standardní balík new Parcel(weight: 15.0, type: ParcelType::PackageOversize); // neskladný / atypický new Parcel(weight: 80.0, type: ParcelType::PalletEur); // EUR paleta (GebrüderWeiss) new Parcel(weight: 60.0, type: ParcelType::PalletOneWay); // jednorázová paleta new Parcel(weight: 50.0, type: ParcelType::PalletHalf); // půl paleta new Parcel(weight: 40.0, type: ParcelType::PalletCustom); // vlastní paleta // S rozměry — hodnoty v cm; u Gebrüder Weiss se odesílají jako metry (automatická konverze ÷ 100) new Parcel(weight: 5.0, dimensions: new Dimensions(60, 40, 30));
Palety jsou podporovány pouze přes Gebrüder Weiss.
GLS a PPL paletové typy nepodporují — handler vyhodíInvalidArgumentException.
Česká pošta podporujePackageaPackageOversize(neskladná zásilka, služba 10), palety nepodporuje.
ShipmentLabel — výstup
$label->carrier; // Carrier::Gls | Carrier::Ppl | Carrier::CzechPost $label->trackingNumber; // číslo zásilky pro sledování $label->labelPdf; // raw PDF bytes — ulož nebo pošli do prohlížeče // Uložení štítku file_put_contents('/path/to/' . $label->trackingNumber . '.pdf', $label->labelPdf); // Sledování zásilky (po doručení) $tracking = $gateway->tracking($label->carrier, $label->trackingNumber);
Více balíků — GLS / PPL / Czech Post: API vrátí jeden kombinovaný PDF soubor pro všechny balíky.
KaždýShipmentLabelmá svůjtrackingNumber,labelPdfje u všech shodné (kombinovaný tisk).Více balíků — Gebrüder Weiss: každý balík dostane vlastní SSCC kód v etiketě a samostatné PDF etiket.
ShipmentLabel[]má tolik prvků, kolik je zásilek — pro tracking mají všechny stejnýtrackingNumber(reference/orderId),labelPdfje u prvního prvku a SSCC zůstává součástí etikety.
Unified tracking
$tracking = $gateway->tracking(Carrier::Gls, '1234567890'); $tracking = $gateway->tracking(Carrier::Ppl, 'KEA12345678'); $tracking = $gateway->tracking(Carrier::CzechPost, 'DR123456789CZ'); $tracking = $gateway->tracking(Carrier::GebruderWeiss, 'ORDER-2026-001'); // reference zásilky / orderId $trackingUrl = $gateway->trackingUrl(Carrier::Gls, '1234567890'); $trackingUrl = $gateway->trackingUrl(Carrier::Ppl, 'KEA12345678'); $trackingUrl = $gateway->trackingUrl(Carrier::CzechPost, 'DR123456789CZ'); $trackingUrl = $gateway->trackingUrl(Carrier::GebruderWeiss, 'ORDER-2026-001'); // GW public tracking deep-link needs pickupAddress.company in config. // PPL public tracking URL uses ?shipmentId={trackingNumber}. if ($tracking !== null) { $tracking->getDelivered(); // bool $tracking->getDeliveredDate(); // ?DateTimeImmutable $tracking->getWeight(); // float (kg) $tracking->getParcelNumber(); // string $tracking->getDeliveryCountryCode(); // string (ISO) foreach ($tracking->getParcelStatuses() as $status) { $status->getStatusDate(); // ?DateTimeImmutable $status->getStatusDescription(); // string $status->getCustomInfo(); // ?string $status->getDelivered(); // bool $status->getDamaged(); // bool } }
trackingUrl()vrací veřejnou stránku sledování dopravce.
U GLS a České pošty je URL předvyplněná číslem zásilky, u PPL a Gebrüder Weiss vede na jejich oficiální tracking stránku.
Gebrüder Weiss: tracking probíhá přes reference/orderId vrácené v
$label->trackingNumber.
API vrací aktuální stav zásilky;nullznamená, že zásilka ještě není v systému GBW (zpoždění po odeslání objednávky).
Extending in your project
Balíček obsahuje API vrstvu (HTTP komunikace, entity, config) a unified shipment handlery.
Aplikační logika — mapování objednávky/faktury na zásilku, ukládání do DB — patří do projektu.
GLS — příklad rozšíření
namespace App\Api\Gls; use Ages\ShippingGateway\Gls\GlsApi; use Ages\ShippingGateway\Gls\Entity\ParcelEntity; use Ages\ShippingGateway\Gls\Entity\ServiceEntity; class Gls extends GlsApi { const string Carrier = 'GLS'; const string TrackUrl = 'https://gls-group.eu/CZ/cs/sledovani-zasilek/?match='; public function createConsignmentFromInvoice(Invoice $invoice): ?Consignment { $services = ServiceEntity::of(); if ($invoice->cashOnDelivery) { $services->addServiceCOD($invoice->priceTax, $invoice->variableSymbol, $invoice->currencyIso); } $parcel = ParcelEntity::of( strval($this->config->clientNumber), $invoice->code, $invoice->packageQty, $this->getPickupAddress(), // z configu $deliveryAddress, $services, ); $data = $this->printLabels($parcel); // $data->PrintLabelsInfoList[0]->ParcelNumber ← tracking number // implode(array_map('chr', $data->Labels)) ← PDF bytes } }
PPL — příklad rozšíření
namespace App\Api\Ppl; use Ages\ShippingGateway\Ppl\PplApi; class Ppl extends PplApi { public function createConsignmentFromInvoice(Invoice $invoice): ?Consignment { $parcel = ParcelEntity::of( $invoice->code, $invoice->packageQty, $this->getPickupAddress(), $deliveryAddress, SpecificDeliveryEntity::of($psdCode), $cod, ); $batchId = $this->createBatch($parcel); $status = $this->getStatus($batchId); // poll dokud není Complete // $status->items[0]->shipmentNumber ← tracking number // $status->completeLabel->labelUrls[0] ← URL štítku → getLabel($url) } }
Czech Post — příklad rozšíření
namespace App\Api\CzechPost; use Ages\ShippingGateway\CzechPost\CzechPostApi; class CzechPost extends CzechPostApi { public function createConsignmentFromInvoice(Invoice $invoice): ?Consignment { $header = $this->prepareParcelServiceHeader(); // z configu $res = $this->parcelService($header, $consignmentEntity->toArray(), $multipart); // $res['responseHeader']['resultHeader']['responseCode'] === 1 ← úspěch // $res['responseHeader']['resultParcelData'][n]['parcelCode'] ← tracking number // $res['responseHeader']['responsePrintParams']['file'] ← base64 PDF } }
Architecture overview
src/
├── ShippingGateway.php ← facade: tracking() + createShipment()
├── Common/
│ ├── Carrier.php ← enum: Gls | Ppl | CzechPost | GebruderWeiss
│ ├── CarrierInterface.php
│ ├── ShipmentHandlerInterface.php ← createShipment(ShipmentRequest): ShipmentLabel[]
│ ├── ParcelTrackingInterface.php
│ ├── ParcelStatusInterface.php
│ ├── PickupAddress.php
│ ├── ShippingException.php
│ └── Shipment/
│ ├── ShipmentRequest.php ← vstupní DTO
│ ├── ShipmentLabel.php ← výstupní DTO (carrier, trackingNumber, labelPdf)
│ ├── RecipientAddress.php ← fromFullName() factory
│ ├── Parcel.php ← weight, type, dimensions
│ ├── Dimensions.php
│ ├── ShipmentValue.php
│ ├── CashOnDelivery.php
│ ├── ParcelType.php ← Package | PackageOversize | PalletEur | ...
│ └── RecipientType.php ← Person | Company
├── Gls/
│ ├── Config/GlsConfig.php
│ ├── GlsApi.php
│ ├── Handler/GlsShipmentHandler.php
│ └── Entity/ Values/
├── Ppl/
│ ├── Config/PplConfig.php
│ ├── PplApi.php
│ ├── Handler/PplShipmentHandler.php
│ └── Entity/ Values/
├── CzechPost/
│ ├── Config/CzechPostConfig.php
│ ├── CzechPostApi.php
│ ├── CzechPostException.php
│ ├── Handler/CzechPostShipmentHandler.php
│ └── Entity/ Values/
└── GebruderWeiss/
├── Config/GebruderWeissConfig.php
├── GebruderWeissApi.php
├── Handler/GebruderWeissShipmentHandler.php
├── Label/GebruderWeissLabelGenerator.php ← mPDF etiketa 100×150 mm
└── Tracking/
├── GbwParcelTracking.php
└── GbwParcelStatus.php
Co je v balíčku: HTTP komunikace, entity, config, unified tracking, unified shipment creation.
Co patří do projektu: mapování Invoice → ShipmentRequest, ukládání zásilek do DB, Storage.
License
Private package — Ages s.r.o.
ages/shipping-gateway 适用场景与选型建议
ages/shipping-gateway 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 60 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 27 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 ages/shipping-gateway 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 ages/shipping-gateway 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 60
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 37
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: Unknown
- 更新时间: 2026-04-27