Розробка кастомного обробника служби доставки 1С-Бітрікс
Стандартних служб доставки Бітрікс та готових модулів із Маркетплейсу вистачає для більшості магазинів. Але є сценарії, де потрібна власна реалізація: нішевий перевізник без готового модуля, власна логістика, складні правила тарифікації, агрегатор кількох служб в одному обробнику. У таких випадках кастомний обробник пишеться з нуля.
Архітектура кастомного модуля доставки
Обробник служби доставки в 1С-Бітрікс — PHP-клас, що успадковує \Bitrix\Sale\Delivery\Services\Base. Розміщується в /local/modules/{vendor}.delivery.{name}/ або безпосередньо в /local/php_interface/include/sale_delivery/.
Структура файлів для модульного варіанту:
/local/modules/myshop.delivery.customservice/
include.php — підключення автозавантажувача
install/
index.php — клас встановлення модуля
lib/
DeliveryHandler.php — основний клас обробника
ApiClient.php — клієнт API служби доставки
LocationMapper.php — маппінг місцезнаходжень
TrackingAgent.php — агент трекінгу
lang/ru/
install/index.php — мовні фрази
Основний клас обробника
namespace Myshop\Delivery\CustomService;
class DeliveryHandler extends \Bitrix\Sale\Delivery\Services\Base
{
protected static $isCalculatePriceImmediately = true;
public static function getClassTitle(): string
{
return 'Кастомна служба доставки';
}
public static function getClassDescription(): string
{
return 'Доставка через API CustomService';
}
// Параметри налаштування в адміністративній частині
public function getConfigStructure(): array
{
return [
'MAIN' => [
'TITLE' => 'Основні налаштування',
'ITEMS' => [
'API_KEY' => [
'TYPE' => 'STRING',
'NAME' => 'API-ключ',
'DEFAULT' => '',
],
'FROM_CITY' => [
'TYPE' => 'STRING',
'NAME' => 'Місто відправлення',
'DEFAULT' => 'Київ',
],
'AUTO_CREATE' => [
'TYPE' => 'Y/N',
'NAME' => 'Створювати заявку автоматично',
'DEFAULT' => 'N',
],
],
],
];
}
}
Метод розрахунку вартості
Ключовий метод — calculateConcrete(). Викликається при кожному розрахунку вартості на сторінці кошика та чекауту.
protected function calculateConcrete(
\Bitrix\Sale\Shipment $shipment
): \Bitrix\Sale\Delivery\CalculationResult {
$result = new \Bitrix\Sale\Delivery\CalculationResult();
// 1. Отримуємо необхідні дані з відправлення
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$toCity = $props->getItemByOrderPropertyCode('CITY')?->getValue();
if (!$toCity) {
$result->addError(new \Bitrix\Main\Error('Місто доставки не вказано'));
return $result;
}
// 2. Розраховуємо вагу
$weight = $this->getShipmentWeight($shipment); // у грамах
// 3. Викликаємо API (з кешуванням!)
try {
$apiClient = new ApiClient($this->getOption('API_KEY'));
$price = $apiClient->calcPrice(
$this->getOption('FROM_CITY'),
$toCity,
$weight
);
} catch (\Exception $e) {
$result->addError(new \Bitrix\Main\Error('Помилка розрахунку: ' . $e->getMessage()));
return $result;
}
if ($price <= 0) {
$result->addError(new \Bitrix\Main\Error('Доставка до цього міста недоступна'));
return $result;
}
// 4. Формуємо результат
$result->setDeliveryPrice($price);
$result->setPeriodDescription('2–5 днів');
return $result;
}
Кешування в calculateConcrete
Метод calculateConcrete() може викликатися кілька разів за одне завантаження сторінки (при оновленні кошика). Кешуємо результати API-запитів:
private function getCachedPrice(string $fromCity, string $toCity, int $weight): ?float
{
$cacheKey = 'delivery_price_' . md5("{$fromCity}_{$toCity}_{$weight}");
$cache = \Bitrix\Main\Data\Cache::createInstance();
if ($cache->startDataCache(1800, $cacheKey, '/delivery/custom')) {
$price = $this->apiClient->calcPrice($fromCity, $toCity, $weight);
$cache->endDataCache(['price' => $price]);
}
return $cache->getVars()['price'];
}
Метод створення заявки
Метод викликається при фактичному створенні відправлення — зазвичай при зміні статусу замовлення менеджером.
public function createDelivery(\Bitrix\Sale\Shipment $shipment): array
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$trackCode = $this->apiClient->createOrder([
'order_id' => $order->getId(),
'recipient' => $this->buildRecipient($props),
'cargo' => $this->buildCargo($shipment),
]);
// Зберігаємо трек-код у відправлення
$shipment->setField('TRACKING_NUMBER', $trackCode);
// І у властивості замовлення (для відображення покупцю)
$props->getItemByOrderPropertyCode('TRACKING_CODE')?->setValue($trackCode);
$order->save();
return ['trackCode' => $trackCode];
}
Автоматичне створення заявки за подією
Якщо потрібно створювати заявку автоматично при зміні статусу замовлення:
// У /local/php_interface/init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'sale', 'OnSaleStatusOrder',
function(\Bitrix\Main\Event $event) {
$orderId = $event->getParameter('id');
$newStatus = $event->getParameter('statusId');
if ($newStatus !== 'PROCESSING') return;
$order = \Bitrix\Sale\Order::load($orderId);
$shipmentCollection = $order->getShipmentCollection();
foreach ($shipmentCollection as $shipment) {
if ($shipment->isSystem()) continue;
$service = \Bitrix\Sale\Delivery\Services\Manager::getObjectById(
$shipment->getDeliveryId()
);
if ($service instanceof DeliveryHandler) {
$service->createDelivery($shipment);
}
}
}
);
Сумісність (isCompatible) та доступність
public function isCompatible(\Bitrix\Sale\Shipment $shipment): bool
{
// Перевіряємо країну
$location = $this->getShipmentLocation($shipment);
if (!$this->isLocationSupported($location)) return false;
// Мінімальна сума замовлення
$order = $shipment->getOrder();
if ($order->getPrice() < 500) return false;
// Максимальна вага
if ($this->getShipmentWeight($shipment) > 30000) return false;
return true;
}
Метод isCompatible() викликається 1С-Бітрікс перед розрахунком. Якщо повертає false — служба не відображається покупцю, розрахунок не виконується.
Сторінка налаштувань в адміністративній частині
Параметри обробника зберігаються в b_sale_delivery_service_params і доступні через $this->getOption('KEY'). Форма налаштувань генерується автоматично з масиву, що повертається getConfigStructure(). Для нестандартних полів (випадаючий список міст з API, карта) — перевизначаємо метод getEditTemplateHTML().
Терміни розробки
| Склад | Термін |
|---|---|
| Базовий обробник: розрахунок + створення | 4–5 днів |
| + Трекінг (polling агент) | +1–2 дні |
| + Webhook-обробник | +1 день |
| + Віджет ПВЗ на чекауті | +2 дні |
| + Кабінет менеджера (друк, статуси) | +2–3 дні |
Повний кастомний модуль доставки «під ключ» з інсталятором, налаштуваннями, розрахунком, створенням заявок, трекінгом та інтерфейсом менеджера — 10–14 робочих днів.







