1С и n8n: HTTP-обмен заказами со статусами, retry и дедупликацией ¶
Обновлено: 2026-05-30
Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production.
Проблема: 1С часто становится источником заказов, остатков или статусов, но прямой HTTP-обмен ломается на повторах, ручных перезапусках, временных 5xx и разных форматах номеров документов.
Решение: использовать n8n как безопасный integration layer между 1С и внешними системами: принимать HTTP-события, проверять подпись, строить idempotency key по `external_id`, обновлять CRM/магазин и возвращать 1С понятный ответ.
Проблема: почему HTTP-обмен 1С создает дубли и потерянные статусы ¶
В интеграциях с 1С дубли появляются не потому, что кто-то плохо написал webhook. Обычно причина в бизнес-реальности: пользователь повторно выгрузил документ, регламентное задание перезапустилось, сеть оборвалась после успешной записи, а 1С не получила подтверждение и отправила заказ ещё раз.
Если n8n каждый раз создаёт новую сделку или заказ во внешней системе, бухгалтерия и продажи быстро перестают доверять автоматизации. Надёжный HTTP-обмен должен быть идемпотентным: один `external_id` из 1С приводит к одному бизнес-объекту, а повтор меняет статус или возвращает уже обработанный результат.
Архитектура workflow 1С → n8n → CRM/API ¶
| Нода | Роль | Что проверить |
|---|---|---|
| 1C HTTP service | отправляет заказ или статус | метод POST, JSON, external_id, подпись |
| n8n Webhook | принимает событие от 1С | production URL, timeout, корректный ответ |
| Normalize order | приводит поля к контракту | суммы, НДС, строки товаров, телефоны |
| Idempotency check | ищет обработанный external_id | unique key, статус, retry_count |
| Upsert target system | создаёт/обновляет CRM, сайт или склад | маппинг полей, API ошибки, rate limit |
| Confirm to 1C | возвращает результат обмена | код, message, target_id, повторный ответ |
Для обмена статусами и заказами лучше разделять event types: `order.created`, `order.updated`, `payment.status`, `shipment.status`. Так проще маршрутизировать ошибки и не смешивать разные бизнес-процессы в одном IF-блоке.
Контракт входных данных из 1С ¶
{
"event_type": "order.created",
"external_id": "1c-doc-000184",
"number": "Заказ покупателя 000184",
"date": "2026-05-30T09:45:00+03:00",
"customer": {
"name": "ООО Ромашка",
"inn": "7701000000",
"phone": "+7 (495) 100-20-30"
},
"items": [
{
"sku": "N8N-SETUP",
"name": "Внедрение n8n",
"quantity": 1,
"price": 49000,
"vat": "20%"
}
],
"total": 49000,
"currency": "RUB",
"status": "new"
}
`external_id` — главный ключ. Не используйте номер документа как единственный ID, если в 1С есть разные базы, организации или типы документов с пересекающейся нумерацией.
Code Node: нормализация заказа и idempotency key ¶
const src = $json.body ?? $json;
const eventType = String(src.event_type ?? '').trim();
const externalId = String(src.external_id ?? '').trim();
if (!eventType) throw new Error('Missing event_type from 1C');
if (!externalId) throw new Error('Missing external_id from 1C');
const items = Array.isArray(src.items) ? src.items : [];
if (items.length === 0) throw new Error('Order has no items');
const normalizedItems = items.map((item, index) => {
const quantity = Number(item.quantity ?? 0);
const price = Number(item.price ?? 0);
if (quantity <= 0) throw new Error(`Invalid quantity at line ${index + 1}`);
return {
sku: String(item.sku ?? '').trim(),
name: String(item.name ?? '').trim(),
quantity,
price,
amount: Number((quantity * price).toFixed(2)),
vat: String(item.vat ?? 'none')
};
});
const total = normalizedItems.reduce((sum, item) => sum + item.amount, 0);
const idempotencyKey = `1c:${eventType}:${externalId}`;
return [{
json: {
event_type: eventType,
external_id: externalId,
idempotency_key: idempotencyKey,
order_number: String(src.number ?? externalId),
customer: src.customer ?? {},
items: normalizedItems,
total_calculated: Number(total.toFixed(2)),
total_declared: Number(src.total ?? total),
status: String(src.status ?? 'new'),
received_at: new Date().toISOString()
}
}];
Почему нельзя отвечать 200 до записи idempotency
Если n8n вернёт 200, а потом упадёт до записи external_id в durable storage, 1С будет считать обмен успешным. Сначала сохраняйте idempotency record или результат обработки, затем возвращайте подтверждение.
Готовый workflow JSON: скачать и импортировать ¶
Скачать готовый workflow JSON Скачать тестовый payload
{
"name": "Nodbot - 1C HTTP exchange with idempotency",
"nodes": [
{
"name": "1C Webhook",
"type": "n8n-nodes-base.webhook",
"purpose": "Принять заказ или статус от 1С"
},
{
"name": "Normalize 1C order",
"type": "n8n-nodes-base.code",
"purpose": "Проверить external_id, строки и суммы"
},
{
"name": "Check idempotency",
"type": "n8n-nodes-base.postgres",
"purpose": "Не обработать документ повторно"
},
{
"name": "Upsert CRM or API",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Создать или обновить целевую систему"
},
{
"name": "Write exchange log",
"type": "n8n-nodes-base.postgres",
"purpose": "Сохранить результат, target_id и retry_count"
},
{
"name": "Respond to 1C",
"type": "n8n-nodes-base.respondToWebhook",
"purpose": "Вернуть код, message и target_id"
}
],
"connections": "1C Webhook → Normalize 1C order → Check idempotency → Upsert CRM or API → Write exchange log → Respond to 1C"
}
Пошаговая настройка HTTP-сервиса 1С и webhook n8n ¶
- Опишите контракт JSON с разработчиком 1С: event_type, external_id, customer, items, totals.
- Опубликуйте HTTP-сервис в 1С или настройте регламентную отправку на webhook n8n.
- Импортируйте workflow и добавьте проверку подписи или Basic/Auth token.
- Создайте таблицу exchange_log с unique index по idempotency_key.
- Настройте retry/DLQ для ошибок внешней CRM или API, чтобы 1С не теряла статус.
Тесты перед production для обмена с 1С ¶
curl -X POST "https://YOUR-N8N-DOMAIN/webhook/onec-http-exchange" \
-H "Content-Type: application/json" \
--data @onec-http-exchange-payload.json
- Отправьте один и тот же `external_id` дважды: target object должен остаться один.
- Проверьте заказ без строк и с отрицательным количеством.
- Сымитируйте ошибку внешнего API 500 и проверьте retry/DLQ.
- Отправьте статус по уже созданному заказу и проверьте update, а не create.
- Сравните `total_declared` и `total_calculated` на строках с НДС и округлением.
Production-риски интеграции 1С через HTTP ¶
- Нет стабильного external_id. Повторы из 1С превращаются в новые сделки или заказы.
- Ответ 200 без durable log. 1С считает обмен успешным, хотя downstream API мог упасть.
- Смешаны разные event types. Статус оплаты случайно обрабатывается как новый заказ.
- Сумма не сверяется со строками. Внешняя система получает неправильный total.
- Нет DLQ. Временная ошибка API навсегда теряет документ обмена.
Полезные ссылки и смежные workflow ¶
См. также retry и DLQ для HTTP Request, webhook idempotency to Postgres, idempotency keys и ЮKassa → CRM. Официальные документы: 1C:Enterprise documentation, 1C HTTP services и n8n Webhook node.
Критерии готовности ¶
- У каждого события из 1С есть стабильный external_id.
- Повторный документ не создаёт второй объект во внешней системе.
- Ошибки API уходят в retry/DLQ и видны владельцу интеграции.
- Ответ 1С содержит понятный код, message и target_id.
- Есть журнал обмена с idempotency_key, event_type, status и retry_count.
Nodbot спроектирует HTTP-обмен 1С и n8n: контракт данных, idempotency, retry/DLQ, журнал обмена, мониторинг и безопасный rollout.
Обсудить интеграцию 1С