Каталог из 1С на сайт — направление, которое настраивают все. Заказы с сайта в 1С — направление, которое настраивают один раз и вспоминают о нём, когда менеджер сообщает, что в учётной системе появилось два одинаковых заказа на одного покупателя.
Механика здесь та же, что и в каталоге, но набор команд другой, а ошибки — совсем другого сорта. Каталог ломается тихо и портит витрину. Заказы ломаются громко и портят учёт.
Эта статья закрывает разбор обмена с 1С обратным направлением: что уходит, по каким командам и почему уходит дважды.
Что такое обмен заказами
Обмен заказами — это отдельный сценарий того же протокола, работающий через тот же скрипт 1c_exchange.php, но с параметром type=sale вместо type=catalog. Инициатор, как и в каталоге, — 1С: она приходит и забирает, сайт только отвечает.
Направлений на самом деле два, и их часто путают:
| Направление | Команды | Что происходит |
|---|---|---|
| Сайт → 1С | query, success | 1С забирает новые заказы |
| 1С → сайт | file, import | 1С сообщает об оплатах и отгрузках |
Второе направление настраивается отдельно и на многих проектах не настроено вовсе — именно поэтому оплаченный в 1С заказ на сайте остаётся неоплаченным.
Пять команд
1. GET ?type=sale&mode=checkauth → авторизация
2. GET ?type=sale&mode=init → параметры
3. GET ?type=sale&mode=query → Битрикс отдаёт XML заказов
4. GET ?type=sale&mode=success → 1С подтверждает приём
5. POST ?type=sale&mode=file + GET ?type=sale&mode=import → обратная загрузкаПервые две — те же, что в каталоге, механика разобрана в статье про протокол обмена по CommerceML. Интерес представляют третья и четвёртая.
query: Битрикс отдаёт заказы
В ответ приходит XML с заказами, которые ещё не выгружались:
<КоммерческаяИнформация ВерсияСхемы="2.05" ДатаФормирования="2026-10-30">
<Документ>
<Ид>1204</Ид>
<Номер>1204</Номер>
<Дата>2026-10-30</Дата>
<ХозОперация>Заказ товара</ХозОперация>
<Роль>Продавец</Роль>
<Валюта>RUB</Валюта>
<Сумма>14970</Сумма>
<Контрагенты>
<Контрагент>
<Ид>user-4821</Ид>
<Наименование>Иванов Иван Иванович</Наименование>
</Контрагент>
</Контрагенты>
<Товары>
<Товар>
<Ид>f4e2c1a9-...</Ид>
<Наименование>Смеситель для кухни</Наименование>
<ЦенаЗаЕдиницу>4990</ЦенаЗаЕдиницу>
<Количество>3</Количество>
<Сумма>14970</Сумма>
</Товар>
</Товары>
</Документ>
</КоммерческаяИнформация>Обратите внимание на <Ид> товара: это тот же GUID, что приезжал в каталоге. Опознание работает в обе стороны и держится на XML_ID — со всеми следствиями, разобранными в статье про маппинг свойств из 1С.
success: подтверждение приёма
Вот команда, вокруг которой строится вся надёжность механизма — и все его проблемы.
Заказ помечается выгруженным не в момент отдачи XML, а по команде success. Логика правильная: пока 1С не подтвердила приём, считать заказ доставленным нельзя.
Но у неё есть обратная сторона:
10:00:00 1С запрашивает query → Битрикс отдаёт заказ №1204
10:00:03 1С создаёт заказ у себя
10:00:04 обрыв связи, success не отправлен
10:15:00 следующий обмен: query → Битрикс снова отдаёт №1204
10:15:03 1С создаёт заказ у себя ещё раз ← дубльСайт вёл себя правильно на каждом шаге. Подтверждения не было — значит, заказ не доставлен — значит, отдаём снова.
Защита от дублей возможна только на стороне 1С. Сайт не может отличить «1С не получила заказ» от «получила, но не подтвердила»: снаружи оба случая выглядят одинаково — отсутствием команды success. Единственное надёжное решение — идемпотентность в 1С: перед созданием документа проверять, нет ли уже заказа с таким номером. Если разработчик 1С говорит, что это не нужно, покажите ему сценарий выше.
Что ломается
Заказ ушёл дважды
Разобрано выше. Проверяется по логу: два запроса query без success между ними.
grep "1c_exchange" /var/log/nginx/access.log \
| grep "type=sale" \
| awk '{print $4, $7, $9}' \
| tail -40Ищем последовательности query → query без промежуточного success. Общий порядок разбора логов обмена описан в статье про отладку обмена.
Товар в заказе не сопоставлен
Если у элемента пустой или изменённый XML_ID, товар уедет в 1С строкой без ссылки на номенклатуру. Менеджер будет подбирать его руками, а при большом потоке — не будет, и заказ повиснет.
Проверять это нужно до выгрузки, а не после:
-- Позиции заказов за сутки, товары которых не имеют XML_ID.
-- Такие поедут в 1С без привязки к номенклатуре
SELECT
b.ORDER_ID,
b.PRODUCT_ID,
b.NAME,
e.XML_ID
FROM b_sale_basket b
JOIN b_sale_order o ON o.ID = b.ORDER_ID
LEFT JOIN b_iblock_element e ON e.ID = b.PRODUCT_ID
WHERE o.DATE_INSERT > DATE_SUB(NOW(), INTERVAL 1 DAY)
AND (e.XML_ID IS NULL OR e.XML_ID = '')
LIMIT 50;Пустой результат — всё сопоставлено. Непустой — вы уже знаете, какие заказы вызовут вопросы, и можете починить до того, как их зададут.
Статус затёрся
Заказ был «Собран», после обмена стал «Принят». Причина — 1С прислала своё значение статуса, а таблицы соответствий между статусами двух систем нет или она неполна.
Опасность здесь в направлении затирания: 1С обычно отстаёт от сайта, потому что менеджер меняет статус в 1С позже, чем это делает автоматика сайта. В результате обмен регулярно откатывает заказы назад по воронке.
Заводите соответствие статусов явной таблицей, а не по совпадению названий. «Оплачен» на сайте и «Оплачен» в 1С могут означать разные вещи: на сайте — что пришло уведомление от платёжной системы, в 1С — что деньги дошли до расчётного счёта. Между этими событиями проходят дни. Явная таблица заставляет проговорить такие расхождения на этапе настройки, а не обнаруживать их в отчётах.
Заказ не уходит вообще
Проверяется по порядку:
# 1. Приходила ли 1С за заказами
grep "type=sale" /var/log/nginx/access.log | tail -20
# 2. Что Битрикс отдаёт по query — руками, с сохранением куки
curl -s -c /tmp/sale.jar -u "exchange1c:password" \
"https://site.ru/bitrix/admin/1c_exchange.php?type=sale&mode=checkauth"
curl -s -b /tmp/sale.jar -c /tmp/sale.jar \
"https://site.ru/bitrix/admin/1c_exchange.php?type=sale&mode=query" \
| head -60Не отправляйте mode=success при ручной проверке. Эта команда пометит все отданные заказы выгруженными, и настоящий обмен их больше не увидит — заказы просто не доедут до 1С, а вы будете искать причину в другом месте. Запрос query безопасен и ничего не меняет, success меняет состояние необратимо.
Если query возвращает пустой документ, а заказы на сайте есть — смотрите настройки выгрузки. Типичные причины: заказ не подходит под фильтр по статусу, по способу оплаты или по дате начала выгрузки, выставленной при настройке обмена и давно забытой.
Обратное направление: оплаты и отгрузки
Вторая половина обмена заказами — то, как 1С сообщает сайту, что заказ оплачен, собран или отгружен. Идёт она командами file и import с тем же type=sale: 1С загружает XML с изменёнными заказами, Битрикс их разбирает.
Настраивается это отдельно, и вот здесь чаще всего обнаруживается пропуск. Симптом характерный: на сайте заказы вечно «в обработке», хотя в 1С половина отгружена. Личный кабинет покупателя показывает неверную картину, письма о статусе не отправляются, а менеджеры отвечают на звонки «где мой заказ» вручную.
Проверка занимает минуту:
# Приходили ли за последние сутки запросы на загрузку заказов в обратную сторону
grep "type=sale" /var/log/nginx/access.log \
| grep -E "mode=(file|import)" \
| wc -lНоль при работающей выгрузке заказов означает, что обратное направление не настроено.
Что проверить при настройке
Порядок, который стоит пройти один раз и записать в документацию проекта:
- Идемпотентность в 1С по номеру заказа. Единственная защита от дублей.
- Все товары каталога имеют
XML_ID. Запрос выше, в чек-лист после каждого обмена каталогом. - Таблица соответствия статусов заведена явно и согласована с бизнесом.
- Обратное направление настроено — оплаты и отгрузки доезжают до сайта.
- Дата начала выгрузки в настройках не отсекает нужные заказы.
- Свойства заказа сопоставлены — телефон, адрес, комментарий должны доехать до менеджера.
Итоги
Заказы уходят по подтверждению, а не по отдаче. Пока нет success, заказ считается невыгруженным — отсюда и надёжность механизма, и дубли при обрывах.
Дубли лечатся только в 1С. Сайт принципиально не может отличить потерянный заказ от неподтверждённого.
XML_ID работает в обе стороны. Товар без него не существует для 1С ни в каталоге, ни в заказе.
Статусы затираются в сторону отката. 1С отстаёт от сайта, и без явного соответствия обмен будет двигать заказы назад по воронке.
Обратное направление — половина задачи, которую регулярно не делают. Проверяется одной командой в логе.
И наблюдение, которым стоит закончить разбор обмена целиком. Каталог и заказы ломаются по-разному не потому, что устроены по-разному — протокол один и тот же. Разница в том, кто замечает поломку. Ошибку в каталоге видит покупатель и молча уходит, ошибку в заказах видит менеджер и сразу приходит к вам. Поэтому обмен заказами обычно работает лучше — не потому, что его аккуратнее настроили, а потому, что у него есть кому жаловаться.
Частые вопросы
Как заказы из Битрикса попадают в 1С?
1С сама забирает их запросом к /bitrix/admin/1c_exchange.php с параметром type=sale. Последовательность: checkauth для авторизации, init для параметров, query — Битрикс отдаёт XML с невыгруженными заказами, success — 1С подтверждает, что приняла их. Сайт заказы никуда не отправляет, он только отвечает на запрос.
Почему заказ выгрузился в 1С дважды?
Потому что 1С получила XML по команде query, но не прислала success — оборвалась связь, упала обработка на стороне 1С или истёк таймаут. Заказ остался помеченным как невыгруженный и попал в следующую выборку, а в 1С к этому моменту уже был создан из первой попытки. Защита — идемпотентность на стороне 1С по номеру заказа, потому что со стороны сайта отличить повторный запрос от первого невозможно.
Что делать, если товар в заказе не сопоставлен с номенклатурой 1С?
Такой товар уедет в заказ строкой без ссылки на номенклатуру, и менеджеру придётся подбирать его руками. Причина — пустой или изменённый XML_ID элемента: 1С опознаёт товары только по GUID. Проверять стоит до выгрузки, отдельным запросом по позициям заказов за последние сутки.
Как передать в 1С информацию об оплате заказа?
Признак оплаты уходит в XML заказа вместе с остальными его реквизитами, а обратное движение — когда 1С сообщает сайту, что заказ оплачен или отгружен, — идёт через загрузку файла с заказами в обратном направлении, командами file и import с тем же type=sale. То есть обмен заказами двусторонний, и вторая половина настраивается отдельно от первой.
Почему после обмена у заказа сбросился статус?
Потому что 1С прислала своё значение статуса, а сопоставление статусов между системами не настроено или настроено частично. Битрикс применит то, что получил, и статус, выставленный менеджером на сайте, будет затёрт. Это одна из причин заводить статусы сайта и 1С как явную таблицу соответствий, а не полагаться на совпадение названий.