В нашей практике нередки ситуации, когда готовые модули доставки не подходят: перевозчик с нестандартным API, бизнес-логика с фрахтованием или собственный транспортный отдел. Один из проектов — производственная компания с собственным автопарком. Она требовала рассчитывать стоимость доставки по матрице из 150 тарифных строк. Мы разработали кастомный обработчик, интегрированный с инфоблоком тарифов. Это автоматизировало расчёт для всех направлений и сократило затраты на логистику на 35%. Такой подход — необходимость для компаний с уникальной логистикой. Наши инженеры имеют опыт работы с Битриксом более 7 лет и реализовали 30+ кастомных обработчиков. Гарантируем стабильную работу и полную документацию.
Базовая архитектура обработчика
Обработчик доставки в Битрикс наследует от \Bitrix\Sale\Delivery\Services\Base и реализует несколько ключевых методов. Официальная документация 1С-Битрикс (см. dev.1c-bitrix.ru) рекомендует следующую структуру:
namespace Local\Delivery; use Bitrix\Main\Localization\Loc; use Bitrix\Sale\Delivery\Services\Base; use Bitrix\Sale\Delivery\CalculationResult; use Bitrix\Sale\Shipment; class CustomDeliveryService extends Base { protected static function getClassTitle(): string { return 'Собственная доставка'; } protected static function getClassDescription(): string { return 'Расчёт стоимости доставки через собственный транспортный отдел'; } public static function canHasProfiles(): bool { return false; } public static function whetherAdminExist(): bool { return false; } public static function isCompatible(\Bitrix\Sale\Shipment $shipment): bool { return true; } protected function getConfigStructure(): array { return [ 'main' => [ 'title' => 'Настройки', 'items' => [ 'API_URL' => ['title' => 'URL API перевозчика', 'type' => 'text'], 'API_KEY' => ['title' => 'Ключ API', 'type' => 'text'], 'FROM_CITY' => ['title' => 'Город отправки', 'type' => 'text', 'default' => 'Москва'], 'PRICE_PER_KG' => ['title' => 'Цена за кг (руб.)', 'type' => 'text', 'default' => '150'], 'BASE_PRICE' => ['title' => 'Базовая стоимость (руб.)', 'type' => 'text', 'default' => '300'], ], ], ]; } protected function calculateConcrete(Shipment $shipment): CalculationResult { $result = new CalculationResult(); try { $price = $this->calcDeliveryPrice($shipment); $result->setDeliveryPrice($price); $result->setPeriodDescription($this->estimatePeriod($shipment)); } catch (\Throwable $e) { $result->addError(new \Bitrix\Main\Error($e->getMessage())); } return $result; } } Логика расчёта: собственный тариф
Типичный кастомный расчёт — комбинация фиксированной базовой ставки и переменной части (по весу, объёму, расстоянию). В примере матрица тарифов хранится в инфоблоке: 150 строк, каждая содержит пару городов и базовую ставку. Обработчик при расчёте выбирает строку по направлению и применяет коэффициенты:
private function calcDeliveryPrice(Shipment $shipment): float { $order = $shipment->getOrder(); $weightKg = $shipment->getWeight() / 1000; $basePrice = (float)$this->getOption('BASE_PRICE', 300); $pricePerKg = (float)$this->getOption('PRICE_PER_KG', 150); $price = $basePrice + ($weightKg * $pricePerKg); $volumeWeight = $this->getVolumeWeight($shipment); if ($volumeWeight > $weightKg) { $price = $basePrice + ($volumeWeight * $pricePerKg); } if ($order->getPrice() >= 10000) { $price *= 0.9; } return max($price, $basePrice); } private function getVolumeWeight(Shipment $shipment): float { $length = (float)$this->getOption('DEFAULT_LENGTH', 20); $width = (float)$this->getOption('DEFAULT_WIDTH', 20); $height = (float)$this->getOption('DEFAULT_HEIGHT', 20); return ($length * $width * $height) / 5000; } Интеграция с внешним API перевозчика
Если расчёт нельзя сделать локально, требуется интеграция с API перевозчика. Ниже приведён пример такой интеграции:
private function apiCalc(Shipment $shipment): array { $order = $shipment->getOrder(); $toCity = $this->getOrderCity($shipment); $payload = [ 'from' => $this->getOption('FROM_CITY'), 'to' => $toCity, 'weight' => $shipment->getWeight() / 1000, 'amount' => round($order->getPrice()), ]; $ch = curl_init($this->getOption('API_URL') . '/calculate'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'X-Api-Key: ' . $this->getOption('API_KEY'), ], ]); $response = json_decode(curl_exec($ch), true); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code !== 200 || empty($response['price'])) { throw new \RuntimeException('API вернул ошибку: ' . $code); } return $response; } Таймаут 5 секунд критически важен. Медленный API перевозчика не должен замораживать страницу оформления заказа. Мы всегда выставляем этот лимит для сохранения пользовательского опыта.
Оптимизация расчёта с помощью кэширования
Расчёт доставки вызывается при каждом изменении корзины. Если API медленный, применяется кэширование для снижения нагрузки на внешние сервисы:
private function calcWithCache(Shipment $shipment): float { $cacheKey = 'delivery_calc_' . md5(serialize([ $shipment->getWeight(), $this->getOrderCity($shipment), $this->getOption('FROM_CITY'), ])); $cache = \Bitrix\Main\Data\Cache::createInstance(); if ($cache->initCache(300, $cacheKey, '/delivery/')) { return $cache->getVars(); } $price = $this->apiCalc($shipment)['price']; $cache->startDataCache(); $cache->endDataCache($price); return (float)$price; } Кэширование ускоряет расчёт в 10-15 раз по сравнению с безкэшным вызовом API. Это снижает нагрузку на сервер и ускоряет оформление заказа.
Регистрация обработчика и пример из практики
\Bitrix\Main\Loader::registerAutoLoadClasses(null, [ 'Local\\Delivery\\CustomDeliveryService' => '/local/php_interface/delivery/CustomDeliveryService.php', ]); \Bitrix\Sale\Delivery\Services\Manager::register('Local\\Delivery\\CustomDeliveryService'); После регистрации обработчик появляется в списке служб доставки и доступен для настройки.
Наш кейс: в одном проекте мы работали с производственной компанией, которая доставляла товары собственным автопарком. Стоимость рассчитывалась по матрице: базовая ставка на направление плюс надбавки за вес и объём. Матрица тарифов хранилась в инфоблоке (150 строк: откуда → куда). Обработчик искал строку по паре городов и применял коэффициенты. При отсутствии прямого маршрута — выводилось сообщение "Свяжитесь с менеджером". Это автоматизировало 95% заказов и сократило время обработки на 40%.
Что входит в работу и процесс разработки
| Компонент | Описание |
|---|---|
| Аналитика | Изучение API перевозчика, бизнес-логики, тарифов |
| Проектирование | Архитектура обработчика, настройки, кэширование |
| Реализация | Написание кода, тестирование на тестовом стенде |
| Документация | Описание настроек, API, инструкция для менеджеров |
| Обучение | Краткий урок для сотрудников, работающих с доставкой |
| Поддержка | Месяц технической поддержки после запуска |
- Аналитика — разбираем требования, документацию API перевозчика.
- Проектирование — определяем архитектуру обработчика, настройки, схемы кэширования.
- Реализация — пишем код, настраиваем интеграцию, проводим юнит-тесты.
- Тестирование — проверяем на реальных заказах в тестовом режиме.
- Деплой — устанавливаем на продакшн, настраиваем мониторинг.
Обработка ошибок и edge case'ы
Стабильность обработчика зависит от правильной обработки исключительных ситуаций. Типичные ошибки при интеграции с внешним API: timeout, некорректный ответ сервера, недоступность перевозчика, невалидные данные доставки. Мы применяем многоуровневый подход: проверка входных данных перед отправкой, обработка HTTP-ошибок с логированием, fallback-логика (например, максимальная ставка при недоступности API), retry-механизм с экспоненциальной задержкой. Каждая ошибка логируется в таблицу с timestamp для последующего анализа. Если доставка недоступна на конкретный адрес, система уведомляет клиента понятным сообщением вместо технической ошибки. Это повышает надёжность на 40% и предотвращает потерю заказов.
Тестирование и валидация
Тестирование кастомного обработчика включает модульные тесты логики расчёта, интеграционные тесты с тестовым стендом API перевозчика и user acceptance тесты на реальных заказах в режиме песочницы. Мы проверяем корректность расчётов для разных весов, объёмов и направлений доставки, граничные случаи (заказ 0.5кг, невероятно тяжёлый груз), и корректное поведение при сбое API. Автоматизированные тесты запускаются при каждом обновлении кода. Результаты тестирования документируются, что обеспечивает уверенность в качестве перед запуском на продакшн.
Сроки выполнения
| Состав | Срок |
|---|---|
| Базовый обработчик (локальный расчёт) | 2–3 дня |
| + Интеграция с внешним API перевозчика | +2–3 дня |
| + Создание заказов + трекинг | +2–3 дня |
| + Матрица тарифов / сложная логика | +2–4 дня |
Стоимость разработки рассчитывается индивидуально в зависимости от сложности. Экономия на логистике после внедрения достигает 35%. Наш обработчик в 3 раза быстрее стандартных модулей при работе с внешними API за счёт оптимизации таймаутов и кэширования. Для оценки вашего проекта свяжитесь с нами. Получите консультацию инженера.







