1С Битрикс · 7 мин чтения

sale.order.ajax: кастомизация шаблона оформления заказа в Битрикс

Компонент 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 ₽, а точечный кастомный скрипт под готовый магазин можно обсудить отдельно.

Есть задача?

Обсудим в мессенджере

Расскажите, что нужно сделать — отвечу в течение 4 часов в рабочее время. Первая консультация бесплатно.

Самозанятый Калинкин Н. А. · работаю с физлицами и юрлицами

Продолжая пользование настоящим сайтом Вы выражаете своё согласие на обработку Ваших персональных данных (файлов куки) с использованием Yandex.Metrika.
Понятно