Компонент sale.order.ajax отвечает за одностраничное оформление заказа в интернет-магазинах на Битрикс, и рано или поздно любой разработчик, который ведёт такой проект, упирается в задачу кастомизации: добавить поле, спрятать блок доставки, поменять валидацию или подключить свой способ оплаты. Я регулярно дорабатываю этот компонент на проектах клиентов и в этой статье собрал рабочий подход, без общих слов из документации.
Что такое sale.order.ajax и когда его трогают руками
sale.order.ajax появился в модуле sale как замена старому bitrix:sale.order.full и с 2018 года стал стандартом для чекаута на D7. Он рисует форму в один экран: контакты, доставка, оплата, кнопка «Оформить», и всё это без перезагрузки страницы через AJAX-запросы к самому компоненту. Стандартная логика закрывает 70-80% магазинов, но как только в проекте появляется нестандартная доставка, свои способы оплаты, дополнительные согласия или интеграция с CRM, приходится лезть в шаблон и JS.
Я обычно выделяю три сценария кастомизации:
- визуальные правки - перестановка блоков, скрытие лишних полей, адаптация под фирменный стиль;
- функциональные правки - добавление своих свойств заказа, условная логика показа полей, кастомная валидация;
- интеграционные правки - расчёт доставки через СДЭК или Boxberry по API, подключение эквайринга (Т‑Банк, ЮKassa), передача заказа в внешнюю CRM.
Для третьего сценария правкой одного шаблона не обойтись, там подключаются обработчики событий модуля sale и иногда отдельные AJAX-хендлеры.
Где искать файлы шаблона и как их переопределить без правок ядра
Шаблон по умолчанию лежит в /bitrix/components/bitrix/sale.order.ajax/templates/.default/. Внутри template.php, style.css, script.js и папка js с логикой на чистом JS плюс обёрткой BX.Sale.OrderAjaxComponent. Прямые правки в bitrix/components делать нельзя, обновление модуля их затрёт, поэтому шаблон копируется в /local/templates/ваш_шаблон/components/bitrix/sale.order.ajax/.default/ или под своим именем шаблона, если нужно несколько вариантов чекаута на сайте.
При копировании я обычно переношу не всю папку, а точечно нужные файлы - Битрикс подхватывает переопределённый файл, а остальные берёт из ядра, если используется правильный механизм include через result_modifier.php или через параметр компонента TEMPLATE_THEME. Но на практике для sale.order.ajax проще скопировать шаблон целиком: слишком много зависимостей между template.php и script.js, частичное копирование часто ломает JS-инициализацию блоков.
После копирования компонент вызывается с явным указанием шаблона:
$APPLICATION->IncludeComponent(
"bitrix:sale.order.ajax",
"my_checkout",
array(
"PROPERTY_CODES" => array("NAME", "PHONE", "EMAIL", "CDEK_PVZ"),
"PROPERTY_CODES_REQUIRED" => array("NAME", "PHONE"),
"ALLOW_AUTO_REGISTER" => "Y",
"SEF_MODE" => "N",
)
);
PROPERTY_CODES тут ключевой параметр - именно он определяет, какие свойства заказа реально отрисуются в форме, даже если в инфоблоке свойств заказа их больше.
Кастомизация полей заказа через свойства и personal-раздел
Большинство доработок сводится не к правке HTML, а к работе со свойствами заказа. Каждое поле формы - это свойство типа sale, привязанное к персональному разделу (PERSON_TYPE). Чтобы добавить своё поле, я создаю свойство в Настройках - Магазин - Свойства заказов, указываю тип (строка, список, справочник), привязываю к нужному типу плательщика и добавляю его код в PROPERTY_CODES компонента.
Если нужна условная логика - например, поле «Название компании» показывать только для юрлиц - это делается в script.js через подписку на события смены типа плательщика:
BX.addCustomEvent('onSaleOrderAjaxPersonTypeChanged', function(personTypeId) {
var companyField = document.querySelector('[data-entity="company_name"]');
if (!companyField) return;
companyField.closest('.sale-order-ajax-field').style.display =
personTypeId === 2 ? 'block' : 'none';
});
Важный нюанс: события у sale.order.ajax не документированы так подробно, как хотелось бы, часть из них приходится вылавливать через отладку в консоли браузера, расставляя breakpoint в минифицированном bundle. Я обычно беру неминифицированную версию script.js из ядра и сверяюсь по ней, а не по core_ajax.min.js.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Доставка и оплата: интеграция СДЭК и эквайринга в шаблон
Самая частая причина кастомизации, с которой ко мне приходят, это доставка. Стандартный расчёт через модуль sale поддерживает служебные интеграции, но кастомный виджет выбора пункта выдачи СДЭК на карте, привязка стоимости к весу корзины с нестандартной формулой или showcase собственных ПВЗ требуют переопределения блока delivery в шаблоне.
Логика следующая: на клиенте я добавляю свой JS-виджет карты, который после выбора точки записывает её код в скрытое поле-свойство заказа (например, DELIVERY_POINT_ID), а на сервере обработчик события OnSaleComponentOrderOneStepDeliveryPay пересчитывает стоимость доставки исходя из выбранной точки. Для эквайринга (я чаще работаю с Т‑Банк и ЮKassa) похожая история - платёжная система подключается штатным модулем payment system, а в шаблоне переопределяется только вывод способов оплаты, если нужен кастомный вид карточек или иконки.
| Задача | Где правится | Типичный срок |
|---|---|---|
| Скрыть/показать способ доставки | template.php + JS-фильтр по DELIVERY_ID | 1-2 дня |
| Виджет ПВЗ СДЭК с картой | script.js + обработчик OnSaleComponentOrderOneStepDeliveryPay | 3-5 дней |
| Кастомная валидация полей | script.js, событие onOrderAjaxDataReceived | 1 день |
| Передача заказа во внешнюю CRM | обработчик OnSaleOrderSaved | от 3 дней |
Если у вас уже есть готовый парсер зон доставки или интеграция с эквайрингом на Tilda и нужно перенести ту же логику на Битрикс, дешевле не переписывать с нуля, а адаптировать существующую схему расчёта под структуру sale.order.ajax - я закладываю на это меньше времени, чем на разработку с нуля.
JS-события компонента и точки расширения на клиенте
Основной объект на клиенте - BX.Sale.OrderAjaxComponent, он хранит состояние формы и генерирует пользовательские события через BX.addCustomEvent. Из тех, что я использую чаще всего:
onSaleOrderAjaxPersonTypeChanged- смена типа плательщика (физлицо/юрлицо);onSaleOrderAjaxDeliveryChanged- смена способа доставки, сюда вешаю пересчёт стоимости на фронте;onSaleOrderAjaxPaySystemChanged- смена способа оплаты;onSaleOrderAjaxOrderCreated- заказ успешно создан, точка для отправки события в аналитику или пиксель.
Последнее событие я обычно использую для интеграции с внешними системами аналитики и уведомлений - например, чтобы после оформления заказа сразу дёрнуть свой webhook и продублировать данные в Telegram-бота на aiogram для отдела продаж, без ожидания штатных крон-обработчиков модуля sale. Такая связка закрывает разрыв между «заказ создан» и «менеджер узнал о заказе» за секунды вместо минут.
Если расширение сводится к точечным правкам чужого шаблона без переписывания ядра логики, такие задачи я закрываю в рамках разработки и доработки интеграций для интернет-магазинов - обычно это быстрее, чем разбираться в чужом шаблоне самостоятельно, особенно если правок несколько и они взаимосвязаны.
Типичные ошибки при кастомизации sale.order.ajax
За несколько лет работы с этим компонентом я вывел список граблей, на которые наступают почти все:
- Правка файлов прямо в bitrix/components - слетает при первом обновлении модуля sale, причём тихо, без предупреждения;
- Игнор кеша компонента - sale.order.ajax кеширует часть данных, и после правки PROPERTY_CODES изменения не видны, пока не почистить кеш вручную через административную панель;
- Правка минифицированного script.js - при следующем обновлении модуля правки теряются, нужно either хранить diff отдельно, либо (правильнее) выносить кастомную логику в отдельный подключаемый JS-файл через init.php, не трогая файл ядра;
- Несогласованность PROPERTY_CODES между PHP и JS - если добавили свойство в БД, но не прописали его в параметрах компонента, поле просто не появится, и час уходит на поиск несуществующей ошибки;
- Смешивание логики валидации на клиенте и сервере - JS-валидация не подменяет серверную, обе должны дублировать друг друга, иначе заказ можно оформить в обход обязательных полей просто отключив JS в браузере.
Отдельно скажу про мобильную адаптацию: штатный шаблон .default рассчитан на десктоп с натяжкой, на узких экранах часто ломается сетка блока оплаты, если добавить больше двух-трёх способов. Проверяю каждую доработку на 375px ширины отдельно, до сдачи заказчику.
Интернет-магазин под ключ
Интернет-магазин
от 80 000 ₽
Подробнее →Частые вопросы
Можно ли использовать sale.order.ajax без модуля sale в D7-режиме?
Нет, компонент жёстко завязан на новую архитектуру заказов модуля sale (namespace BitrixSale). Если магазин работает на старом модуле catalog/sale в режиме совместимости, сначала нужен переход на D7, а это отдельная миграция с проверкой всех обработчиков событий заказа.
Как добавить своё поле в форму заказа без разработчика?
Частично можно через административную панель - создать свойство заказа нужного типа и привязать к типу плательщика, оно появится в форме автоматически, если входит в список PROPERTY_CODES компонента. Но условная логика показа, кастомная валидация и визуальное встраивание в сетку шаблона руками через админку не делаются, там нужна правка script.js и template.php.
Почему после правки шаблона изменения не отображаются на сайте?
Чаще всего дело в кеше компонента или в том, что правки внесены в bitrix/components вместо local/templates - система при наличии переопределённого шаблона в local берёт именно его, а не ядровый, и если путь указан неверно, компонент молча использует старую версию. Второй частый случай - браузер кеширует script.js, нужно сбросить версию файла или почистить кеш браузера при тестировании.
Сколько стоит доработка чекаута на sale.order.ajax под свою доставку и оплату?
Зависит от объёма: точечная правка полей и валидации занимает 1-2 дня, интеграция с СДЭК или другой службой доставки с виджетом ПВЗ и пересчётом стоимости - от недели. Как ориентир по рынку у сторонних студий такие задачи обычно оценивают от 30 000 до 100 000 ₽ в зависимости от сложности интеграции, у меня разработка интернет-магазина под ключ с такими доработками начинается от 80 000 ₽, а точечный кастомный скрипт под готовый магазин можно обсудить отдельно.