Розробка кастомного плагіна доставки 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. Зв'яжіться з нами для консультації, і ми допоможемо інтегрувати будь-якого перевізника.







