Ограничения служб доставки в интернет‑магазине Битрикс на D7
Зачем нужны ограничения доставки
При работе интернет‑магазина часто нужно исключить курьерку для тяжёлого тарифа, отключить ПВЗ за пределами обслуживаемой области или привязать способ отправки к выбранной оплате. В платформе на D7 эти условия оформляются как ограничения службы доставки: платформа последовательно запускает зарегистрированные проверки и отбрасывает вариант, который не прошёл правило.
В коробке уже есть ограничения по местоположению, весу, стоимости и ряду смежных сценариев. Если бизнесу нужно нестандартное условие, его добавляют отдельным PHP‑классом и включают в реестр обработчиков событием onSaleDeliveryRestrictionsClassNamesBuildList.
Регистрация класса ограничения
Событию передаётся карта «полное имя класса → путь к файлу от корня сайта». Путь должен реально существовать; удобно положить реализацию в /local/lib/... и подключать автозагрузкой Composer или через явный require_once до срабатывания цепочки ограничений.
use Bitrix\Main\EventManager;
use Bitrix\Main\EventResult;
EventManager::getInstance()->addEventHandler(
'sale',
'onSaleDeliveryRestrictionsClassNamesBuildList',
static function (): EventResult {
return new EventResult(
EventResult::SUCCESS,
[
\Fulfillment\RouteGuard\SlotAvailabilityRule::class
=> '/local/lib/Fulfillment/RouteGuard/SlotAvailabilityRule.php',
]
);
}
);Минимальный каркас на Base
Точкой расширения служит абстрактный предок \Bitrix\Sale\Delivery\Restrictions\Base. Полезные ориентиры можно подсмотреть в каталоге /bitrix/modules/sale/lib/delivery/restrictions/, но для собственной логики достаточно переопределить перечисленные ниже статические методы.
getClassTitleиgetClassDescriptionзадают текст в интерфейсе администрирования.extractParamsготовит срез данных из активной отгрузки перед проверкой.getParamsStructureописывает поля конфигурации ограничения в административной форме.checkсравнивает то, что вернулextractParams, с параметрами, сохранёнными для конкретной службы.
namespace Fulfillment\RouteGuard;
use Bitrix\Sale\Shipment;
use Bitrix\Sale\Delivery\Restrictions\Base;
final class SlotAvailabilityRule extends Base
{
public static function getClassTitle(): string
{
return 'Отбор слота перед отгрузкой';
}
public static function getClassDescription(): string
{
return 'Сравнивает выбранные оплату и вес отправления с сохранёнными порогами.';
}
protected static function extractParams(Shipment $shipment)
{
return null;
}
public static function getParamsStructure($deliverySvcId = 0): array
{
return [];
}
public static function check($payload, array $ruleConfig, $deliverySvcId = 0)
{
return true;
}
}Извлекаем контекст из отгрузки
Методу extractParams передаётся \Bitrix\Sale\Shipment участвующего в расчёте экземпляра. По коллекции позиций отгрузки можно пройти товары корзины, подняться к заказу и прочитать оплаты, свойства получателя или произвольные данные складской интеграции. Если проверке ничего не нужно из заказа, допустимо вернуть null или скаляр. Подробнее об объектах см. заметки о корзине и о заказе на D7.
protected static function extractParams(Shipment $shipment)
{
$payload = [
'paySystemHandles' => [],
];
foreach ($shipment->getShipmentItemCollection() as $line) {
$basketRow = $line->getBasketItem();
if ($basketRow && $basketRow->getProductId() > 0) {
$payload['sampleProductId'] = (int)$basketRow->getProductId();
}
}
$order = $shipment->getCollection()->getOrder();
foreach ($order->getPaymentCollection() as $payment) {
$payload['paySystemHandles'][] = (int)$payment->getPaymentSystemId();
}
return $payload;
}Настройки в админке и проверка
getParamsStructure возвращает массив описаний полей. Типы вроде Y/N, ENUM и NUMBER превращаются в переключатели, списки и числовые вводы. Пустой массив означает «ограничение без ручных параметров».
В check первый аргумент — результат extractParams, второй — сохранённые значения из формы, третий — идентификатор службы доставки. Возвращайте true, если способ разрешён. Для не тестовых сценариев полезно явно игнорировать служебные вызовы с некорректным $deliverySvcId.
public static function getParamsStructure($deliverySvcId = 0): array
{
return [
'RQ_SLOT_ACK' => [
'TYPE' => 'Y/N',
'VALUE' => 'Y',
'LABEL' => 'Требовать подтверждённое окно доставки',
],
'RQ_PAY_SYSTEM_UID' => [
'TYPE' => 'NUMBER',
'DEFAULT' => '0',
'MIN' => 0,
'LABEL' => 'ID платёжной системы-спутника',
],
'RQ_HUB_TAGS' => [
'TYPE' => 'ENUM',
'MULTIPLE' => 'Y',
'OPTIONS' => [11 => 'Север', 19 => 'Юг'],
'LABEL' => 'Разрешённые узлы распределения',
],
];
}
public static function check($payload, array $ruleConfig, $deliverySvcId = 0)
{
if ((int)$deliverySvcId <= 0) {
return true;
}
$wantedPay = (int)($ruleConfig['RQ_PAY_SYSTEM_UID'] ?? 0);
if ($wantedPay > 0) {
$handles = is_array($payload['paySystemHandles'] ?? null) ? $payload['paySystemHandles'] : [];
if (!in_array($wantedPay, $handles, true)) {
return false;
}
}
return ($ruleConfig['RQ_SLOT_ACK'] ?? 'N') === 'Y';
}Порядок проверки и хранилище параметров
Статическое свойство $easeSort задаёт очередность: чем значение выше, тем позже выполняется правило (по умолчанию 100). Практичная градация: 100 для лёгких сравнений полей без БД, 200 там, где нужны простые запросы, и 300+ для тяжёлых расчётов.
Если стандартного хранилища параметров недостаточно, переопределяют prepareParamsValues, save и delete — именно этим механизмом платформа совмещает новое ограничение по местоположениям со старыми таблицами совместимости.
Сценарий «все регионы, кроме списка»
Для узких зон исключений иногда нужна инверсия стандартного правила локаций: связь между службой и деревом регионов уже учитывает выбранные узлы через DeliveryLocationTable, а бизнесу достаточно разрешить доставку везде, кроме перечисленных кодов. Реализуется это дополнением к extractParams, которое читает символьный код местоположения из свойства заказа доставки, и проверкой, инвертирующей результат DeliveryLocationTable::checkConnectionExists. После сохранения настройки обычно синхронизируют методом prepareParamsForSaving, а при удалении очищают собственную таблицу или вызывают resetMultipleForOwner, если данные живут во встроенном контуре связей службы.
Итого
- Кастомные ограничения подключаются событием
onSaleDeliveryRestrictionsClassNamesBuildList. - Класс наследует
Base: отделяйте сбор фактов заказа (extractParams) от бизнес‑условия (check). - Используйте
$easeSort, чтобы дорогие проверки выполнялись после дешёвых.
Не хотите копаться сами?
Починю за 1-3 дня. Без предоплаты — оплата по результату.
15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии