Разработка мобильного приложения интернет-магазина 1С-Битрикс
Запрос на мобильное приложение обычно приходит, когда адаптивная вёрстка уже есть, конверсия с мобильного трафика — 0.8% против 2.5% на десктопе, а маркетинг хочет push-уведомления, которые в мобильном Safari не работают (Web Push появился только в iOS 16.4, да и то с ограничениями). Вопрос не «зачем приложение», а какой подход выбрать — PWA, кроссплатформа на React Native, или нативная разработка — и как правильно связать это с Битрикс.
PWA: быстрый старт с жёсткими ограничениями
Progressive Web App — самый дешёвый путь. Битрикс-магазин с адаптивной вёрсткой превращается в PWA за два-три дня: manifest.json с иконками и цветами, service worker для кеширования статики и офлайн-страницы, мета-теги для Add to Home Screen.
Что получаете: установка на домашний экран без сторов, офлайн-доступ к ранее загруженным страницам каталога, кеширование через Cache API. Service worker перехватывает запросы и отдаёт закешированные ресурсы — CSS, JS, шрифты, изображения товаров.
Чего не получаете: полноценных push на iOS (ограничение на хранилище ~50 МБ), доступа к NFC и Bluetooth, фоновой синхронизации на iOS, нативных анимаций и переходов. Apple продолжает держать PWA в песочнице WebKit, и это не изменится в ближайшие годы.
PWA подходит для каталога с корзиной, где основной сценарий — просмотр и заказ. Для маркетплейса с чатом, оффлайн-корзиной и сканером штрихкодов — нет.
React Native + REST API: основной вариант для большинства магазинов
React Native даёт нативное приложение с единой кодовой базой на TypeScript. Битрикс выступает бэкендом, отдаёт данные через REST API. Если для веб-версии уже написаны кастомные API-эндпоинты (headless-подход), мобильное приложение переиспользует их без изменений.
Архитектура:
React Native App → HTTPS → API Gateway (опционально) → REST API Битрикс → ORM → PostgreSQL/MySQL
Ключевые REST-методы Битрикс для мобильного приложения:
-
catalog.product.list,catalog.product.get— каталог и карточка товара -
sale.basket.addItem,sale.basket.getItems— корзина -
sale.order.add,sale.order.get— заказы -
sale.shipment.getDeliveryServices,sale.paySystem.getList— доставка и оплата
Но стандартного REST часто недостаточно. На практике пишутся кастомные эндпоинты через \Bitrix\Main\Engine\Controller:
-
/api/mobile/catalog/list— облегчённый ответ для списка (ID, название, цена, одна картинка-превью вместо полного набора свойств) -
/api/mobile/catalog/detail— полная карточка с торговыми предложениями -
/api/cart/calculate— пересчёт корзины с учётом скидок, правил корзины и промокодов -
/api/checkout/delivery-options— расчёт стоимости доставки по адресу
Почему отдельные эндпоинты для мобильного? Размер ответа. На 3G или в лифте каталог из 50 полей на товар убивает UX. Мобильный эндпоинт возвращает 7-8 полей для списка, полный набор — только при открытии карточки.
Пагинация: курсорная вместо страничной
На вебе стандартная страничная пагинация (page=3&limit=20) работает нормально. На мобильном — нет. Пользователь листает ленту вниз бесконечным скроллом. Если между запросами на предыдущую и следующую страницу добавился новый товар — появляются дубли.
Решение — курсорная пагинация. Каждый ответ содержит cursor (обычно закодированный ID + timestamp последнего элемента). Следующий запрос передаёт cursor вместо номера страницы:
GET /api/mobile/catalog/list?section_id=15&cursor=eyJpZCI6MTUwMH0=&limit=20
На стороне Битрикс курсор декодируется в WHERE ID < 1500 ORDER BY ID DESC LIMIT 20 — стабильная выборка независимо от добавления новых товаров.
Push-уведомления: архитектура и сценарии
Push — главное преимущество приложения над мобильным браузером. Архитектура:
-
Device-токен — при установке приложение регистрируется в FCM (Android) или APNs (iOS), получает токен. Приложение отправляет токен на сервер через
/api/push/register. -
Хранение токенов — кастомная таблица в Битрикс или highload-инфоблок:
USER_ID,DEVICE_TOKEN,PLATFORM(ios/android),CREATED_AT. -
Генерация события — обработчик Битрикс на событие
OnSaleStatusOrderили агент для брошенных корзин формирует payload. -
Отправка — HTTP POST в FCM API v1 (
https://fcm.googleapis.com/v1/projects/{project}/messages:send) с токеном устройства, заголовком, текстом и deeplink на экран в приложении.
Сценарии для магазина:
-
Статус заказа — «Заказ #4521 передан курьеру» (событие
OnSaleStatusOrder) -
Брошенная корзина — через 30 минут после добавления без оформления (агент
CAgent) - Снижение цены — товар из избранного подешевел (агент, проверяющий историю цен)
- Персональные акции — через сегментацию в CRM-модуле
React Native использует @react-native-firebase/messaging для приёма push, react-native-push-notification для локального отображения.
Оффлайн-режим: SQLite и дельта-синхронизация
Офлайн-просмотр каталога — причина, по которой пользователь ставит приложение. Архитектура:
При первом запуске приложение загружает каталог через REST API порциями по 100 товаров и сохраняет в локальную SQLite (react-native-sqlite-storage). Изображения кешируются на файловой системе устройства через react-native-fast-image.
Дальше — дельта-синхронизация. Эндпоинт /api/catalog/delta?since=2025-03-10T12:00:00 возвращает только изменённые товары. На стороне Битрикс:
SELECT ID, NAME, PREVIEW_PICTURE, DETAIL_PAGE_URL
FROM b_iblock_element
WHERE IBLOCK_ID = 15
AND TIMESTAMP_X > '2025-03-10 12:00:00'
AND ACTIVE = 'Y'
Плюс отдельный запрос на удалённые товары (через лог удалений или флаг ACTIVE = 'N').
Корзина в оффлайне. Пользователь добавляет товары без сети — они сохраняются в локальной SQLite. При появлении связи приложение отправляет содержимое на сервер через sale.basket.addItem. Сервер может вернуть изменённые цены, убрать недоступные товары, применить скидки. Приложение показывает diff: «Цена на [товар] изменилась с 1500 на 1350 руб.»
Checkout и оплата из приложения
Оформление заказа — технически самый сложный экран. Последовательность:
-
Адрес доставки — автодополнение через DaData (
/api/dadata/suggest/address) или сохранённый адрес из профиля -
Расчёт доставки — запрос к
/api/checkout/delivery-optionsс адресом и содержимым корзины. Битрикс вызывает обработчики доставки (СДЭК, Boxberry), возвращает варианты с ценами и сроками -
Выбор оплаты — список из
sale.paySystem.getList - Промокод — проверка через кастомный endpoint, пересчёт суммы
-
Подтверждение —
sale.order.add
Оплата картой — через SDK платёжного шлюза. ЮKassa предоставляет yookassa-android-sdk и YooKassaPaymentsSDK для iOS. SDK открывает нативный экран оплаты, обрабатывает 3D Secure, возвращает результат. Apple Pay / Google Pay — через тот же SDK.
После оплаты приложение получает подтверждение от SDK, Битрикс — callback от шлюза на /bitrix/tools/sale_ps_result.php. Заказ считается оплаченным, когда Битрикс обработал callback и выставил PAYED = 'Y' в b_sale_order.
Версионирование API
Мобильное приложение обновляется через Store, старые версии живут неделями. API обязан поддерживать обратную совместимость. Три подхода:
-
URL-версионирование —
/api/v1/catalog,/api/v2/catalog. Простое, понятное, но дублирует код. -
Заголовок —
X-API-Version: 2. Один URL, версия в заголовке. Чище, но сложнее отлаживать. - Расширяемые ответы — новые поля добавляются без удаления старых. Клиент игнорирует неизвестные поля. Работает до первого breaking change.
На практике комбинируют: URL-версионирование для мажорных изменений, расширяемые ответы для минорных.
Сроки по масштабу
| Масштаб | Что входит | Срок (React Native) |
|---|---|---|
| PWA | Манифест, service worker, офлайн-страница | 2–3 дня |
| MVP-приложение | Каталог, карточка, корзина, оформление, push | 3–5 недель |
| Стандартный магазин | + ЛК, история, избранное, оффлайн-каталог | 6–8 недель |
| Продвинутый | + сканер, AR-примерка, чат, Apple Pay / Google Pay | 8–12 недель |
Выбор подхода определяется бюджетом и приоритетами. PWA — для проверки гипотезы за минимальные деньги. React Native — для полноценного приложения без двух команд разработки. Нативная разработка — когда нужна каждая миллисекунда отклика и полный контроль над платформенными API.







