wishbox / cdek-library
PHP library for working with CDEK-related functionality.
v0.1.3
2026-04-18 07:15 UTC
Requires
- php: ^8.5
- ext-ctype: *
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
Requires (Dev)
- guzzlehttp/guzzle: ^7.9
- phpunit/phpunit: ^11.5
README
PHP 8.4 client for CDEK API with a modular structure around a shared CdekClient, PSR-18 HTTP support, request DTOs, and basic local validation for order creation.
Requirements
- PHP 8.4+
- PSR-18 HTTP client
- PSR-17 request and stream factories
Installation
composer require wishbox/cdek-library psr/http-client psr/http-factory psr/http-message
This package expects a PSR-18 HTTP client and PSR-17 factories from your application.
Usage
<?php require __DIR__ . '/vendor/autoload.php'; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Psr7\HttpFactory; use WishboxCdek\CdekClient; use WishboxCdek\Enum\OrderType; use WishboxCdek\Request\Calculator\CalculateTariffRequest; use WishboxCdek\Request\DeliveryPoint\GetDeliveryPointsRequest; use WishboxCdek\Request\Intake\CreateIntakeRequest; use WishboxCdek\Request\Location\GetCitiesRequest; use WishboxCdek\Request\Location\GetRegionsRequest; use WishboxCdek\Request\Order\CreateOrderRequest; use WishboxCdek\Request\Order\OrderContact; use WishboxCdek\Request\Order\OrderItemPayment; use WishboxCdek\Request\Order\OrderLocation; use WishboxCdek\Request\Order\OrderPackage; use WishboxCdek\Request\Order\OrderPackageItem; use WishboxCdek\Request\Order\OrderPhone; use WishboxCdek\Request\Print\CreateOrdersPrintRequest; $httpClient = new GuzzleClient(); $httpFactory = new HttpFactory(); $client = new CdekClient( $httpClient, $httpFactory, $httpFactory, [ 'base_url' => CdekClient::SANDBOX_BASE_URL, 'account' => 'your-account', 'password' => 'your-password', ] ); $regions = $client->locations()->getRegions(new GetRegionsRequest( countryCodes: 'RU', size: 100, )); $cities = $client->locations()->getCities(new GetCitiesRequest( countryCodes: 'RU', city: 'Moscow', )); $deliveryPoints = $client->deliveryPoints()->getList(new GetDeliveryPointsRequest( cityCode: 44, )); try { $order = $client->orders()->create( CreateOrderRequest::make( tariffCode: 139, sender: new OrderContact( name: 'Wishbox Sender', phones: [ new OrderPhone(number: '+79990000001'), ], contragentType: 'LEGAL_ENTITY', ), recipient: new OrderContact( name: 'John Doe', phones: [ new OrderPhone(number: '+79990000002'), ], email: 'john@example.com', ), packages: [ new OrderPackage( number: 'PKG-1', weight: 1000, length: 10, width: 10, height: 10, items: [ new OrderPackageItem( name: 'Test item', wareKey: 'SKU-1', payment: new OrderItemPayment(value: 1000), cost: 1000, weight: 1000, amount: 1, ), ], ), ], ) ->withType(OrderType::INTERNET_SHOP) ->withFromLocation(new OrderLocation(code: 44, address: 'Sender street 1')) ->withToLocation(new OrderLocation(code: 137, address: 'Recipient street 10')) ->withNumber('ORDER-1') ->withComment('Created from Wishbox SDK') ); $orderDetails = $client->orders()->getByUuid($order->entity?->uuid ?? ''); $intake = $client->intakes()->create(new CreateIntakeRequest([ 'order_uuid' => $order->entity?->uuid, 'intake_date' => '2026-03-30', 'intake_time_from' => '10:00', 'intake_time_to' => '14:00', ])); $print = $client->prints()->createOrders(new CreateOrdersPrintRequest([ 'orders' => [ ['order_uuid' => $order->entity?->uuid], ], 'copy_count' => 2, ])); echo $order->entity?->uuid; echo $orderDetails->entity?->uuid; echo $intake->entity?->uuid; echo $print->requests[0]->state; } catch (\WishboxCdek\Exception\OrderValidationException $e) { foreach ($e->getErrors() as $error) { echo $error . PHP_EOL; } } catch (\WishboxCdek\Exception\ApiResponseException $e) { foreach ($e->getErrors() as $error) { echo $error->code . ': ' . $error->message . PHP_EOL; } }
Testing
composer test
composer test:integration
Current unit tests cover:
- request DTO serialization
- auth token request formatting
- authenticated request building
- automatic token fetch before API calls
- typed async responses for
orders(),intakes(), andprints() - typed order details response for
orders()->getByUuid() - local validation for
orders()->create()
Current integration tests cover:
auth()->getOAuthToken()wrong password handling against CDEK sandboxlocations()->getRegions()against CDEK sandboxlocations()->getPostalcodes()against CDEK sandboxorders()->create()against CDEK sandboxorders()->getByUuid()against CDEK sandbox
To run integration tests against sandbox, set:
CDEK_BASE_URL=https://api.edu.cdek.ru CDEK_ACCOUNT=your-account CDEK_PASSWORD=your-password
If credentials are missing, integration tests are skipped automatically.
Structure
WishboxCdek\CdekClient- config, auth, shared HTTP requests, PSR-18 integrationWishboxCdek\Api\AuthApi- OAuth tokenWishboxCdek\Api\LocationApi- cities, regions, postal codes, coordinatesWishboxCdek\Api\DeliveryPointApi- offices and pickup pointsWishboxCdek\Api\CalculatorApi- tariffs and cost calculationWishboxCdek\Api\OrderApi- create, update, get, delete ordersWishboxCdek\Api\IntakeApi- intake dates and courier intake requestsWishboxCdek\Api\PrintApi- order receipts, barcode print jobs, and barcode PDF downloadsWishboxCdek\Api\WebhookApi- webhook subscriptionsWishboxCdek\Request\...- request DTOs for all public API methodsWishboxCdek\Response\...- response DTOs for typed API resultsWishboxCdek\Validation\...- local validators for request prechecksWishboxCdek\Enum\...- enums for documented CDEK constants
Notes
- Production base URL:
https://api.cdek.ru - Sandbox base URL:
https://api.edu.cdek.ru - If
access_tokenis not passed explicitly, the client will request it automatically usingaccountandpassword - Laravel facade
Httpis not PSR-18 by itself - Joomla HTTP package can be used as a PSR-18 client
CreateOrderRequestuses immutable fluent builder-style API:make(...)+with...()OrderType::INTERNET_SHOPandOrderType::DELIVERYmap to the documented order typesИМandДоставкаHttpExceptionhandles transport and HTTP-level errors,ApiResponseExceptionhandles async business errors from successful CDEK responses with invalidrequests[*]OrderValidationExceptionis thrown before the HTTP call when local order validation fails- Async methods like
orders()->create(),intakes()->create(),prints()->createOrders(), andprints()->createBarcodes()return typed async response objects withentityandrequests orders()->getByUuid()returns a typedOrderDetailsobject withentityandextraprints()->downloadBarcodesPdf()returns the raw PDF body for/v2/print/barcodes/{uuid}.pdf- Built-in local validation currently knows destination rules for tariffs
136,137,138, and139