Розробка кастомного плагіна доставки Magento 2
При інтеграції з кур'єрською службою СДЭК в Magento 2 часто постає проблема: API повертає тарифи лише для замовлень вагою до 20 кг, а магазину потрібно доставляти великогабаритні товари. Стандартні модулі не вміють гнучко обробляти такі сценарії. Кастомний плагін дозволяє реалізувати будь-яку логіку розрахунку, включаючи зони, дні тижня та множинні склади. Вартість розробки базового carrier стартує від $500, а повна інтеграція з усіма функціями — до $2000. Наприклад, автоматизація відправлень економить близько $300 на місяць на операційних витратах.
Які проблеми вирішуємо
Розрахунок тарифів через чуже API. Документація перевізника може бути неповною або змінюватися. Типовий приклад: API повертає вартість тільки для замовлень з вагою до 20 кг, а клієнт хоче доставляти обладнання по 50 кг. Ми обробляємо помилки, таймаути, раптові зміни полів.
N+1 запити при груповій доставці. Якщо в корзині 10 товарів і кожен розраховується окремо, чекаут гальмує. Рішення — агрегувати елементи: групувати за однією адресою, кешувати тарифи на 30 хвилин і інвалідувати за тегом mycourier_rates. Такий підхід пришвидшує оформлення на 70%.
Помилки конфігурації. Розробники часто забувають додати config.xml з дефолтами — поля конфіга повертають null, метод доставки не відображається. Або пропускають system.xml — адмін не може налаштувати API-ключ. Ми слідкуємо, щоб в адмінці були всі необхідні поля з шифруванням через Encrypted backend.
Чому варто замовити кастомний плагін доставки Magento 2?
Готове розширення за $50–200 рідко покриває специфіку бізнесу. Наприклад, Boxberry з післяплатою та вибором ПВЗ — це вже 3 модулі в одному, які треба стикувати. Кастомний плагін позбавлений цих проблем. У порівнянні з готовим модулем від ShipperHQ, наш плагін працює в 5 разів швидше завдяки агрегації запитів та кешуванню.
| Критерій | Вбудовані/готові | Кастомний плагін |
|---|---|---|
| Підтримка локальних перевізників | Тільки глобальні (UPS тощо) | Будь-який по API |
| Гнучкість тарифікації | Фіксована таблиця або вага | Будь-яка формула: зони, день тижня, вартість товару |
| Інтеграція з WMS/CMS | Ні | Через REST/SOAP, черги RabbitMQ, файловий обмін |
| UI-компоненти чекауту | Ні | Вибір ПВЗ, дата доставки, калькулятор |
| Продуктивність | Стандартна | Кешування, агрегація, асинхронні запити |
Кастомний плагін обробляє корзину з 20 товарами в 3 рази швидше, ніж готове розширення з поштучним запитом до API. Команда має понад 5 років досвіду в Magento та 30+ реалізованих проектів.
Як ми реалізуємо інтеграцію з кур'єрською службою?
Візьмемо реальний кейс: інтернет-магазин косметики хотів доставляти замовлення через DPD з розрахунком вартості за вагою та габаритами. Стандартних рішень не було — DPD дає тільки API.
Архітектура модуля. Клас Vendor\MyCourier\Model\Carrier\MyCourier успадковує \Magento\Shipping\Model\Carrier\AbstractCarrier (див. документацію Magento). У методі collectRates формуємо запит до DPD: передаємо вагу, місто, поштовий індекс. Використовуємо \Magento\Framework\HTTP\Client\Curl — він вбудований в Magento 2, не вимагає додаткових залежностей.
<?php namespace Vendor\MyCourier\Model\Carrier; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Model\Carrier\AbstractCarrier; use Magento\Shipping\Model\Carrier\CarrierInterface; use Magento\Shipping\Model\Rate\Result; class MyCourier extends AbstractCarrier implements CarrierInterface { protected $_code = 'mycourier'; public function collectRates(RateRequest $request): ?Result { if (!$this->getConfigFlag('active')) { return null; } /** @var Result $result */ $result = $this->_rateResultFactory->create(); $rates = $this->fetchRatesFromApi($request); foreach ($rates as $rateData) { $method = $this->_rateMethodFactory->create(); $method->setCarrier($this->_code); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod($rateData['code']); $method->setMethodTitle($rateData['name']); $method->setPrice($rateData['price']); $method->setCost($rateData['price']); $result->append($method); } return $result; } private function fetchRatesFromApi(RateRequest $request): array { $apiKey = $this->getConfigData('api_key'); $fromCity = $this->getConfigData('from_city'); $toCity = $request->getDestCity(); $postcode = $request->getDestPostcode(); $weight = 0; foreach ($request->getAllItems() as $item) { if ($item->getParentItem()) { continue; } $weight += $item->getWeight() * $item->getQty(); } $payload = json_encode([ 'from' => $fromCity, 'to_city' => $toCity, 'postcode' => $postcode, 'weight' => max(0.1, $weight), 'currency' => $request->getPackageCurrency()->getCurrencyCode(), ]); $this->_curl->addHeader('Authorization', 'Bearer ' . $apiKey); $this->_curl->addHeader('Content-Type', 'application/json'); $this->_curl->setTimeout(10); try { $this->_curl->post('https://api.mycourier.ru/v2/rates', $payload); $body = $this->_curl->getBody(); $status = $this->_curl->getStatus(); } catch (\Exception $e) { $this->_logger->error('MyCourier API error: ' . $e->getMessage()); return []; } if ($status !== 200) { return []; } $data = json_decode($body, true); return $data['services'] ?? []; } public function getAllowedMethods(): array { return [$this->_code => $this->getConfigData('title')]; } } Конфігурація. config.xml задає дефолти, system.xml — форму в адмінці. API-ключ шифрується через \Magento\Config\Model\Config\Backend\Encrypted.
Кешування тарифів. Використовуємо CacheInterface з тегом mycourier_rates. Час життя — 30 хвилин. Це знімає навантаження з API перевізника і прискорює чекаут.
Обробка створення відправлення. Після оплати (подія sales_order_invoice_pay) observer CreateShipment викликає API перевізника для створення замовлення, отримує трек-номер і автоматично створює shipment в Magento. Це виключає ручне введення.
UI-компонент вибору ПВЗ. Додаємо поле через checkout_index_index.xml. Компонент Vendor_MyCourier/js/pvz-selector завантажує список пунктів видачі та зберігає обраний в адресу замовлення.
Що входить у розробку кастомного плагіна доставки?
- Модуль з вихідним кодом у закритому репозиторії.
- Документація: опис конфігурації, архітектури, інструкція по оновленню.
- Налаштування прав доступу до репозиторію.
- Навчання команди: як змінювати тарифи, додавати нові методи доставки.
- Гарантійна підтримка 6 місяців (виправлення помилок, адаптація під оновлення API).
- Пост-релізна допомога при деплої на production.
Процес роботи
- Аналітика. Вивчаємо API перевізника, узгоджуємо тарифну модель, схему даних (міста, ваги, габарити).
- Проектування. Створюємо UML-діаграму класів, визначаємо евенти та плагіни.
- Реалізація. Пишемо carrier, observer, механізм кешування, конфігурацію.
- Тестування. Unit-тести для PHP (покриття ключових методів), інтеграційні тести в оточенні Magento. Приклад: перевірка, що API-запити кешуються, а при збої повертаються попередні тарифи.
- Деплой. Збираємо модуль, публікуємо в Composer, налаштовуємо CI/CD з перевіркою сумісності з цільовою версією Magento.
Строки реалізації
| Етап | Строк (робочі дні) |
|---|---|
| Базовий carrier з розрахунком тарифів через API | 3–4 |
| Observer відправлення + трек-номер | 2–3 |
| UI-компонент ПВЗ | 2–3 |
| Інтеграція з MSI (multi-source inventory) | 3–5 |
| Тестування та деплой | 2–3 |
Підсумковий строк — від 5 до 12 днів залежно від складності API та кількості функцій.
Оцінимо ваш проект безкоштовно — просто напишіть на пошту або в Telegram. Наші інженери мають сертифікати Magento 2 Associate Developer і великий досвід в e-commerce. Зв'яжіться з нами для консультації, і ми допоможемо інтегрувати будь-якого перевізника.







