Задача: изменить стоимость доставки при достижении суммы заказа
Одна из распространённых задач в интернет-магазине на Битрикс — предоставление бесплатной или льготной доставки при достижении определённой суммы в корзине. Например, «бесплатная доставка от 8 500 рублей» или «скидка на доставку 50% при заказе от 5 000 рублей». Стандартный функционал модуля продаж позволяет настроить это через событийную модель, не затрагивая ядро системы.
Для этой задачи используется событие onSaleDeliveryServiceCalculate из модуля sale. Обработчик события вызывается в момент расчёта стоимости доставки и позволяет программно изменить итоговую цену доставки.
Событие onSaleDeliveryServiceCalculate
Событие onSaleDeliveryServiceCalculate генерируется модулем продаж при расчёте стоимости каждой службы доставки. Обработчик получает два ключевых параметра:
- RESULT — объект результата расчёта, через который можно установить новую цену доставки методом
setDeliveryPrice(). - SHIPMENT — объект отправления (Shipment), содержащий информацию о выбранной службе доставки, заказе и вложенных товарах.
Важно: событие срабатывает для каждой доступной службы доставки, поэтому в обработчике необходимо фильтровать по идентификатору службы ($deliveryId), чтобы изменить цену только у нужной.
Разбор кода обработчика
Полный рабочий код обработчика с пояснениями:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
use Bitrix\Main\Event; use Bitrix\Main\EventResult; use Bitrix\Main\EventManager; $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager = EventManager::getInstance(); $eventManager->addEventHandler( 'sale', 'onSaleDeliveryServiceCalculate', 'myCalc' ); function myCalc(Event $event) { $baseResult = $event->getParameter('RESULT'); $shipment = $event->getParameter('SHIPMENT'); // Получаем идентификатор сервиса доставки $delivery = $shipment->getDelivery(); $deliveryId = $delivery->getId(); // Получаем общую стоимость товаров в корзине $basket = \Bitrix\Sale\Basket::loadItemsForFUser(\CSaleBasket::GetBasketUserID(), \Bitrix\Main\Context::getCurrent()->getSite()); $totalPrice = 0; foreach ($basket as $basketItem) { $totalPrice += $basketItem->getPrice() * $basketItem->getQuantity(); } // Пример изменения стоимости доставки для определенного сервиса доставки if ($deliveryId == '259' && $totalPrice > 8500) { $newPrice = 0; // Новая стоимость доставки $baseResult->setDeliveryPrice($newPrice); } $event->addResult( new EventResult( EventResult::SUCCESS, array('RESULT' => $baseResult) ) ); } |
Как вычислить сумму корзины в обработчике
В коде выше используется загрузка корзины через Basket::loadItemsForFUser(). Эта функция принимает идентификатор fuserId (анонимный пользователь корзины) и код сайта. Сумма вычисляется в цикле по всем позициям: цена позиции умножается на количество и добавляется к итогу.
Альтернативно, если нужна сумма уже из объекта отправления, можно получить её через коллекцию корзины заказа:
|
1 2 3 4 |
// Получить сумму корзины через объект заказа (если доступен) $order = $shipment->getCollection()->getOrder(); $basket = $order->getBasket(); $totalPrice = $basket->getPrice(); |
Этот способ более надёжен, так как данные берутся напрямую из объекта заказа, а не из сессии пользователя.
Пример: бесплатная доставка от N рублей
Адаптируйте условие под свои нужды. Например, сделать бесплатную доставку для всех служб при заказе от 10 000 рублей:
|
1 2 3 |
if ($totalPrice >= 10000) { $baseResult->setDeliveryPrice(0); } |
Или задать фиксированную льготную цену доставки (например, 150 рублей вместо стандартной) при заказе от 5 000 рублей:
|
1 2 3 |
if ($totalPrice >= 5000 && $totalPrice < 10000) { $baseResult->setDeliveryPrice(150); } |
Идентификатор службы доставки ($deliveryId) можно найти в административной панели: Магазин → Доставка → Службы доставки. ID отображается в таблице.
Где разместить код
Код обработчика события размещается в файле инициализации Битрикс. Рекомендуется использовать пользовательский файл, чтобы изменения не потерялись при обновлении системы:
|
1 |
/local/php_interface/init.php |
Если папки local нет — создайте её. Это стандартный способ хранения пользовательских обработчиков в Битрикс. Альтернативный путь (устаревший, но рабочий):
|
1 |
/bitrix/php_interface/init.php |
Использовать /bitrix/php_interface/init.php нежелательно, так как файл находится в системной директории и может быть перезаписан при обновлении ядра Битрикс.
Тестирование
После добавления кода проверьте работу следующим образом:
- Добавьте товары в корзину на сумму ниже порогового значения и перейдите к оформлению заказа — стоимость доставки должна быть стандартной.
- Добавьте товары на сумму выше порогового значения — стоимость нужной службы доставки должна измениться согласно условию.
- Если цена не меняется, проверьте правильность
$deliveryId— выведите его черезvar_dump()в обработчике для отладки. - Убедитесь, что файл
init.phpподключается корректно: синтаксических ошибок в нём быть не должно (иначе сайт может перестать работать).
