Когда магазин работает сразу с несколькими перевозчиками, удобно получать тарифы из единой точки. Агрегатор доставки отдаёт стоимость и сроки по API, а задача Битрикса — корректно собрать данные отправления, запросить расчёт и показать цену покупателю в корзине.
Зачем считать доставку через агрегатор
Прямая интеграция с каждой службой (СДЭК, Boxberry, DPD, Почта России) — это отдельные ключи, форматы и обработчики. Агрегатор вроде единого API логистики берёт эту работу на себя: вы отправляете один запрос с параметрами отправления и получателя, а в ответ приходит список тарифов от подключённых у агрегатора перевозчиков.
В 1С-Битрикс такой расчёт реализуется как собственная служба доставки с типом «Расчёт по обработчику». Обработчик в момент оформления заказа обращается к API и возвращает цену. Это даёт три выигрыша:
- единая логика расчёта вместо нескольких коробочных модулей;
- актуальные тарифы онлайн, а не таблицы, которые надо руками обновлять;
- возможность фильтровать и наценивать результаты под свою бизнес-логику.
Как устроен расчёт доставки в Битрикс
Расчётом отгрузки в D7 занимается служба доставки — наследник \Bitrix\Sale\Delivery\Services\Base. Ключевой метод — calculateConcrete(Shipment $shipment), который обязан вернуть объект \Bitrix\Sale\Delivery\CalculationResult.
Внутри результата вы устанавливаете цену и срок:
setDeliveryPrice()— итоговая стоимость доставки;setPeriodDescription()— текст срока («2–4 дня»);addError()— если расчёт невозможен, служба скроется из списка.
Из объекта Shipment доступны все данные корзины: вес через getWeight() (в граммах), сумма товаров через getPrice(), коллекция позиций и связанный заказ через getCollection()->getOrder(). Местоположение получателя берётся из свойств заказа или из выбранного местоположения доставки. Именно эти значения превращаются в тело запроса к агрегатору.
Свой обработчик как служба доставки
Регистрируется обработчик через событие onSaleDeliveryHandlersClassNamesBuildList модуля sale. В обработчике события вы возвращаете массив вида «код класса → путь к файлу», после чего служба появляется в списке при создании доставки в Магазин → Настройки → Службы доставки.
Минимальный каркас класса:
getClassTitle()иgetClassDescription()— название в админке;getConfigStructure()— поля настроек: URL API, токен, идентификатор договора, склад отправления, наценка;isCalculatePriceImmediately()— вернутьtrue, если цена нужна сразу в списке служб;calculateConcrete()— сам расчёт.
Если агрегатор отдаёт несколько тарифов (курьер, ПВЗ, постамат), удобнее сделать профильную службу: родитель наследует Base, а профили-потомки соответствуют типам доставки. Тогда покупатель видит их как отдельные варианты с разными ценами.
getConfigStructure() или в настройки модуля — так их можно менять без правки файлов и не тащить секреты в репозиторий.Формирование запроса к API агрегатора
Внутри calculateConcrete() собирается payload. Типовой набор полей для расчёта:
| Данные Битрикс | Источник | Поле запроса |
|---|---|---|
| Вес отправления | $shipment->getWeight() | weight (г → кг) |
| Габариты | свойства товара в каталоге | length/width/height |
| Город получателя | местоположение заказа / КЛАДР | to_location |
| Склад отправки | настройка службы | from_location |
| Оценённая стоимость | $shipment->getPrice() | declared_value |
Запрос отправляется через штатный \Bitrix\Main\Web\HttpClient (или JsonHttpClient). Обязательно задайте разумные таймауты — setTimeout() и waitResponse(), — потому что запрос выполняется синхронно в момент оформления заказа и «висящий» агрегатор напрямую тормозит корзину. Ответ парсится через \Bitrix\Main\Web\Json::decode(), из него выбирается нужный тариф, применяется наценка и результат кладётся в setDeliveryPrice().
Кэш, таймауты и обработка ошибок
Расчёт может вызываться многократно за один визит: при пересборке корзины, смене города, добавлении товара. Дёргать API на каждый чих — это лишние задержки и риск упереться в лимиты агрегатора. Поэтому ответ стоит кэшировать по ключу из значимых параметров.
- ключ кэша = хэш от города, веса, габаритов и суммы заказа;
- хранилище —
\Bitrix\Main\Data\Cacheс TTL 10–30 минут; - при совпадении параметров отдаём цену из кэша без обращения к API.
Отдельно продумайте поведение при сбое. Если агрегатор недоступен или вернул ошибку, метод не должен ронять оформление заказа. Разумные стратегии:
- вернуть
CalculationResultсaddError()— служба просто исчезнет из списка; - подставить резервный фиксированный тариф (fallback), чтобы покупатель всё же оформил заказ;
- записать причину в журнал через
\Bitrix\Main\Diag\FileExceptionHandlerLogили свой логгер для последующего разбора.
Ограничения, профили и цена в корзине
Не для каждого заказа расчёт через агрегатор уместен. Чтобы служба показывалась только там, где нужно, используйте штатные ограничения доставки (\Bitrix\Sale\Delivery\Restrictions): по местоположению, весу, сумме или способу оплаты. Это дешевле, чем гонять API ради заведомо неподходящих отправлений.
Когда агрегатор возвращает несколько вариантов, покажите их корректно:
- для доставки в ПВЗ и постаматы понадобится выбор точки на карте — цена может зависеть от конкретного пункта;
- наценку и округление применяйте единообразно, чтобы цифра в корзине совпадала с чеком;
- срок из
setPeriodDescription()выводите рядом со стоимостью — это снижает вопросы в поддержку.
Итоговая стоимость доставки автоматически попадает в компонент оформления заказа sale.order.ajax и пересчитывается при изменении состава корзины, так что отдельно верстать её обычно не требуется.
Итог
Расчёт доставки через агрегатор в 1С-Битрикс — это собственная служба доставки, где calculateConcrete() собирает параметры отправления, запрашивает тариф по API через HttpClient и возвращает CalculationResult. Надёжность решения держится на трёх вещах: кэшировании ответов, коротких таймаутах и аккуратном fallback при сбоях агрегатора.
Если нужно спроектировать такой обработчик, увязать его с профилями, ПВЗ и наценками или разобрать нестабильные ответы стороннего API, мы помогаем с интеграционной разработкой на Битрикс — от расчёта тарифов до создания накладных и трек-номеров.
Частые вопросы
Чем расчёт через агрегатор отличается от подключения одной службы?
Агрегатор отдаёт тарифы сразу нескольких перевозчиков через единый API. Вместо нескольких коробочных модулей вы поддерживаете один обработчик расчёта.
Какой метод отвечает за цену доставки в Битрикс?
Метод calculateConcrete() наследника класса Base. Он возвращает объект CalculationResult, в котором задаются стоимость через setDeliveryPrice() и срок.
Как получить вес и габариты отправления?
Вес доступен через $shipment->getWeight() в граммах. Габариты берутся из свойств товара в каталоге, так как штатной размерности отгрузки в Битрикс нет.
Что произойдёт, если агрегатор недоступен?
Если вернуть CalculationResult с addError(), служба просто скроется из списка. Чаще делают fallback на резервный фиксированный тариф, чтобы заказ всё равно оформился.
Нужно ли кэшировать ответы API?
Да. Расчёт вызывается многократно за визит, поэтому ответ кэшируют по ключу из города, веса и суммы через Bitrix\Main\Data\Cache с TTL в несколько минут.
Как ограничить показ службы только для нужных заказов?
Через штатные ограничения доставки: по местоположению, весу, сумме заказа или способу оплаты. Это исключает лишние обращения к API.
Можно ли показать несколько тарифов от разных перевозчиков?
Да, для этого делают профильную службу: родитель наследует Base, а профили-потомки соответствуют вариантам доставки с разными ценами.
Где хранить ключ API агрегатора?
В полях getConfigStructure() или в настройках модуля, а не в коде. Так секрет можно менять без правки файлов и не хранить его в репозитории.
Поможем с настройкой и поддержкой 1С-Битрикс: Управление сайтом
Поможем с настройкой, доработкой и поддержкой 1С-Битрикс: Управление сайтом.