dpd-pl-api-php
Klient API w języku PHP do komunikacji z następującymi web-serwisami firmy kurierskiej DPD:
- PackageService
(rejestrowanie przesyłek, drukowanie etykiet i protokołów przekazania przesyłek kurierowi, zamawianie kuriera po odbiór przesyłki)
- AppService
(obsługa zleceń odbioru przesyłek od osób trzecich)
- InfoService
(tracking przesyłek), (*1)
Instalacja
Najprostszy sposób to instalacja za pomocą Composer-a (http://getcomposer.org)., (*2)
Poprzez plik composer.json
:, (*3)
{
"require": {
"t3ko/dpd-pl-api-php": "^0"
}
}
lub z linii poleceń:, (*4)
composer require t3ko/dpd-pl-api-php
Biblioteka korzysta z httplug
jako abstrakcji klienta HTTP i nie zawiera żadnej domyślnej implementacji.
Po stronie projektu, w którym jest umieszczona - leży obowiązek dostarczenia klienta HTTP zgodnego z PSR-18.
Więcej informacji tutaj: http://docs.php-http.org/en/latest/httplug/users.html, (*5)
Jeśli Twój projekt zawiera już jakiegoś klienta HTTP wspieranego przez httplug
(http://docs.php-http.org/en/latest/clients.html) wystarczy razem z biblioteką doinstalować odpowiedni adapter., (*6)
Np. dla curl
:, (*7)
composer require php-http/curl-client:^1 t3ko/dpd-pl-api-php
Jeśli natomiast nie używasz jeszcze żadnego kompatybilnego klienta HTTP w swoim kodzie, będzie konieczne zainstalowanie go razem z adapterem., (*8)
Np. guzzle
:, (*9)
composer require php-http/guzzle6-adapter:^1 guzzlehttp/guzzle:~6.0 t3ko/dpd-pl-api-php
Użycie
Sposób korzystania
Aby poprawnie wysłać przesyłkę korzystając z API DPD należy przejść następujące, omówione szerzej w dalszej części, kroki:
1. Zarejestrować przesyłkę/przesyłki (metoda generatePackageNumbers()
), (*10)
Do tej metody wysyłamy fizyczne dane paczek składajacych się na przesyłkę, dane nadawcy i odbiorcy, dodatkowych zamówionych usług (np. pobranie, gwarancja dostarczenia, itd.).
W odpowiedzi otrzymujemy numery listów przewozowych przypisanych do każdej paczki., (*11)
-
Wygenerować etykiety dla paczek (metoda generateLabels()
), (*12)
Uzyskane w poprzednim kroku numery listów przewozowych przesłane do tej metody pozwolą w odpowiedzi uzyskać w odpowiedzi plik PDF z etykietami do umieszczenia na paczkach., (*13)
-
Wygenerować protokół przekazania paczek kurierowi (metoda generateProtocol()
), (*14)
Tak jak wyżej, do metody przekazujemy numery listów przewozowych paczek, które mają być wysłane wspólnie. W odpowiedzi API zwraca plik PDF z przygotowanym protokołem przekazania przesyłek kurierowi., (*15)
-
Sprawdzić dostępność godzinową kuriera w pożądanym dniu nadania (metoda getCourierAvailability()
), (*16)
Ta metoda po przesłaniu kodu pocztowego miejsca z którego nadane zostaną przesyłki, zwróci przedziały czasowe dostępności kuriera odbierającego przesyłki na najbliższe kilka dni., (*17)
-
Zamówić odbiór przesyłek przez kuriera (TODO), (*18)
Do tej metody przekazujemy dzień i przedział godzinowy wybrany z tych które zwróciła metoda wyżej, a także miejsce odbioru. W odpowiedzi uzyskujemy potwiedzenie przyjęcia zlecenia odbioru.
Kurier odbiera paczki oznaczone etykietami wygenerowanymi w kroku 2., pokwitowując protokół przekazania wygenerowany w kroku 3., (*19)
Poza powyższymi podstawowymi metodami obsługi paczek, poniższa biblioteka umożliwia także:, (*20)
- Zlecanie odbioru od osoby trzeciej
- Pobieranie listy puntów doręczenia (TODO)
- Śledzenie przesyłek
0. Połączenie z API
Aby rozpocząć korzystanie z API wymagane są dane autentykacyjne składające się z trzech parametrów:
- nazwa użytkownika
- hasło
- numer FID, (*21)
Dane te uzyskuje się od swojego opiekuna klienta po podpisaniu umowy i zadeklarowaniu chęci korzystania z API.
Te same dane służą do autoryzacji we wszystkich trzech webserwisach wymienionych na początku tego dokumentu., (*22)
Korzystanie z API odbywa się poprzez obiekt klasy T3ko\Dpd\Api
budowany jak poniżej:, (*23)
require_once __DIR__.'/vendor/autoload.php';
$login = 'testlogin';
$password = 'testpassword';
$fid = 12345;
$api = new \T3ko\Dpd\Api($login, $password, $fid);
Domyślnie biblioteka łączy się do endpointów produkcyjnych, ale dla większości usług API DPD udostępnia także endpointy testowe pozwalające na bezpieczne przetestowanie integracji własnego kodu z webserwisem. Aby włączyć ich użycie należy wywołać na obiekcie Api
metodę setSandboxMode
:, (*24)
$api->setSandboxMode(true);
Od tego momentu wszystkie żądania będą kierowane do endpointów testowych. Dla usług które nie udostępniają wersji testowej próba użycia w trybie sandbox
zakończy się wyjątkiem SandboxNotAvailableException
., (*25)
Testowe API wymaga osobnych danych logowania (dane te są przekazywane przez IT DPD razem z pakietem dokumentacji, po zgłoszeniu przez klienta chęci integracji API). Próba zalogowania się produkcyjnymi danymi dostępowymi na endpoint testowy spowoduje błąd autentykacji., (*26)
Aby wyłączyć tryb testowy można oczywiście użyć:, (*27)
$api->setSandboxMode(false);
1. Rejestracja przesyłki
GeneratePackageNumbersRequest
Nadawanie paczkom numerów listów przewozowych odbywa się za pomocą metody generatePackageNumbers
przyjmującej jako parametr obiekt typu GeneratePackageNumbersRequest
:, (*28)
use \T3ko\Dpd\Request\GeneratePackageNumbersRequest;
/** @var GeneratePackageNumbersRequest $request */
$response = $api->generatePackageNumbers($request);
Obiekt żądania jest budowany na podstawie danych przesyłki/przesyłek przekazywanych do metody fabrykujacej fromPackage
lub fromPackages
(dla żądania złożonego z wielu przesyłek jednocześnie):, (*29)
$singlePackageRequest = GeneratePackageNumbersRequest::fromPackage($package);
$multiplePackagesRequest = GeneratePackageNumbersRequest::fromPackages([$package1, $package2]);
Package
Encja używana do budowania powyższego requestu to obiekt typu Package
, zawierający konfigurację przesyłki. Do jego budowy potrzeba co najmniej trzech danych - obiektu nadawcy Sender
, obiektu odbiorcy Receiver
i jednej lub więcej instancji klasy Parcel
wyrażających fizyczne paczki, które składają sie na przesyłkę. Przykładkowy kod tworzący obiekt Package
może wyglądać jak niżej:, (*30)
use T3ko\Dpd\Objects\Sender;
use T3ko\Dpd\Objects\Receiver;
use T3ko\Dpd\Objects\Parcel;
use T3ko\Dpd\Objects\Package;
$sender = new Sender(12345, 501100100, 'Jan Kowalski', 'Puławska 1', '02566', 'Warszawa', 'PL');
$receiver = new Receiver(605600600, 'Piotr Nowak', 'Kwiatowa 2', '60814', 'Poznań', 'PL');
$parcel = new Parcel(30, 30, 15, 1.5);
$package = new Package($sender, $receiver, [$parcel]);
Obiekty Sender
i Receiver
inicjalizuje się podobobnie, używając danych adresowych i obowiązkowo numeru telefonu. Poza tym do obiektu Sender
przekazywany jest także numer FID używany do zalogownia (to API zakłada, że nadawcą paczki jest klient API):, (*31)
$sender = new Sender(
$fid, //numer FID
$phone, //telefon
$name, //imię i nazwisko
$address, //adres
$postalCode, //kod pocztowy
$city, //miasto
$countryCode, //kod kraju
$company, //nazwa firmy (opcjonalnie)
$email //email (opcjonalnie)
);
$receiver = new Receiver(
$phone, //telefon
$name, //imię i nazwisko
$address, //adres
$postalCode, //kod pocztowy
$city, //miasto
$countryCode, //kod kraju
$company, //nazwa firmy (opcjonalnie)
$email //email (opcjonalnie)
);
Obiekt Parcel
jest natomiast budowany następująco:, (*32)
$parcel = new Parcel(
$sizeX, //szerokość w cm
$sizeY, //wysokość w cm
$sizeZ, //głębokość w cm
$weight, //masa w kg
$reference, //unikalna referencja paczki
$contents, //opis zawartości
$customerNotes //notatka dla kuriera
);
GeneratePackageNumbersResponse
Metoda generatePackageNumbers
zwraca w odpowiedzi obiekt typu GeneratePackageNumbersResponse
:, (*33)
/** @var GeneratePackageNumbersResponse $response */
$response = $api->generatePackageNumbers($request);
Wewnątrz mamy dostęp do listy zarejestrowanych przesyłek - tablicy obiektów typu RegisteredPackage
:, (*34)
/** @var RegisteredPackage[] $packages */
$packages = $response->getPackages()
A w każdej z przesyłek - listy zarejestrowanych paczek, z nadanymi numerami listów przewozowych:, (*35)
list($package) = $packages;
/** @var RegisteredParcel[] $parcels */
$parcels = $package->getParcels();
list($parcel) = $parcels;
$parcel->getWaybill(); //numer listu przewozowego, np. 0000092494467Q
2. Pobranie etykiet
"Wydruk" etykiet odbywa się przy użyciu metody generateLabels
do której przekazujemy obiekt typu GenerateLabelsRequest
:, (*36)
use \T3ko\Dpd\Request\GenerateLabelsRequest;
/** @var GenerateLabelsRequest $request */
$response = $api->generateLabels($request);
GenerateLabelsRequest
Obiekt żądania można skonstruować na trzy sposoby:, (*37)
- przy użyciu numerów listów przewozowych wygenerowanych w kroku 1.:
use \T3ko\Dpd\Request\GenerateLabelsRequest;
$request = GenerateLabelsRequest::fromWaybills(['0000092494467Q']);
- przy użyciu numerów identyfikatorów paczek nadanych przez DPD w kroku 1.:
use \T3ko\Dpd\Request\GenerateLabelsRequest;
$parcelId = $parcel->getId();
$request = GenerateLabelsRequest::fromParcelIds([$parcelId]);
- lub, korzystając z pola
reference
paczek
use \T3ko\Dpd\Request\GenerateLabelsRequest;
$parcelRef = $parcel->getReference();
$request = GenerateLabelsRequest::fromReferences([$parcelRef]);
(oczywiście tutaj trzeba pamiętać że pole reference
to dowolny string który chcemy powiązać z paczką -
np. numer zamówienia do wysyłki itp. - wobec czego jeśli nie przekażemy żadnej wartości tego pola w kroku 1. gdy rejestrujemy
paczki - nie będzie można z niego skorzystać), (*38)
GenerateLabelsResponse
Po skonstruowaniu żadania i wysłaniu go do API metodą generateLabels
uzyskamy w odpowiedzi obiekt typu
GenerateLabelsResponse
:, (*39)
/** @var GenerateLabelsResponse $response */
$response = $api->generateLabels($request);
Wewnątrz mamy dostęp do pola fileContent
zawierającego dane binarne pliku PDF z etykietą/etykietami.
W przykładzie poniżej przedstawiono zapis etykiety do pliku etykieta.pdf
:, (*40)
$response = $api->generateLabels($request);
$fp = fopen('etykieta.pdf', 'wb');
fwrite($fp, $response->getFileContent());
fclose($fp)
3. Generowanie protokołu przekazania
Aby wygenerować protokół przekazania paczek kurierowi, używamy metody generateProtocol
:, (*41)
use \T3ko\Dpd\Request\GenerateProtocolRequest;
/** @var GenerateProtocolRequest $request */
$response = $api->generateProtocol($request);
GenerateProtocolRequest
Tworzenie obiektu żądania jest bliźniaczo podobne do przypadku generowania etykiet. Tutaj też możemy stworzyć obiekt na trzy sposoby,
korzystając z numerów listów przewozowych, identyfikatorów paczek lub referencji paczek:, (*42)
use \T3ko\Dpd\Request\GenerateProtocolRequest;
$request = GenerateProtocolRequest::fromWaybills([...]);
$request = GenerateProtocolRequest::fromParcelIds([...]);
$request = GenerateProtocolRequest::fromReferences([...]);
GenerateProtocolResponse
Wysłanie tak skonstruowanego żądania do API da nam w odpowiedzi obiekt typu GenerateProtocolResponse
, w którym do
dyspozycji - znów - jest pole fileContent
zawierające treść pliku PDF:, (*43)
/** @var GenerateLabelsResponse $response */
$response = $api->generateProtocol($request);
$response->getFileContent()); //treść pliku PDF z protokołem przekazania
4. Sprawdzenie godzin dostępności kuriera
DOC TODO, (*44)
5. Zamówienie kuriera po odbiór przesyłek
DOC TODO, (*45)
Zlecanie odbioru od osoby trzeciej
Korzystając z API AppService
można wystawić żądanie odebrania przesyłki od osoby trzeciej.
W tym celu należy utworzyć obiekt (lub obiekty) typu Package
opisujące konfigurację przesyłki jak przy zwykłym nadawaniu,
pamiętając, że w polu $sender
powinny znajdować się dane podmiotu faktycznie wydającego paczkę kurierowi, a nie zlecającego odbiór!, (*46)
Poza tym, endpoint do zlecania odbioru akceptuje jedynie obiekty Package
, w których zadeklarowano płatność przez stronę trzecią
(rozumianą jako stronę zlecającą odbiór):, (*47)
$package->setPayerType(\T3ko\Dpd\Objects\Enum\PayerType::THIRD_PARTY());
oraz podano numer FID tego płatnika (czyli w praktyce ten sam, którego używamy do łączenia się z API):, (*48)
$package->setThirdPartyFid(123);
CollectionOrderRequest
Tak skonstruowany Package
służy jako parametr do generowania obiektu CollectionOrderRequest
:, (*49)
use \T3ko\Dpd\Request\CollectionOrderRequest;
$singlePackageRequest = CollectionOrderRequest::fromPackage($package);
$multiplePackagesRequest = CollectionOrderRequest::fromPackages([$package1, $package2]);
dzięki któremu możemy wywołać metodę API zlecającą odbiór - collectionOrder()
:, (*50)
use \T3ko\Dpd\Request\CollectionOrderRequest;
/** @var CollectionOrderRequest $request */
$response = $api->collectionOrder($request);
CollectionOrderResponse
W odpowiedzi uzyskujemy obiekt typu CollectionOrdersResponse
:, (*51)
/** @var CollectionOrderResponse $response */
$response = $api->collectionOrder($request);
zawierający listę informację o przesyłkach, które udało się zlecić, w postaci tablicy obiektów typu CollectionOrderedPackage
:, (*52)
/** @var CollectionOrderedPackage[] $packages */
$packages = $response->getCollectionOrderedPackages();
list($package) = $packages;
$package->getPackageId(); //identyfikator przesyłki nadany przez DPD
$package->getReference(); //ewentualna referencja klienta nadana wiążąca paczkę z obiektem Package przesłanym w requeście
$package->getParcels(); //tablica obiektów typu CollectionOrderedParcel opisujących zlecona paczki tej przeysyłki
$package->getStatusInfo(); //status tego requestu
$package->getOrderNumber(); //numer zlecenia w systemie DPD
Natomiast w obiektach CollectionOrderedParcel
pobranych z $package->getParcels()
zapisany jest identyfikator paczki
nadawany przez DPD oraz numer listu przewozowego dla tej paczki:, (*53)
list($parcel) = $package->getParcels();
$parcel->getParcelId(); //identyfikator paczki nadany przez DPD
$parcel->getWaybill(); //numer listu przewozowego dla tej paczki
Składanie zlecenia odbioru przesyłki od osoby trzeciej w tym miejscu się kończy. Nie ma potrzeby drukowania etykiet i przekazywania ich nadającemu lub zamawiania kuriera - to zadzieje się automatycznie po stronie DPD., (*54)
Śledzenie przesyłek
Aby uzyskać informacje na temat konkretnej przesyłki możemy wykorzystać API InfoService
poprzez metodę getParcelTracking
:, (*55)
use \T3ko\Dpd\Request\GetParcelTrackingRequest;
/** @var GetParcelTrackingRequest $request */
$response = $api->getParcelTracking($request);
GetParcelTrackingRequest
Obiekt żądania przekazywany do tej metody tworzymy przekazując numer listu przewozowego:, (*56)
use \T3ko\Dpd\Request\GetParcelTrackingRequest;
$request = GetParcelTrackingRequest::fromWaybill(...);
Opcjonalnie możemy wskazać czy chodzi nam o podgląd pełnej historii paczki czy tylko ostatnie zarejestrowane zdarzenie jej dotyczące:, (*57)
use \T3ko\Dpd\Request\GetParcelTrackingRequest;
use T3ko\Dpd\Objects\Enum\TrackingEventsCount;
$request = GetParcelTrackingRequest::fromWaybill('01234567890U', TrackingEventsCount::ALL());
$request = GetParcelTrackingRequest::fromWaybill('01234567890U', TrackingEventsCount::ONLY_LAST());
przy czym domyślną wartością jest TrackingEventsCount::ALL()
czyli pobieranie wszystkich zdarzeń w historii paczki., (*58)
GetParcelTrackingResponse
W odpowiedzi uzyskujemy obiekt typu GetParcelTrackingResponse
, (*59)
use \T3ko\Dpd\Response\GetParcelTrackingResponse;
/** @var GetParcelTrackingResponse $response */
$response = $api->getParcelTracking($request);
dający poprzez metodę getEvents()
do tablicy obiektów typu ParcelEvent
wyrażających pojedyncze zdarzenie w historii przesyłki:, (*60)
/** @var GetParcelTrackingResponse $response */
$response = $api->getParcelTracking($request);
foreach ($response->getEvents() as $event) {
printf("%s - %s - %s - %s - %s (%s %s) (%s) %s",
$event->getEventTime()->format(DATE_ATOM), //data zdarzenia
$event->getWaybill(), //numer listu przewozowego
$event->getPackageReference(), //dowolne dane powiązane z przesyłką podane przez wysyłającego
$event->getParcelReference(), //j.w. związane z pojedynczą paczką
$event->getCountry(), //kod kraju operacji
$event->getDepot(), //numer oddziału DPD
$event->getDepotName(), //nazwa oddziału DPD
$event->getBusinessCode(), //kod zdarzenia
$event->getDescription() //opis słowny zdarzenia
);
$eventAdditionalData = [];
if (!empty($event->getAdditionalData())) { //dodatkowe dane zdarzenia
foreach ($event->getAdditionalData() as $additionalData) {
$eventAdditionalData[] = $additionalData->getValue();
}
}
if (!empty($eventAdditionalData)) {
printf(' [%s]', implode(', ', $eventAdditionalData));
}
echo "\n";
}
Przykładowy efekt powyższego wywołania możemy zobaczyć poniżej, (*61)
2020-08-26T09:05:18+00:00 - 0123456789012A - - - PL (1349 Warszawa3) (190101) Przesyłka doręczona [Kowalski]
2020-08-26T07:02:15+00:00 - 0123456789012A - - - PL (1349 Warszawa3) (170304) Wysłano powiadomienie
2020-08-26T07:01:46+00:00 - 0123456789012A - - - PL (1305 Warszawa) (170309) Powiadomienie SMS [+48000000000, DELIVERED]
2020-08-26T06:38:21+00:00 - 0123456789012A - - - PL (1305 Warszawa) (170310) Powiadomienie mail [xxx@xxx.pl, SENT]
2020-08-26T06:19:49+00:00 - 0123456789012A - - - PL (1349 Warszawa3) (170102) Wydanie przesyłki do doręczenia [LOK9999WAC]
2020-08-26T00:44:23+00:00 - 0123456789012A - - - PL (1349 Warszawa3) (330137) Przyjęcie przesyłki w oddziale DPD [LOK0002WAC]
2020-08-25T16:16:14+00:00 - 0123456789012A - - - PL (1320 Piotrków Tryb.) (330135) Przyjęcie przesyłki w oddziale DPD [LOK0033PTR]
2020-08-25T14:46:29+00:00 - 0123456789012A - - - PL (1320 Piotrków Tryb.) (040101) Przesyłka odebrana przez Kuriera
2020-08-24T15:05:48+00:00 - 0123456789012A - - - ( ) (030103) Zarejestrowano dane przesyłki, przesyłka jeszcze nie nadana