Интеграция Битрикс с маркетплейсами: чек-лист перед запуском
Остатки уезжают, заказы приезжают, тест зелёный — а в проде отмена по вине продавца на третий день. Разбираем, что проверить в интеграции 1С-Битрикс с Ozon, WB и Яндекс Маркетом до того, как её включат на живом каталоге.

Интеграция собрана и работает: остатки уезжают на площадку, заказы приезжают в модуль sale, менеджер видит их в админке. На третий день в проде — отмена по вине продавца: один и тот же товар продан в офлайне и на маркетплейсе. Причина не в коде обмена, а в том, что синхронизация остатков висела на агенте Битрикса. Агент по умолчанию запускается на хите посетителя, ночью хитов мало, остаток на площадке застыл на шесть часов. Очевидное решение — «поставим агент раз в 5 минут» — не помогает: интервал агента это не расписание, а минимальная пауза между запусками.
Ниже чек-лист из тех пунктов, которые обычно всплывают уже после запуска. Он рассчитан на 1С-Битрикс: Управление сайтом 23–24 с ядром D7 и модулями catalog и sale, PHP 8.1. Про настройку личного кабинета площадки речи не будет — только то, что живёт на вашей стороне.
Четыре способа связать Битрикс с площадкой
Выбор транспорта определяет половину будущих проблем, поэтому начинать чек-лист надо с него, а не с полей выгрузки.
- Готовый модуль из Маркетплейса 1С-Битрикс. Быстрее всего: ставится, настраивается маппинг свойств, работает. Платите тем, что логика внутри чужая. Когда площадка меняет версию метода, вы ждёте обновления вендора и не можете ускорить этот процесс.
- Внешний сервис-интегратор. Битрикс отдаёт данные в один API, сервис раскладывает их по площадкам. Снимает с вас лимиты и версионирование, добавляет ещё одну точку отказа и абонентскую плату, а главное — ещё одно место, где остатки могут отстать.
- Своя интеграция на событиях, с синхронными вызовами. Обработчик
OnSaleOrderSavedилиOnAfterIBlockElementUpdateдёргает HTTP прямо на хите. Минимальная задержка, максимальный риск: площадка отвечает за 3 секунды — админка Битрикса тормозит на 3 секунды, площадка отдаёт 500 — у вас 500 в сохранении заказа. - Своя интеграция через очередь. События только кладут задачу в таблицу, обменом занимается отдельный процесс по крону. Дороже в разработке на пару дней, но это единственный вариант, который переживает недоступность площадки без потери данных.
| Подход | Срок запуска | Контроль логики | Кто держит лимиты API | Риск при обновлении ядра | Поведение при недоступности площадки |
|---|---|---|---|---|---|
| Готовый модуль | Дни | Низкий, только настройки | Вендор модуля | Средний: ждёте совместимую версию | Зависит от реализации, обычно логируется и повторяется |
| Внешний сервис | Дни | Средний: ваш маппинг, их транспорт | Сервис | Низкий | Данные копятся на стороне сервиса |
| Своя, синхронно на событиях | 1–2 недели | Полный | Вы | Средний: события модулей меняются | Теряете изменение или ломаете хит |
| Своя, через очередь | 2–4 недели | Полный | Вы | Средний | Задачи ждут и повторяются |
Чек-лист перед продакшеном
Товары и идентификаторы
- Проверьте, что уезжают торговые предложения, а не товары. На площадке продаётся конкретный размер и цвет, то есть элемент инфоблока SKU. Связка товар — предложение в Битриксе живёт отдельно; получить её для набора ID можно через
CCatalogSKU::GetInfoByProductIDs(), точную сигнатуру метода в вашей версии сверьте в документации. - Найдите, где лежат штрихкоды. Частая ошибка: ищут свойство элемента, а штрихкоды в Битриксе хранятся отдельной сущностью в таблице
b_catalog_store_barcode. Если площадка требует баркод обязательным, без этой таблицы выгрузка упадёт на половине номенклатуры. - Сверьте единицы измерения и служебные справочники.
MEASUREи смежные служебные коды в Битриксе и у площадки заполняются по разным справочникам. Маппинг должен быть явной таблицей, а не угадыванием по названию. - Зафиксируйте, что считается ключом сопоставления. Артикул, баркод или внутренний ID площадки. Выберите одно поле, запретите его изменение в админке руками и проверьте, что оно уникально:
SELECT ARTICLE_FIELD, COUNT(*) ... GROUP BY ... HAVING COUNT(*) > 1на живой базе почти всегда что-то находит.
Остатки и цены
Главный источник отмен — отдача на площадку физического остатка вместо доступного к продаже.
<?php
use Bitrix\Main\Loader;
use Bitrix\Catalog\ProductTable;
Loader::includeModule('catalog');
// ID здесь — ID элемента инфоблока: товара или торгового предложения
$productIds = [1001, 1002, 1003];
$rows = ProductTable::getList([
'select' => ['ID', 'QUANTITY', 'QUANTITY_RESERVED', 'QUANTITY_TRACE'],
'filter' => ['@ID' => $productIds],
])->fetchAll();
$stocks = [];
foreach ($rows as $row) {
// Площадке нужно то, что можно продать прямо сейчас
$available = (int)$row['QUANTITY'] - (int)$row['QUANTITY_RESERVED'];
// Буфер гасит рассинхрон между выгрузками: лучше не продать одну штуку,
// чем получить отмену по вине продавца
$stocks[(int)$row['ID']] = max(0, $available - 2);
}Оговорка, которая важнее самого кода: при включённом складском учёте резерв распределён по складам, и одного поля QUANTITY_RESERVED недостаточно — смотреть надо остатки по складам (\Bitrix\Catalog\StoreProductTable) и то, какие склады вы отдаёте этой площадке. Механика резервирования в Битриксе менялась между версиями, поэтому перед продом проверьте поведение именно на своей сборке, а не по статье в интернете.
- Решите, какие склады видит площадка. Если на маркетплейс уходит суммарный остаток по всем складам, включая розницу и витрину, переотмены гарантированы.
- Проверьте, что цена берётся из нужного типа цен. У маркетплейсов обычно отдельная цена: своя скидка, своя комиссия. Выгружать базовую цену сайта — способ торговать в убыток.
- Поставьте нижнюю границу. Простая проверка «цена не ниже X и не выше Y от базовой» перед отправкой спасает от обмена с 1С, который однажды приедет с нулями.
- Отправляйте только изменения. Полная выгрузка каталога каждые 15 минут съедает лимиты запросов и ничего не даёт. Храните хеш отправленного значения и пропускайте совпадения.
Интеграция с маркетплейсом — это не выгрузка товаров. Это обязательство отвечать площадке в срок, который вы не контролируете, и отвечать правдой об остатке.
Заказы и статусы
- Обработчик события не должен ходить в сеть. Событие пишет задачу, задачу исполняет крон. Регистрация обработчика в
/bitrix/php_interface/init.php:
Внутри<?php use Bitrix\Main\EventManager; EventManager::getInstance()->addEventHandler( 'sale', 'OnSaleOrderSaved', ['MarketplaceQueue', 'onOrderSaved'] );onOrderSaved— только INSERT в таблицу задач. Состав параметров события (сущность заказа, признак нового заказа) отличается между версиями модуляsale, сверьте его в документации для своей сборки, а не копируйте из примеров пятилетней давности. - Не ловите изменения цен и остатков только событиями. Обмен с 1С через
/bitrix/admin/1c_exchange.phpи массовые операции в админке могут менять данные путями, где ваш обработчик не сработает. Нужен страховочный проход по изменённым за период записям. - Опишите маппинг статусов в обе стороны. Таблица «статус площадки — статус Битрикса» с указанием, какой переход инициирует вашу отправку, а какой только принимается. Без неё заказ будет циклически переключаться между двумя системами.
- Проверьте, что заказ не создаётся дважды. Уникальный индекс по внешнему номеру заказа площадки, а не проверка
SELECTперед вставкой: при двух параллельных кронах проверка не спасёт.
Транспорт: лимиты, повторы, таймауты
Схемы авторизации у площадок разные: Ozon Seller API использует пару заголовков с идентификатором клиента и ключом, Wildberries — токен в заголовке авторизации, Яндекс Маркет менял схему с OAuth на ключ. Конкретные имена заголовков, хосты и версии методов берите из актуальной документации площадки, они меняются чаще, чем выходят статьи. Ключи — в .settings.php или переменные окружения, не в коде и не в свойствах инфоблока.
- Поставьте таймаут на каждый HTTP-запрос. Запрос без таймаута при недоступной площадке превращает воркер в зависший процесс, а их накапливается столько, сколько запусков успел сделать крон.
- Повторы — только с экспоненциальной паузой и ограничением попыток. Поле
ATTEMPTSиNEXT_RUNв задаче, после 5–7 неудач задача уходит в разбор человеком. Бесконечный ретрай при ответе 429 выглядит для площадки как атака. - Повторять можно не всё. Отправка остатка идемпотентна: отправили дважды — ничего не случилось. Создание отгрузки или подтверждение заказа — нет. Для таких вызовов нужен ключ идемпотентности*, либо проверка состояния на площадке перед повтором.
- Лимиты запросов читайте в документации, а не выводите опытом. Они разные для разных методов и меняются. В коде заложите настраиваемую паузу между запросами, чтобы менять её без релиза.
Эксплуатация
- Снимите агенты с хитов. Для продакшена это обязательный пункт:
define("BX_CRONTAB_SUPPORT", true);в/bitrix/php_interface/dbconn.phpи запуск штатного скрипта по расписанию:
Точный путь к PHP и к корню сайта свой, порядок настройки описан в документации 1С-Битрикс.*/1 * * * * /usr/bin/php -f /home/bitrix/www/bitrix/php_interface/cron_events.php - Защититесь от параллельного запуска. Один обмен длится дольше минуты, крон запустит второй. Нужна блокировка: файловый lock или
GET_LOCKв MySQL. - Логируйте запрос и ответ целиком, с ротацией. Без тела ответа спор с поддержкой площадки неразрешим. Маскируйте ключи в логах.
- Сделайте выключатель. Один флаг в настройках модуля, который останавливает отправку, не останавливая сайт. Он понадобится в первый же инцидент.
- Поставьте алерт на тишину. Мониторить надо не ошибки, а отсутствие успешных обменов: «нет успешной отправки остатков более 30 минут». Самые дорогие инциденты проходят вообще без ошибок в логе.
Когда какой подход выбирать
Критерий простой: считайте стоимость одной отмены по вине продавца и количество SKU.
- До 500 SKU, одна площадка, обычные сроки отгрузки — готовый модуль. Свою интеграцию здесь нечем окупить.
- Две и больше площадок, стандартный ассортимент — внешний сервис. Вы покупаете чужую работу по поддержке трёх меняющихся API.
- Склад один и общий с офлайном, оборачиваемость высокая — своя интеграция через очередь. Здесь задержка остатка стоит денег и рейтинга, а управлять ей можно только самому.
- Синхронные вызовы на событиях — допустимы для одного случая: уведомить площадку о чём-то некритичном, когда потеря события ничего не стоит. В остальных ситуациях это мина.
Что ломается первым
По порядку появления после запуска: остатки отстают из-за агентов на хитах; обмен с 1С перезаписывает цены, а интеграция не узнаёт об этом, потому что события не сработали; админка начинает тормозить на сохранении заказа, потому что обработчик ждёт ответа площадки; задачи в очереди копятся молча, так как алерт стоит на ошибки, а не на отсутствие успехов; после обновления модуля меняется состав параметров события, и обработчик тихо перестаёт вызываться.
Отдельно: права файлов и доступ к интернету с сервера. На многих хостингах исходящие соединения с боевого сервера фильтруются, и интеграция, которая работала с локальной машины разработчика, в проде не открывает соединение вообще.
Что делать дальше
Соберите нагрузочный прогон до запуска: выгрузите полный каталог в тестовый кабинет площадки и замерьте, сколько это заняло и сколько запросов потратило. Из этих двух чисел выводится реальный интервал синхронизации, а не желаемый. Дальше настройте один дашборд с тремя показателями: время с последней успешной отправки остатков, число задач в статусе ошибки и средняя задержка между изменением остатка в Битриксе и его появлением на площадке. Этот третий показатель и есть качество вашей интеграции.
Маппинг характеристик под требования карточек каждой площадки, контентная часть и продвижение — отдельная тема, здесь речь только о транспорте и данных.
* Ключ идемпотентности — уникальный идентификатор операции, который клиент передаёт вместе с запросом. Если запрос придёт повторно с тем же ключом, сервер не создаст вторую сущность, а вернёт результат первой. Поддержка и имя такого ключа зависят от конкретного API площадки.
* FBS и FBO — схемы работы с маркетплейсом: FBS означает отгрузку со своего склада по заказу, FBO — продажу с товара, заранее переданного на склад площадки. Для FBS интеграция обязана держать остатки в актуальном состоянии постоянно, для FBO остатками распоряжается площадка.
Карточки для маркетплейсов: Таблица товаров и папка фотографий на входе — комплект слайдов и описаний на выходе, по требованиям Wildberries и Ozon.
Спросить за 5 ₽Источники: 1С-Битрикс: документация по API ядра D7, Ozon Seller API: документация для разработчиков
Частые вопросы
У меня Битрикс другой версии, примеры подойдут?
Можно обойтись без очереди и просто отправлять данные из обработчика события?
Почему агент синхронизации не запускается по расписанию?
Что делать, если площадка отвечает 429 и обмен встал?
Как не получить двойную продажу, если склад общий с офлайн-магазином?
Интеграция работала с локальной машины, а на проде соединение не открывается. Почему?
Готовый модуль из Маркетплейса или своя разработка?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.