Коллеги, мы с вами рассмотрим актуальную и довольно сложную задачу — интеграцию 1С:УНФ, работающей в облаке 1cfresh.com, с внешним бэкендом (например, на Python). Наша цель — обеспечить отправку POST-запроса в формате JSON на внешний сервер сразу после записи документа «Заказ покупателя» в 1С. Это позволит реализовать Push-обмен (Webhooks), при котором данные передаются мгновенно, без задержек, связанных с периодическим опросом.
Однако, облачная платформа 1С:Фреш имеет жесткую политику безопасности, которая ограничивает исходящие соединения. Это вызывает главный вопрос: возможно ли через расширение отправлять запросы на произвольный внешний URL, который пользователь может задавать самостоятельно? Или же Фреш разрешает запросы только на те домены, которые были заранее жестко прописаны и прошли аудит?
Давайте разберем эту ситуацию подробно, рассмотрим ограничения и выясним, какие решения предлагает платформа 1С, а также какие архитектурные подходы позволят нам реализовать задуманное.
Прежде всего, важно понимать, что все расширения конфигурации в 1С:Фреш работают в так называемом безопасном режиме (Safe Mode). Это ключевое понятие, определяющее, что расширение может и не может делать.
Из вышесказанного следует, что напрямую отправить вебхук на произвольный внешний URL из серверного кода расширения, работающего во Фреше, не представляется возможным без дополнительных архитектурных решений.
Если нам нужна возможность отправки данных на URL, который пользователь может менять динамически, и при этом сохранить надежность серверного Push-обмена, то на практике применяется схема с использованием промежуточного сервера, или шлюза (Middleware).
Рассмотрим шаги реализации:
gateway.ваша-компания.ru).Это единственный надежный способ реализовать «универсальный» вебхук-отправитель для тиражного решения во Фреше, где конечный адрес получателя может быть задан пользователем.
При реализации вебхука через расширение (серверный код) крайне важно учитывать момент отправки запроса. Мы не можем отправлять HTTP-запрос непосредственно внутри транзакции записи документа по нескольким причинам:
Правильный паттерн для 1С:Фреш выглядит следующим образом:
ПриЗаписи (или ПриЗаписиНаСервере для управляемых форм) для документа «Заказ покупателя». Эта подписка должна выполняться после записи, но не блокировать ее.Пример структуры кода для отправки запроса (этот код будет выполняться в регламентном задании):
// Предполагаем, что у нас есть структура с данными для отправки
// и целевым URL для промежуточного шлюза.
// Получение данных из очереди (регистра сведений)
СообщениеДляОтправки = ПолучитьСледующееСообщениеИзОчереди();
Если СообщениеДляОтправки <> Неопределено Тогда
ЦелевойАдресШлюза = "gateway.ваша-компания.ru"; // Жестко прописанный и аудированный адрес шлюза
ПортШлюза = 443; // Или 80
// Формируем тело запроса, которое включает данные заказа и *конечный* URL клиента
ДанныеДляШлюза = Новый Структура;
ДанныеДляШлюза.Вставить("ДанныеЗаказа", СообщениеДляОтправки.ДанныеЗаказа); // Данные заказа из очереди
ДанныеДляШлюза.Вставить("КонечныйURL", СообщениеДляОтправки.КонечныйURL); // URL клиента, куда шлюз перешлет
// Преобразуем структуру в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляШлюза);
ТелоЗапросаJSON = ЗаписьJSON.Закрыть();
HTTPСоединение = Новый HTTPСоединение(ЦелевойАдресШлюза, ПортШлюза, , , , 10, Истина); // Истина для HTTPS
HTTPЗапрос = Новый HTTPЗапрос;
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапросаJSON, КодировкаТекста.UTF8, "application/json");
// Добавляем необходимые заголовки, например, для авторизации на шлюзе
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
// HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступаКШлюзу); // Если шлюз требует авторизации
Попытка
HTTPОтвет = HTTPСоединение.Отправить(HTTPЗапрос, "/webhook_forwarder"); // Путь на шлюзе
Если HTTPОтвет.КодСостояния = 200 Тогда
// Успешно отправлено, помечаем сообщение как обработанное
ОбновитьСтатусСообщения(СообщениеДляОтправки, "Отправлено");
Иначе
// Ошибка при отправке, логируем, увеличиваем счетчик попыток
ЗаписатьЖурналРегистрации("Ошибка отправки вебхука: " + HTTPОтвет.СтатусСтрока, УровеньЖурналаРегистрации.Ошибка);
ОбновитьСтатусСообщения(СообщениеДляОтправки, "Ошибка", HTTPОтвет.КодСостояния);
КонецЕсли;
Исключение
// Ошибка HTTP-соединения, логируем
ЗаписатьЖурналРегистрации("Ошибка HTTP-соединения: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
ОбновитьСтатусСообщения(СообщениеДляОтправки, "ОшибкаСоединения");
КонецПопытки;
КонецЕсли;
Помимо серверного Push-обмена через промежуточный шлюз, существуют другие подходы, которые могут быть применены в зависимости от требований к мгновенности и типу обмена (Push или Pull).
В некоторых случаях предлагается делать вызов из клиентского контекста, то есть через код, выполняющийся в браузере пользователя. Это позволяет обойти серверные ограничения 1С:Фреш на whitelisting доменов, так как запрос инициируется браузером.
Однако, у этого подхода есть серьезные недостатки, из-за которых мы стремимся его избегать:
Для задач, где данные требуется не отправлять из 1С, а забирать сторонней системой, существует типовой и широко используемый механизм — протокол OData. Это стандартный способ получения данных из 1С:Фреш баз.
Разберем, как это работает:
Несмотря на простоту реализации, у OData есть один существенный недостаток для нашей задачи: это Pull-обмен. Данные не отправляются мгновенно при записи, а забираются внешним сервисом с определенной задержкой (например, раз в несколько минут). Это не подходит, если требуется мгновенная передача данных сразу после записи «Заказа покупателя».
Платформа 1С предлагает еще один встроенный механизм для реализации событийной модели без использования классических вебхуков — это Система взаимодействия (1С:Dialogs).
Принцип работы:
Этот механизм является легальным и поддерживаемым способом для облачных решений 1С и может быть хорошей альтернативой классическим вебхукам для обеспечения мгновенной доставки уведомлений.
Итак, мы выяснили, что прямая отправка вебхуков из 1С:Фреш на произвольный URL через серверный код расширения невозможна из-за политики безопасности и механизма аудита. Разрешения на исходящие соединения выдаются только для жестко прописанных и аудированных адресов.
Однако, для реализации Push-обмена с динамическим целевым URL, наиболее надежным и рекомендуемым решением является использование промежуточного шлюза (Middleware). В этом случае расширение во Фреше отправляет данные на фиксированный, аудированный шлюз, который затем пересылает их на конечный адрес клиента. При этом критически важно использовать подход с очередью сообщений и регламентным заданием, чтобы избежать блокировок транзакций.
Для извлечения данных из 1С мы всегда можем использовать OData (Pull-модель), а для мгновенных уведомлений без прямого HTTP-вызова — Систему взаимодействия (1С:Dialogs). Клиентский контекст для вебхуков обладает существенными ограничениями и не рекомендуется для надежных интеграций.
Выбирая путь интеграции, мы должны тщательно взвесить требования к мгновенности, надежности и готовности к разработке промежуточных компонентов.