Как отправить JSON-запрос из веб-клиента 1С к локальному оборудованию или внешнему сайту?

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

При работе в веб-клиенте 1С программисты часто сталкиваются с необходимостью напрямую взаимодействовать с внешними веб-сервисами, API сторонних сайтов или локальным торговым оборудованием (например, ККТ, весы, сканеры), подключенным к компьютеру пользователя по интерфейсу RNDIS или USB. В классическом тонком клиенте эта задача легко решается стандартными серверными вызовами, но в веб-клиенте, работающем непосредственно внутри интернет-браузера, вступают в силу жесткие ограничения безопасности.

В данной статье мы подробно разберем, как обойти эти ограничения, какие современные механизмы предлагает платформа «1С:Предприятие 8.3» для отправки JSON-запросов на клиенте, и как правильно спроектировать архитектуру взаимодействия с локальными устройствами (RNDIS).

Основные сложности при работе из веб-клиента

Прежде чем перейти к программным решениям, выясним причину возникновения сложностей. При исполнении кода на стороне веб-клиента мы полностью подчиняемся правилам «песочницы» браузера. Это накладывает следующие ограничения:

  1. Политика одного источника (CORS — Cross-Origin Resource Sharing): Браузер блокирует любые HTTP/HTTPS запросы к адресам, отличным от домена, на котором запущен сам веб-клиент 1С. Например, если веб-клиент открыт по адресу https://mycompany.ru/unf, а запрос отправляется на локальный адрес устройства http://192.168.137.111, браузер отклонит запрос, если удаленная сторона не вернет специальные CORS-заголовки.
  2. Смешанный контент (Mixed Content): Если ваш веб-клиент работает по защищенному протоколу HTTPS (что является стандартом), современные браузеры заблокируют любые попытки отправить запрос на незащищенный протокол HTTP (например, на локальный IP-адрес ККТ).
  3. Отсутствие синхронных методов: Любые сетевые вызовы в браузере должны выполняться асинхронно, чтобы не «замораживать» интерфейс программы.

Рассмотрим подробнее основные способы решения этих проблем, начиная от штатных асинхронных механизмов платформы и заканчивая интеграционными прослойками.

Решение 1. Использование встроенных асинхронных HTTP-запросов (Платформа 8.3.21+)

Начиная с версии платформы 8.3.21.1302, разработчики «1С» добавили поддержку объектов HTTPСоединение и HTTPЗапрос непосредственно в веб-клиенте. Однако использовать их можно исключительно асинхронно.

Разберем по шагам, как сформировать и отправить асинхронный JSON-запрос в веб-клиенте. Начиная с версии 8.3.23, мы также можем использовать быстрые методы сериализации JSON.

Посмотрим на пример кода, который подготавливает данные и отправляет POST-запрос:


&НаКлиенте
Асинх Процедура ОтправитьДанныеНаУстройствоАсинх()
    
    // Шаг 1. Формируем структуру данных для отправки
    ПараметрыЗапроса = Новый Структура;
    ПараметрыЗапроса.Вставить("Command", "PrintReceipt");
    ПараметрыЗапроса.Вставить("Sum", 1500.50);
    
    // Шаг 2. Сериализуем структуру в строку JSON (доступно в веб-клиенте с 8.3.23)
    СтрокаJSON = ЗаписатьЗначениеJSON(ПараметрыЗапроса);
    
    // Шаг 3. Создаем HTTP-запрос
    Запрос = Новый HTTPЗапрос("/api/v1/execute");
    Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    Запрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеМаркераПоследовательностиБайтов.НеИспользовать);
    
    // Шаг 4. Инициализируем HTTP-соединение (указываем адрес устройства или сервиса)
    // Обратите внимание: адрес должен поддерживать CORS заголовки!
    Соединение = Новый HTTPСоединение("192.168.137.111", 8080);
    
    Попытка
        // Шаг 5. Отправляем запрос асинхронно с помощью оператора Ждать
        Ответ = Ждать Соединение.ОтправитьДляОбработкиАсинх(Запрос);
        
        Если Ответ.КодСостояния = 200 Тогда
            СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
            
            // Парсим ответ обратно в структуру 1С
            Результат = ПрочитатьЗначениеJSON(СтрокаОтвета);
            ПоказатьПредупреждение(, "Запрос выполнен успешно! Ответ устройства: " + Результат.Status);
        Иначе
            ПоказатьПредупреждение(, "Ошибка сервера. Код состояния: " + Ответ.КодСостояния);
        КонецЕсли;
    Исключение
        ИнформацияОбОшибке = ИнформацияОбОшибке();
        ПоказатьПредупреждение(, "Не удалось связаться с устройством: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
    КонецПопытки;
    
КонецПроцедуры

Этот способ является наиболее лаконичным и современным, однако он требует, чтобы целевое устройство или сайт, к которому мы обращаемся, корректно обрабатывали CORS-запросы (возвращали заголовок Access-Control-Allow-Origin: *).

Решение 2. Использование Поля HTML-документа и JavaScript (универсальный обходной путь)

Если вам приходится работать на более старых версиях платформы или необходимо обойти специфические ограничения безопасности браузера, можно встроить JavaScript-код внутрь элемента формы ПолеHTMLДокумента.

Проанализируем ситуацию: мы помещаем простую HTML-страницу со скриптом AJAX во внутреннее поле 1С. Этот скрипт отправляет XMLHttpRequest или использует современный fetch API, получает JSON и передает результат обратно в 1С через генерацию события.

Разберем реализацию этого механизма:


&НаКлиенте
Процедура ИнициализироватьПолеHTML()
    
    // Формируем HTML со встроенным JS кодом
    ТекстHTML = 
    "<html>" +
    "<head>" +
    "<script type='text/javascript'>" +
    "function sendJsonRequest(url, jsonData) {" +
    "    fetch(url, {" +
    "        method: 'POST'," +
    "        headers: {'Content-Type': 'application/json'}," +
    "        body: jsonData" +
    "    })" +
    "    .then(response => response.json())" +
    "    .then(data => {" +
    "        // Передаем ответ обратно в 1С через специальное событие" +
    "        window.parent.postMessage({type: '1C_JSON_RESPONSE', success: true, data: data}, '*');" +
    "    })" +
    "    .catch(error => {" +
    "        window.parent.postMessage({type: '1C_JSON_RESPONSE', success: false, error: error.message}, '*');" +
    "    });" +
    "}" +
    "</script>" +
    "</head>" +
    "<body>" +
    "<p>Интеграционный модуль активен</p>" +
    "</body>" +
    "</html>";
    
    // Записываем HTML в реквизит формы, связанный с Полем HTML
    СодержимоеПоляHTML = ТекстHTML;
    
КонецПроцедуры

Для получения данных обратно в 1С необходимо настроить обработчик события ПриНажатии или использовать встроенный механизм сообщений (в зависимости от версии платформы и используемого браузера). Важно помнить, что современные версии платформы перешли на движки Chromium, поэтому прямая синхронная работа с DOM-деревом (свойство Документ) из кода 1С в веб-клиенте ограничена и требует асинхронного подхода.

Решение 3. Архитектурный обход ограничений через внешние компоненты или локальный веб-сервер

Если устройство RNDIS подключено локально к компьютеру пользователя, обращение к нему напрямую из браузера часто натыкается на блокировки смешанного контента (HTTPS -> HTTP). Чтобы обойти это фундаментальное ограничение безопасности браузеров, используют два промышленных архитектурных решения:

  1. Локальный веб-сервер-прослойка (Local Daemon): На компьютере пользователя устанавливается небольшая служба (например, написанная на Go или Python), которая работает локально и имеет доступ к RNDIS-девайсу. Браузер делает запросы к этой локальной службе на localhost, в настройках которой прописаны все необходимые CORS-разрешения. Служба принимает JSON, транслирует его в устройство и возвращает ответ веб-клиенту.
  2. Внешние компоненты (ВК) Native API для веб-клиента: Это самый надежный способ. Компонента упаковывается в ZIP-архив и устанавливается как расширение браузера. Поскольку ВК выполняется вне жесткой песочницы браузера, она может открывать прямые TCP/UDP сокеты, работать с драйверами торгового оборудования и отправлять любые сетевые пакеты на RNDIS-устройство без каких-либо CORS-ограничений.

Рекомендации по выбору архитектуры решения

Для того чтобы сделать правильный выбор между предложенными вариантами, проанализируем различные эксплуатационные сценарии:

← На главную