Каждый незавершённый заказ — потерянные деньги. Стандартный 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-чекаута — напишите нам. Получите консультацию по вашему проекту — мы расскажем, какие шаги нужны именно вам.







