bitbag / dpd-pl-api-php
PHP DPD API 客户端
Requires
- php-http/client-common: ^2.1
- php-http/discovery: ^1.7
- php-http/httplug: ^2.1
- php-http/message: ^1.8
- php-http/message-factory: ^1.0
- phpro/soap-client: ^1.0
- psr/http-client: ^1.0
- psr/http-client-implementation: ^1.0
- psr/http-message: ^1.0
- sabre/xml: ^2.1
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-14 12:22:35 UTC
README
PHP 语言编写的客户端,用于与 DPD 快递公司的以下 Web 服务进行通信
PackageService
(登记包裹、打印标签和交接协议,以及预约快递员取件)AppService
(处理第三方收件订单)InfoService
(跟踪包裹)
安装
最简单的方法是使用 Composer 进行安装(https://getcomposer.org.cn)。
通过 composer.json
文件
{ "require": { "t3ko/dpd-pl-api-php": "^0" } }
或者通过命令行
composer require t3ko/dpd-pl-api-php
该库使用 httplug
作为 HTTP 客户端的抽象,不包含任何默认实现。在包含该项目的项目中,需要提供符合 PSR-18 的 HTTP 客户端。更多信息请参阅:http://docs.php-http.org/en/latest/httplug/users.html
如果您的项目中已经包含了一个由 httplug
支持的 HTTP 客户端(http://docs.php-http.org/en/latest/clients.html),则只需与库一起安装相应的适配器即可。
例如,对于 curl
composer require php-http/curl-client:^1 t3ko/dpd-pl-api-php
如果您的代码中还没有使用任何兼容的 HTTP 客户端,则需要与适配器一起安装它。
例如,guzzle
composer require php-http/guzzle6-adapter:^1 guzzlehttp/guzzle:~6.0 t3ko/dpd-pl-api-php
使用方法
使用方法
要使用 DPD API 正确发送包裹,需要遵循以下步骤(以下步骤将在后续部分进行详细说明)
-
注册包裹(使用
generatePackageNumbers()
方法)向此方法发送构成包裹的物理包裹数据、寄件人和收件人数据以及额外订购的服务数据(例如,取件、送货保证等)。作为响应,我们将收到每个包裹分配的运单号。
-
为包裹生成标签(使用
generateLabels()
方法)将上一步骤中获得的运单号发送到此方法,将获得用于粘贴在包裹上的标签的 PDF 文件。
-
为包裹生成交接协议(使用
generateProtocol()
方法)与上一步骤类似,向此方法传递要一起发送的包裹的运单号。作为响应,API 返回一个包含准备好的交接协议的 PDF 文件。
-
检查快递员在指定投递日的可用时间(使用
getCourierAvailability()
方法)此方法在发送发件地的邮政编码后,将返回快递员在接下来几天内接收包裹的时间段。
-
预约快递员取件(待定)
向此方法传递从上述方法返回的选择的日期和时间以及取件地点,将获得取件确认。快递员将取走带有步骤 2 中生成的标签的包裹,并确认步骤 3 中生成的交接协议。
除了上述基本的包裹处理方法外,以下库还允许
- 委托第三方收件
- 获取投递点列表(待定)
- 跟踪包裹
0. 连接 API
要开始使用 API,需要以下三个参数的认证数据
- 用户名
- 密码
- FID 号码
这些数据可以在与客户经理签订合同并声明愿意使用 API 后从客户经理处获得。这些数据用于在本文档开头提到的三个 Web 服务中执行认证。
通过构建以下类 T3ko\Dpd\Api
对象来使用 API
require_once __DIR__.'/vendor/autoload.php'; $login = 'testlogin'; $password = 'testpassword'; $fid = 12345; $api = new \T3ko\Dpd\Api($login, $password, $fid);
默认情况下,库连接到生产端点,但大多数API服务DPD还提供了测试端点,允许安全地测试自己的代码与Web服务的集成。要启用它们的使用,需要在Api
对象上调用setSandboxMode
方法。
$api->setSandboxMode(true);
从此时起,所有请求都将被导向测试端点。对于不提供测试版本的服务,尝试在sandbox
模式下使用将引发SandboxNotAvailableException
异常。
测试API需要单独的登录数据(这些数据由DPD IT部门在客户提出API集成意向后,随文档包一同提供)。尝试使用生产数据在测试端点上登录将导致认证错误。
要关闭测试模式,当然可以使用
$api->setSandboxMode(false);
1. 注册包裹
GeneratePackageNumbersRequest
通过方法generatePackageNumbers
分配运输单号,该方法接受一个GeneratePackageNumbersRequest
类型的对象作为参数
use \T3ko\Dpd\Request\GeneratePackageNumbersRequest; /** @var GeneratePackageNumbersRequest $request */ $response = $api->generatePackageNumbers($request);
请求对象基于传递给生成方法fromPackage
或fromPackages
(对于由多个包裹组成的复合请求)的包裹/包裹数据构建
$singlePackageRequest = GeneratePackageNumbersRequest::fromPackage($package); $multiplePackagesRequest = GeneratePackageNumbersRequest::fromPackages([$package1, $package2]);
Package
构建上述请求的加密方式是Package
类型的对象,包含包裹的配置。构建它至少需要三个数据 - 发件人对象Sender
,收件人对象Receiver
以及一个或多个表示组成包裹的物理包裹的Parcel
类的实例。以下是一个创建Package
对象的示例代码
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]);
Sender
和Receiver
对象使用地址数据和必填的电话号码初始化。此外,还向Sender
对象传递用于登录的FID号码(此API假定包裹的发送者是API客户端)
$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) );
Parcel
对象是按照以下方式构建的
$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
generatePackageNumbers
方法返回一个GeneratePackageNumbersResponse
类型的对象
/** @var GeneratePackageNumbersResponse $response */ $response = $api->generatePackageNumbers($request);
我们有权访问注册包裹列表 - 一个包含RegisteredPackage
类型对象的数组
/** @var RegisteredPackage[] $packages */ $packages = $response->getPackages()
在每一份包裹中 - 包含已注册包裹和分配的运输单号的列表
list($package) = $packages; /** @var RegisteredParcel[] $parcels */ $parcels = $package->getParcels(); list($parcel) = $parcels; $parcel->getWaybill(); //numer listu przewozowego, np. 0000092494467Q
2. 获取标签
使用generateLabels
方法打印标签,该方法接收一个GenerateLabelsRequest
类型的对象
use \T3ko\Dpd\Request\GenerateLabelsRequest; /** @var GenerateLabelsRequest $request */ $response = $api->generateLabels($request);
GenerateLabelsRequest
可以通过三种方式构建请求对象
- 使用步骤1中生成的运输单号
use \T3ko\Dpd\Request\GenerateLabelsRequest; $request = GenerateLabelsRequest::fromWaybills(['0000092494467Q']);
- 使用步骤1中由DPD分配的包裹标识符
use \T3ko\Dpd\Request\GenerateLabelsRequest; $parcelId = $parcel->getId(); $request = GenerateLabelsRequest::fromParcelIds([$parcelId]);
- 或使用包裹的
reference
字段
use \T3ko\Dpd\Request\GenerateLabelsRequest; $parcelRef = $parcel->getReference(); $request = GenerateLabelsRequest::fromReferences([$parcelRef]);
(当然,这里的reference
是我们希望与包裹关联的任何字符串,例如订单编号等。因此,如果在步骤1注册包裹时没有传递任何值,则无法使用它)
GenerateLabelsResponse
在构建请求并发送它到API后,使用generateLabels
方法我们将得到一个GenerateLabelsResponse
类型的对象作为响应
/** @var GenerateLabelsResponse $response */ $response = $api->generateLabels($request);
在内部,我们有访问包含PDF标签的二进制文件数据的fileContent
字段。以下示例显示了将标签写入etykieta.pdf
文件的记录
$response = $api->generateLabels($request); $fp = fopen('etykieta.pdf', 'wb'); fwrite($fp, $response->getFileContent()); fclose($fp)
3. 生成交接协议
为了生成将包裹交付给快递员的协议,我们使用generateProtocol
方法
use \T3ko\Dpd\Request\GenerateProtocolRequest; /** @var GenerateProtocolRequest $request */ $response = $api->generateProtocol($request);
GenerateProtocolRequest
创建请求对象的方式与生成标签的情况非常相似。在这里,我们也可以以三种方式创建对象,使用运输单号、包裹标识符或包裹参考
use \T3ko\Dpd\Request\GenerateProtocolRequest; $request = GenerateProtocolRequest::fromWaybils([...]); $request = GenerateProtocolRequest::fromParcelIds([...]); $request = GenerateProtocolRequest::fromReferences([...]);
GenerateProtocolResponse
向API发送这样构建的请求将给我们一个GenerateProtocolResponse
类型的对象作为响应,其中再次提供包含PDF文件内容的fileContent
字段
/** @var GenerateLabelsResponse $response */ $response = $api->generateProtocol($request); $response->getFileContent()); //treść pliku PDF z protokołem przekazania
4. 检查快递员的可用时间
DOC TODO
5. 预约快递员取件
DOC TODO
委托第三方收件
使用 AppService
API 可以发出请求,由第三方接收包裹。为此,需要创建一个或多个描述包裹配置的 Package
类型对象,就像在常规发送时一样,记住,在 $sender
字段中应包含实际向快递员发出包裹的主体信息,而不是委托接收者!
此外,接收委托的端点仅接受已声明由第三方支付(即委托接收方)的 Package
对象
$package->setPayerType(\T3ko\Dpd\Objects\Enum\PayerType::THIRD_PARTY());
以及支付方的 FID 号码(实际上是我们用于连接 API 的相同号码)
$package->setThirdPartyFid(123);
CollectionOrderRequest
这样构建的 Package
对象用作生成 CollectionOrderRequest
对象的参数
use \T3ko\Dpd\Request\CollectionOrderRequest; $singlePackageRequest = CollectionOrderRequest::fromPackage($package); $multiplePackagesRequest = CollectionOrderRequest::fromPackages([$package1, $package2]);
通过它我们可以调用 API 的接收委托方法 - collectionOrder()
use \T3ko\Dpd\Request\CollectionOrderRequest; /** @var CollectionOrderRequest $request */ $response = $api->collectionOrder($request);
CollectionOrderResponse
响应中我们获得一个类型为 CollectionOrdersResponse
的对象
/** @var CollectionOrderResponse $response */ $response = $api->collectionOrder($request);
其中包含已委托的包裹信息列表,这些信息以 CollectionOrderedPackage
类型对象的数组形式呈现
/** @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
而在从 $package->getParcels()
获取的 CollectionOrderedParcel
对象中,记录了由 DPD 分配的包裹标识符以及该包裹的运单号码
list($parcel) = $package->getParcels(); $parcel->getParcelId(); //identyfikator paczki nadany przez DPD $parcel->getWaybill(); //numer listu przewozowego dla tej paczki
至此,第三方接收包裹的委托操作结束。无需打印标签并交给发货人或委托快递员,这一切将由 DPD 自动完成。
跟踪包裹
要获取有关特定包裹的信息,可以使用 API 的 InfoService
通过 getParcelTracking
方法
use \T3ko\Dpd\Request\GetParcelTrackingRequest; /** @var GetParcelTrackingRequest $request */ $response = $api->getParcelTracking($request);
GetParcelTrackingRequest
向该方法传递的请求对象是通过传递运单号码创建的
use \T3ko\Dpd\Request\GetParcelTrackingRequest; $request = GetParcelTrackingRequest::fromWaybill(...);
可选地,我们可以指定是要查看包裹的完整历史记录还是仅查看与包裹相关的最后一条记录
use \T3ko\Dpd\Request\GetParcelTrackingRequest; use T3ko\Dpd\Objects\Enum\TrackingEventsCount; $request = GetParcelTrackingRequest::fromWaybill('01234567890U', TrackingEventsCount::ALL()); $request = GetParcelTrackingRequest::fromWaybill('01234567890U', TrackingEventsCount::ONLY_LAST());
默认值是 TrackingEventsCount::ALL()
,即获取包裹历史记录中的所有事件。
GetParcelTrackingResponse
响应中我们获得一个类型为 GetParcelTrackingResponse
的对象
use \T3ko\Dpd\Response\GetParcelTrackingResponse; /** @var GetParcelTrackingResponse $response */ $response = $api->getParcelTracking($request);
通过 getEvents()
方法,该方法通过方法将事件列表返回给 ParcelEvent
类型对象数组,这些对象表示包裹历史中的单个事件
/** @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"; }
以下是一个示例调用效果
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