Интеграция 1С и сайта: кто должен быть клиентом, а кто сервером при обмене данными?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При проектировании обмена данными между интернет-магазином и учетной системой 1С разработчики часто сталкиваются с принципиальным архитектурным спором: кто должен выступать инициатором соединения? С одной стороны, веб-разработчики предпочитают отдавать данные по запросу (модель Pull), чтобы не нагружать сайт лишней логикой очередей и повторных отправк. С другой стороны, разработчики 1С настаивают на событийной модели (модель Push), когда сайт мгновенно передает новые заказы на HTTP-сервис 1С, аргументируя это требованием «минимальной задержки» и снижением бесполезной нагрузки на веб-сервер. В этой статье мы подробно проанализируем обе модели, разберем их сильные и слабые стороны, а также рассмотрим компромиссные и наиболее надежные варианты реализации обмена.

Модель №1: Pull-модель (1С опрашивает сайт по расписанию)

В этой схеме веб-сайт выступает в роли пассивного сервера, предоставляющего GET-эндпоинт (API) для получения списка новых заказов. 1С выступает клиентом: она с определенной периодичностью (например, каждые 20 секунд или раз в минуту) отправляет HTTP-запросы к сайту, забирает накопившиеся заказы и помечает их как полученные.

Преимущества Pull-модели:

  1. Безопасность и закрытый контур 1С. База 1С чаще всего развернута внутри корпоративной сети за NAT и брандмауэром. При Pull-модели инициатором сетевого соединения всегда является 1С. Системным администраторам не нужно «публиковать» базу 1С наружу, открывать порты в глобальный интернет и настраивать веб-серверы (IIS/Apache) для приема внешних запросов. Это минимизирует риски сетевых атак на учетную систему.
  2. Простота реализации на стороне сайта. Веб-программисту достаточно написать простой GET-метод, отдающий JSON/XML-пакет с новыми заказами. Ему не нужно заботиться о доступности 1С в режиме 24/7 и писать сложные механизмы повторной отправки данных при сетевых сбоях.
  3. Контроль нагрузки на 1С. Учетная система сама решает, когда ей забирать данные. Если в 1С в данный момент выполняется тяжелый расчет себестоимости или закрытие месяца, регламентное задание обмена можно временно приостановить, чтобы не перегружать сервер баз данных.

Недостатки Pull-модели:

  1. Паразитный трафик и высокая нагрузка на сайт. Опрос сайта каждые 20 секунд порождает огромное количество «холостых» запросов (более 4300 запросов в сутки), в ходе которых сайт будет отдавать пустой ответ, тратя ресурсы процессора и оперативной памяти на инициализацию фреймворка базы данных веб-ресурса.
  2. Задержка в получении данных. Если интервал опроса увеличить до 5-10 минут для снижения нагрузки, теряется оперативность. Менеджер в 1С увидит заказ со значительным опозданием, что критично для экспресс-доставок или бронирования дефицитных товаров.

Модель №2: Push-модель (Сайт отправляет вебхуки в 1С)

В этой схеме роли меняются: сайт при создании или изменении заказа на стороне клиента мгновенно инициирует POST-запрос на опубликованный HTTP-сервис 1С. База 1С выступает в роли веб-сервера, принимающего входящие пакеты данных.

Преимущества Push-модели:

  1. Работа в режиме реального времени (Real-Time). Заказ появляется в 1С через доли секунды после того, как покупатель нажал кнопку «Оформить заказ» на сайте. Это идеальное решение для высоконагруженных и быстрых b2c-продаж.
  2. Отсутствие «холостых» запросов. Трафик генерируется исключительно тогда, когда происходит реальное событие (создание или изменение статуса заказа).

Недостатки Push-модели:

  1. Необходимость организации очереди на сайте. Сервер 1С может быть временно недоступен (обновление конфигурации, перезапуск службы SQL, кратковременный сбой сети). Чтобы заказы не терялись, веб-разработчик обязан спроектировать надежную очередь отправки. Если HTTP-сервис 1С вернул ошибку или таймаут, сайт должен сохранить заказ локально и пытаться отправить его повторно по экспоненциальному тайм-ауту.
  2. Уязвимость инфраструктуры 1С. Публикация HTTP-сервисов 1С в открытый доступ требует жестких мер безопасности: настройки реверс-прокси (nginx), SSL-сертификатов, авторизации по токенам и защиты от DDoS-атак, чтобы злоумышленники не смогли заблокировать работу всей ERP-системы предприятия.

Компромиссный вариант: Гибридный подход «Ping-and-Pull»

Если внедрение полноценной Push-модели пугает веб-разработчика из-за необходимости писать отказоустойчивую очередь тяжелых транзакций, а Pull-модель не устраивает 1С-ника из-за частого «холостого» опроса, мы рекомендуем использовать гибридный паттерн «Уведомление и забор» (Ping-and-Pull).

Проанализируем шаги этого процесса:

  1. Покупатель оформляет заказ на сайте.
  2. Сайт мгновенно отправляет в 1С ультракороткий POST-запрос (вебхук), содержащий только уникальный идентификатор заказа: {"event": "new_order", "id": "12345"}.
  3. Этот запрос обрабатывается HTTP-сервисом 1С мгновенно, так как он не содержит тяжелых данных и не требует проведения документов.
  4. 1С принимает сигнал, регистрирует этот ID в своей базе и запускает асинхронное фоновое задание, которое идет на сайт по GET-методу и забирает полную информацию именно по заказу с ID "12345".

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

Практическая реализация асинхронного приема заказов в 1С

При реализации Push-модели крайне важно, чтобы входящие HTTP-запросы обрабатывались системой 1С максимально быстро. Если при получении JSON-пакета 1С начнет синхронно создавать контрагента, искать номенклатуру, рассчитывать скидки и проводить документ ЗаказКлиента, веб-сервер быстро исчерпает свободные потоки, и сайт начнет получать ошибки 504 Gateway Timeout.

Рассмотрим правильную архитектуру обработки на стороне 1С: входящий запрос должен лишь записывать сырые данные JSON в буферный регистр сведений, после чего сразу возвращать сайту ответ 202 Accepted. Разбор буфера и создание документов будут происходить асинхронно в фоновом режиме.

Ниже представлен пример кода HTTP-сервиса 1С для приема заказов с проверкой на дубликаты (обеспечение свойства идемпотентности API):


// Обработчик метода POST HTTP-сервиса "ПринятьЗаказ"
Функция ДобавитьЗаказ(Запрос)
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    
    // Получаем тело запроса в виде строки JSON
    ТелоСтрокой = Запрос.ПолучитьТелоКакСтроку("UTF-8");
    
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ТелоСтрокой);
    ДанныеЗаказа = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    
    // Извлекаем уникальный идентификатор заказа на сайте
    IDЗаказаНаСайте = ДанныеЗаказа.id;
    
    Если ПустаяСтрока(IDЗаказаНаСайте) Тогда
        Ответ.КодСостояния = 400; // Bad Request
        Ответ.УстановитьТелоИзСтроки("{""error"":""Не указан ID заказа""}", "UTF-8");
        Возврат Ответ;
    КонецЕсли;
    
    // Проверяем, не получали ли мы этот заказ ранее (идемпотентность)
    ЗапросДублей = Новый Запрос;
    ЗапросДублей.Текст = 
        "ВЫБРАТЬ Первые 1
        |   Очередь.ИдентификаторЗаказа КАК ИдентификаторЗаказа
        |ИЗ
        |   РегистрСведений.ОчередьЗаказовСайта КАК Очередь
        |ГДЕ
        |   Очередь.ИдентификаторЗаказа = &IDЗаказа";
    ЗапросДублей.УстановитьПараметр("IDЗаказа", IDЗаказаНаСайте);
    
    Если Не ЗапросДублей.Выполнить().Пустой() Тогда
        // Заказ уже был успешно принят ранее, возвращаем статус 208 Already Reported
        Ответ.КодСостояния = 208;
        Ответ.УстановитьТелоИзСтроки("{""status"":""Заказ уже находится в обработке""}", "UTF-8");
        Возврат Ответ;
    КонецЕсли;
    
    // Записываем JSON в буферную таблицу (Регистр сведений) для последующей обработки
    МенеджерЗаписи = РегистрыСведений.ОчередьЗаказовСайта.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.ИдентификаторЗаказа = IDЗаказаНаСайте;
    МенеджерЗаписи.ДатаПолучения       = ТекущаяДатаСеанса();
    МенеджерЗаписи.ТелоJSON            = ТелоСтрокой;
    МенеджерЗаписи.Обработан           = Ложь;
    
    Попытка
        МенеджерЗаписи.Записать(Истина);
        
        Ответ.КодСостояния = 202; // Accepted (Принято к обработке)
        Ответ.УстановитьТелоИзСтроки("{""status"":""Заказ успешно помещен в очередь""}", "UTF-8");
    Исключение
        Ответ.КодСостояния = 500; // Internal Server Error
        Ответ.УстановитьТелоИзСтроки("{""error"":""Ошибка записи в базу данных 1С""}", "UTF-8");
    КонецПопытки;
    
    Возврат Ответ;
    
КонецФункции

Для разбора накопленной очереди заказов настроим регламентное задание 1С, которое будет запускать процедуру фоновой обработки с периодичностью, например, раз в 30 секунд. Проанализируем пример кода этой процедуры:


// Процедура выполняется в фоновом задании по расписанию
Процедура ОбработатьОчередьЗаказов() Экспорт
    
    // Выбираем необработанные заказы из буфера
    ЗапросОчереди = Новый Запрос;
    ЗапросОчереди.Текст = 
        "ВЫБРАТЬ
        |   Очередь.ИдентификаторЗаказа КАК IDЗаказа,
        |   Очередь.ТелоJSON КАК ТелоJSON
        |ИЗ
        |   РегистрСведений.ОчередьЗаказовСайта КАК Очередь
        |ГДЕ
        |   Очередь.Обработан = ЛОЖЬ";
    
    Результат = ЗапросОчереди.Выполнить();
    Если Результат.Пустой() Тогда
        Возврат;
    КонецЕсли;
    
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл
        
        НачатьТранзакцию();
        Попытка
            // Читаем JSON данные конкретного заказа
            Чтение = Новый ЧтениеJSON;
            Чтение.УстановитьСтроку(Выборка.ТелоJSON);
            ДанныеЗаказа = ПрочитатьJSON(Чтение);
            Чтение.Закрыть();
            
            // Создаем новый документ "Заказ клиента"
            НовыйЗаказ = Документы.ЗаказКлиента.СоздатьДокумент();
            НовыйЗаказ.Дата = ТекущаяДата();
            НовыйЗаказ.ИдентификаторСайта = Выборка.IDЗаказа;
            
            // Здесь выполняется бизнес-логика: поиск контрагента, заполнение ТЧ "Товары"
            // ЗаполнитьРеквизитыЗаказа(НовыйЗаказ, ДанныеЗаказа);
            
            НовыйЗаказ.Записать(РежимЗаписиДокумента.Проведение);
            
            // Помечаем запись в регистре очереди как успешно обработанную
            МенеджерЗаписи = РегистрыСведений.ОчередьЗаказовСайта.СоздатьМенеджерЗаписи();
            МенеджерЗаписи.ИдентификаторЗаказа = Выборка.IDЗаказа;
            МенеджерЗаписи.Прочитать();
            Если МенеджерЗаписи.Выбран() Тогда
                МенеджерЗаписи.Обработан = Истина;
                МенеджерЗаписи.ДатаОбработки = ТекущаяДатаСеанса();
                МенеджерЗаписи.Записать(Истина);
            КонецЕсли;
            
            ЗафиксироватьТранзакцию();
            
        Исключение
            ОтменитьТранзакцию();
            
            // Логируем ошибку для последующего разбора администратором
            ЗаписатьЗаписьВЖурналРегистрации("ОбменССайтом.ОшибкаОбработкиЗаказа",
                УровеньЖурналаРегистрации.Ошибка,
                ,
                ,
                "Ошибка при обработке заказа " + Выборка.IDЗаказа + ": " + ОписаниеОшибки());
                
            // Сдвигаем дату или увеличиваем счетчик ошибок записи, чтобы временно пропустить проблемный заказ
            ПропуститьПроблемныйЗаказ(Выборка.IDЗаказа, ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;
    
КонецПроцедуры

Подводя итоги

В споре о том, кто должен выступать инициатором обмена, нет однозначно неправой стороны — всё зависит от требований к скорости, безопасности и доступного бюджета разработки.

Если во главу угла ставится максимальная скорость получения заказов без создания паразитной нагрузки на серверы — 1С-программист прав: необходимо настраивать событийный Push-обмен. Но для его безопасной и надежной работы веб-разработчику потребуется реализовать буферную очередь отправки на сайте, а 1С-специалисту — опубликовать отказоустойчивый асинхронный HTTP-сервис с гарантированной защитой от дублирования транзакций.

← На главную