Інтеграція служб доставки: CDEK, Boxberry, Пошта Росії, DHL
Інтернет-магазин теряє клієнтів не на сторінці товару, а на кроці вибору доставки. Занадто мало варіантів, невірні тарифи, немає калькулятора — і покупець йде. За даними досліджень, незручний вибір доставки входить у топ-3 причин кинутих корзин.
Інтеграція зі службами доставки — це не просто «вивести список ПВЗ». Це актуальні тарифи по вазі та габаритам, автоматичне створення заявок, отслідкування статусу, обробка помилок API.
Справжні складності інтеграції
У кожної служби свій API, своя ступінь зрілості документації та свій набір неочевидних обмежень.
CDEK API v2 — найбільш зрілий із російських перевозників. OAuth 2.0 авторизація (токен живе 24 години, потрібна логіка рефреша), REST JSON. Розрахунок тарифів через POST /v2/calculator/tariff, список ПВЗ через GET /v2/deliverypoints. Типова помилка: забути передати from_location та packages з реальними вазою та розмірами — у відповідь приходить error_code: 3 без пояснень. ПВЗ потрібно кешувати (список мінюється нечасто), інакше кожен запит до чекауту генерує окремий API-виклик.
Boxberry API — простіший по функціоналу, XML у ряді методів (legacy), частина API — REST. Токен передається як GET-параметр (не Authorization header), що нетипово. Список ПВЗ повертає все одразу (~2MB JSON), його обов'язково потрібно кешувати в Redis або БД з ночам оновленням.
Пошта Росії API — найскладніший із російських. SOAP + REST гібрид, вимагає договору та налаштування в ЛК. x-user-authorization + Authorization — два різні заголовки одночасно. Нормативні відправлення, EMS, 1-й клас — різні тарифні групи. Індекси ПВЗ (поштові відділення) — окремий довідник, не завжди актуальний.
DHL Express API — для міжнародної доставки. XML-based API (DHL XML Services), хоча є новіший MyDHL+ API. Вимагає зареєстрованого account number. Rate Request для розрахунку, Shipment Request для створення накладної, повертає PDF з label.
Як будуємо інтеграцію
Абстракція над провайдерами. Жоден магазин не використовує одну службу доставки вічно. Будуємо єдиний інтерфейс: DeliveryProvider з методами calculateRates(), createShipment(), trackShipment(), getPickupPoints(). Кожна служба — окрема реалізація. Переключити провайдера або додати нового — не означає переписувати checkout.
Кешування ПВЗ. Геопошук ПВЗ по координатам або місту — частий запит. Тягти з API кожен раз не можна (ліміти, затримка). Схема: ночне завдання оновлює таблицю pickup_points у PostgreSQL з PostGIS або просто з lat/lng. Пошук найближчих — ORDER BY ST_Distance() або проста формула Хаверсина якщо PostGIS надлишкова.
Віджет на фронтенді. CDEK надає офіційний JS-віджет (@cdek-it/widget) — швидко, але обмежено в кастомізації. Для нестандартних дизайнів — кастомний віджет: карта (Яндекс.Карти API або Leaflet з тайлами 2GIS), список ПВЗ з фільтрами, детальна карточка точки з режимом роботи.
Трекінг статусів. Статусы заказів приходять або через webhook (CDEK підтримує), або через періодичний polling (Boxberry, Пошта Росії). Для polling — очередь завдань (Laravel Queue, Bull для Node.js), перевірка раз в 4–6 годин, нотифікація покупцю при зміні статусу через email або SMS.
Кейс: мультиперевозчик для WooCommerce. Магазин спортивного харчування: CDEK + Boxberry + самовивіз із 3 магазинів. Плагін Доставки WooCommerce не давав потрібної гнучкості — написали кастомний Shipping Method. calculate_shipping() робить паралельні запити до обох API через GuzzleHttp\Pool, агрегує тарифи, фільтрує по зоні доставки (немає CDEK — показуємо тільки Boxberry). Кеш тарифів у Redis на 30 хвилин по ключу delivery:{city}:{weight}:{dimensions}. Час розрахунку: було 2.8s (послідовні запити), стало 380ms (паралельно + кеш).
Процес та строки
Аудит вимог (які служби, які сценарії, трекінг потрібен?) → вибір архітектури → бекенд-інтеграція з API → кешування ПВЗ → віджет на фронтенді → тестування з реальними заявками в тестовому режимі → деплой.
| Сценарій | Строк |
|---|---|
| Одна служба (CDEK або Boxberry), WooCommerce | 1–2 тижні |
| Дві-три служби + віджет карти | 3–5 тижнів |
| Повний мультиперевозчик + трекінг + нотифікації | 6–10 тижнів |
Вартість розраховується індивідуально.







