Заказы обратно в 1С: статусы, оплаты, отгрузки

Как работает обратное направление обмена: пять команд type=sale, почему заказ уходит дважды и что делать с товарами, которых нет в номенклатуре 1С.

Дмитрий Мещеряков
Дмитрий Мещеряков
📅 30 октября 2026 г.📖 7 мин чтения

Каталог из 1С на сайт — направление, которое настраивают все. Заказы с сайта в 1С — направление, которое настраивают один раз и вспоминают о нём, когда менеджер сообщает, что в учётной системе появилось два одинаковых заказа на одного покупателя.

Механика здесь та же, что и в каталоге, но набор команд другой, а ошибки — совсем другого сорта. Каталог ломается тихо и портит витрину. Заказы ломаются громко и портят учёт.

Эта статья закрывает разбор обмена с 1С обратным направлением: что уходит, по каким командам и почему уходит дважды.

Что такое обмен заказами

Обмен заказами — это отдельный сценарий того же протокола, работающий через тот же скрипт 1c_exchange.php, но с параметром type=sale вместо type=catalog. Инициатор, как и в каталоге, — 1С: она приходит и забирает, сайт только отвечает.

Направлений на самом деле два, и их часто путают:

НаправлениеКомандыЧто происходит
Сайт → 1Сquery, success1С забирает новые заказы
1С → сайтfile, import1С сообщает об оплатах и отгрузках

Второе направление настраивается отдельно и на многих проектах не настроено вовсе — именно поэтому оплаченный в 1С заказ на сайте остаётся неоплаченным.

Пять команд

text
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 с заказами, которые ещё не выгружались:

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С не подтвердила приём, считать заказ доставленным нельзя.

Но у неё есть обратная сторона:

text
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 между ними.

bash
grep "1c_exchange" /var/log/nginx/access.log \
  | grep "type=sale" \
  | awk '{print $4, $7, $9}' \
  | tail -40

Ищем последовательности query → query без промежуточного success. Общий порядок разбора логов обмена описан в статье про отладку обмена.

Товар в заказе не сопоставлен

Если у элемента пустой или изменённый XML_ID, товар уедет в 1С строкой без ссылки на номенклатуру. Менеджер будет подбирать его руками, а при большом потоке — не будет, и заказ повиснет.

Проверять это нужно до выгрузки, а не после:

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

Заказ не уходит вообще

Проверяется по порядку:

bash
# 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С половина отгружена. Личный кабинет покупателя показывает неверную картину, письма о статусе не отправляются, а менеджеры отвечают на звонки «где мой заказ» вручную.

Проверка занимает минуту:

bash
# Приходили ли за последние сутки запросы на загрузку заказов в обратную сторону
grep "type=sale" /var/log/nginx/access.log \
  | grep -E "mode=(file|import)" \
  | wc -l

Ноль при работающей выгрузке заказов означает, что обратное направление не настроено.

Что проверить при настройке

Порядок, который стоит пройти один раз и записать в документацию проекта:

  1. Идемпотентность в 1С по номеру заказа. Единственная защита от дублей.
  2. Все товары каталога имеют XML_ID. Запрос выше, в чек-лист после каждого обмена каталогом.
  3. Таблица соответствия статусов заведена явно и согласована с бизнесом.
  4. Обратное направление настроено — оплаты и отгрузки доезжают до сайта.
  5. Дата начала выгрузки в настройках не отсекает нужные заказы.
  6. Свойства заказа сопоставлены — телефон, адрес, комментарий должны доехать до менеджера.

Итоги

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