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

URL: https://dmeshcheryakov.ru/blog/bitrix-1c-orders-exchange-back/
Раздел: 1С-Битрикс
Теги: 1С-Битрикс, Интеграции, E-commerce, XML
Опубликовано: 2026-10-30
Обновлено: 2026-10-30
Автор: Дмитрий Мещеряков (https://dmeshcheryakov.ru)

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

Каталог из 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](/blog/bitrix-1c-exchange-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С](/blog/bitrix-1c-custom-fields-mapping).

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

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

Ищем последовательности `query` → `query` без промежуточного `success`. Общий порядок разбора логов обмена описан в статье про [отладку обмена](/blog/bitrix-1c-exchange-debug).

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

Если у элемента пустой или изменённый `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С отстаёт от сайта, и без явного соответствия обмен будет двигать заказы назад по воронке.

**Обратное направление — половина задачи, которую регулярно не делают.** Проверяется одной командой в логе.

И наблюдение, которым стоит закончить разбор обмена целиком. Каталог и заказы ломаются по-разному не потому, что устроены по-разному — протокол один и тот же. Разница в том, кто замечает поломку. Ошибку в каталоге видит покупатель и молча уходит, ошибку в заказах видит менеджер и сразу приходит к вам. Поэтому обмен заказами обычно работает лучше — не потому, что его аккуратнее настроили, а потому, что у него есть кому жаловаться.