Каждый незавершённый заказ — потерянные деньги. Стандартный bitrix:sale.order.ajax на jQuery медленно отрисовывает блоки: обновление поля занимает 1–2 секунды, а при 10 000+ товарах — до 3 секунд. Пользователь уходит, конверсия падает. Настроить многошаговую форму, B2B-реквизиты или выбор даты доставки на этом компоненте практически невозможно — код превращается в лапшу из PHP-вставок и JavaScript.
Мы заменяем sale.order.ajax на React-чекаут под ключ. Наши инженеры — сертифицированные разработчики Битрикс с 10+ годами опыта. После внедрения у одного из клиентов конверсия выросла с 62% до 79% за 6 недель. Средний бюджет проекта — $1.5k–4k, окупаемость наступает через 4–5 месяцев. Если вы хотите таких же результатов, свяжитесь с нами — оценим ваш проект.
Почему React-чекаут быстрее и гибче стандартного компонента?
React-чекаут решает проблему на уровне архитектуры: UI в компонентах, логика в хуках, общение с сервером через API. Смена доставки обрабатывается за 200 мс, штатный компонент тратит больше секунды. Валидация полей выполняется мгновенно при потере фокуса — пользователь сразу видит ошибку, а не после нажатия кнопки.
Как устроена архитектура React-чекаута?
Оформление заказа делится на два независимых уровня: UI-уровень (React) и бизнес-логика (Битрикс на сервере). На фронте — React-приложение, которое управляет формой, показывает/скрывает шаги, рассчитывает итог в реальном времени. На сервере — Битрикс обрабатывает заказ через \Bitrix\Sale\Order, применяет скидки, рассчитывает стоимость доставки, проверяет остатки. Подробнее о системе заказов — в документации Bitrix Sale.
Ключевой API-метод для расчёта заказа без его создания:
// Расчёт итогов без сохранения заказа
$order = \Bitrix\Sale\Order::create(SITE_ID, $userId);
$basket = \Bitrix\Sale\Basket::loadSiteBasket(SITE_ID);
$order->setBasket($basket);
// Применяем параметры доставки
$shipment = $order->getShipmentCollection()->createItem(
\Bitrix\Sale\Delivery\Services\Manager::getById($deliveryId)
);
$shipment->setFields(['DELIVERY_ID' => $deliveryId, 'CURRENCY' => 'USD']);
$shipment->calculateDelivery();
// Применяем купон
$order->getDiscountSystem()->calculate();
// Возвращаем итог без сохранения (без вызова $order->save())
return [
'subtotal' => $basket->getPrice(),
'delivery_price' => $shipment->getPrice(),
'discount' => $order->getDiscountPrice(),
'total' => $order->getPrice(),
];
Этот endpoint вызывается при каждом изменении полей: выбор службы доставки, ввод промокода, изменение количества. React получает актуальные цифры без перезагрузки.
Как интегрировать React-чекаут с Битрикс?
Для сложного чекаута (3+ шагов с валидацией) оптимальна библиотека React Hook Form с Zod-схемами валидации:
const checkoutSchema = z.object({
contact: z.object({
name: z.string().min(2, 'Укажите имя'),
phone: z.string().regex(/^\+7\d{10}$/, 'Неверный формат'),
email: z.string().email('Неверный email'),
}),
delivery: z.object({
type: z.enum(['courier', 'pickup', 'cdek']),
address: z.string().optional(),
pickupId: z.number().optional(),
}),
payment: z.object({
method: z.enum(['online', 'cash', 'invoice']),
}),
});Стейт чекаута хранится в Zustand: шаги, текущий шаг, данные каждого шага, результат расчёта. При переходе между шагами данные не теряются, пользователь может вернуться назад.
Мы используем React Hook Form для валидации, Zustand для состояния и React Query для запросов.
| Технология | Применение |
|---|---|
| React Hook Form + Zod | Валидация форм с минимальным ререндером |
| Zustand | Лёгкий state-менеджер для шагов и UI-состояний |
| React Query | Кеширование запросов к API Битрикс, автоматический retry при сбоях |
Интеграция с картами для курьерской доставки
Яндекс.Карты или DaData для автодополнения адреса — стандартная задача для React-чекаута.
// Хук для автодополнения адреса через DaData
function useAddressSuggest(query: string) {
return useQuery({
queryKey: ['address-suggest', query],
queryFn: () => fetchDaDataSuggestions(query),
enabled: query.length > 3,
staleTime: 60_000,
});
}При выборе адреса через DaData структурированные данные (город, улица, индекс) передаются в Битрикс отдельными полями — это упрощает последующую обработку заказа и передачу в службы доставки.
Кейс: чекаут для мебельного ритейлера
Наш клиент — интернет-магазин мебели с 2000+ SKU. Специфика: товары с разными сроками изготовления (от 3 до 40 дней), возможность заказать доставку на конкретную дату, обязательный замер для ряда товаров, B2B-оформление с реквизитами. Штатный sale.order.ajax не поддерживал ни выбор даты доставки, ни условное отображение блока замера, ни реквизиты компании в одном потоке.
Реализация:
-
Шаг 1 — контакты. Форма с телефоном и именем. Телефон валидируется через libphonenumber-js, подсказка через СМС-верификацию (опционально).
-
Шаг 2 — доставка. Динамическое отображение: если в заказе есть товары с замером — появляется блок «Запись на замер» с datepicker. Доступные даты загружаются с сервера (из CRM Битрикс, занятые слоты закрыты). Выбор даты доставки с учётом срока изготовления — минимальная дата рассчитывается на сервере по
max(PRODUCTION_DAYS)в корзине. -
Шаг 3 — оплата. Переключатель «Физическое лицо / Юридическое лицо». При выборе юрлица разворачивается блок реквизитов (ИНН → автозаполнение через DaData → подтягивание КПП, названия, адреса). Безналичный счёт для B2B генерируется автоматически после создания заказа через
\Bitrix\Sale\PaySystem\Manager. -
Создание заказа. Финальный POST отправляет все данные на сервер. Bitrix создаёт заказ, привязывает кастомные свойства (дата доставки, тип клиента, реквизиты), отправляет уведомления. React получает ID заказа и переводит пользователя на страницу «Спасибо».
| Шаг | Штатный Битрикс | React-чекаут |
|---|---|---|
| Выбор даты доставки | Невозможно | Datepicker с занятыми слотами |
| B2B-реквизиты | Отдельная форма | Inline, в том же потоке |
| Валидация в реальном времени | Только при сабмите | Мгновенно, по blur |
| Расчёт итогов при смене доставки | Перезагрузка блока (>1 с) | Без перезагрузки (<200 мс) |
Конверсия чекаута выросла с 62% до 79% за первые 6 недель после запуска.
Создание заказа на сервере
public function createOrderAction(array $data): array {
$order = \Bitrix\Sale\Order::create(SITE_ID, $this->getCurrentUserId());
$basket = \Bitrix\Sale\Basket::loadSiteBasket(SITE_ID);
$order->setBasket($basket);
// Контакт
$order->setField('USER_DESCRIPTION', $data['comment'] ?? '');
// Доставка
$shipmentCollection = $order->getShipmentCollection();
$shipment = $shipmentCollection->createItem(
\Bitrix\Sale\Delivery\Services\Manager::getById($data['delivery_id'])
);
$shipment->setField('DELIVERY_ID', $data['delivery_id']);
// Оплата
$paymentCollection = $order->getPaymentCollection();
$payment = $paymentCollection->createItem(
\Bitrix\Sale\PaySystem\Manager::getObjectById($data['payment_id'])
);
$payment->setField('PAY_SYSTEM_ID', $data['payment_id']);
$payment->setField('SUM', $order->getPrice());
// Свойства заказа (адрес, телефон, ИНН и т.д.)
$propertyCollection = $order->getPropertyCollection();
foreach ($data['properties'] as $code => $value) {
$prop = $propertyCollection->getItemByOrderPropertyCode($code);
if ($prop) {
$prop->setValue($value);
}
}
$result = $order->save();
if (!$result->isSuccess()) {
throw new \Exception(implode(', ', $result->getErrorMessages()));
}
return ['order_id' => $order->getId()];
} Обработка ошибок и edge cases
Недостаточный остаток товара при оформлении — обрабатывается на финальном шаге сохранения. React показывает модальное окно с перечнем недоступных позиций, предлагает удалить их или сохранить заказ без них.
Потеря соединения во время оформления — React Query с retry: 3 и уведомлением пользователю. Данные формы сохраняются в sessionStorage и восстанавливаются при перезагрузке.
Что входит в работу
- Проектирование шагов чекаута, условной логики, валидации
- Разработка API-контроллеров: расчёт заказа, создание, получение служб доставки и ПВЗ
- Создание React-приложения: форма, стейт-менеджер, интеграция с картами/DaData
- Привязка кастомных свойств заказа, настройка платёжных систем
- Тестирование edge cases: пустая корзина, нехватка остатка, таймаут сессии
- Документация по API и коду, обучение вашей команды
Готовы ускорить ваш чекаут? Закажите разработку React-чекаута — напишите нам. Получите консультацию по вашему проекту — мы расскажем, какие шаги нужны именно вам.







