При интеграции 1С с внешними веб-сервисами программисты часто сталкиваются с ситуацией, когда один и тот же код ведет себя по-разному в зависимости от клиента или режима совместимости конфигурации. Типичный сценарий: в современной конфигурации на управляемых формах (например, УТ 11) запрос проходит успешно, а в старой конфигурации на обычных формах (например, УТ 10.3) тот же самый запрос возвращает ошибку "Код состояния: 400 (Bad Request)".
В данной статье мы подробно разберем причины возникновения этой ошибки, выясним, как протоколы шифрования влияют на результат, и рассмотрим два способа решения проблемы: от настройки платформенных свойств до использования системных компонентов Windows.
Рассмотрим стандартный механизм отправки запроса, который может давать сбой в толстом клиенте. Проблема обычно проявляется при попытке авторизации, когда необходимо передать логин и пароль в формате JSON и получить токен доступа. Рассмотрим типичный код, который работает в современных условиях, но выдает ошибку в устаревших режимах совместимости:
Функция ПолучитьТокен()
Логин = "**********";
Пароль = "**********";
ssl1 = Новый ЗащищенноеСоединениеOpenSSL;
HTTPСоединение = Новый HTTPСоединение("sintec.club", 11000, , , , 60, ssl1);
Данные = Новый Структура;
Данные.Вставить("login", Логин);
Данные.Вставить("password", Пароль);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
ТелоЗапроса = ЗаписьJSON.Закрыть();
АдресРесурса = "auth/sign-in";
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса);
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Если НЕ HTTPОтвет.КодСостояния = 200 Тогда
Сообщить("Ошибка: " + HTTPОтвет.КодСостояния);
Возврат Неопределено;
КонецЕсли;
// Обработка ответа...
КонецФункции
При запуске этого кода в конфигурации с низким режимом совместимости (например, 8.2.13), сервер возвращает код 400. Это происходит несмотря на то, что сама платформа 1С может быть версии 8.3.20 и выше. Причина кроется в том, как 1С обрабатывает защищенные соединения в режиме совместимости.
Главная причина «необъяснимого» поведения кроется в протоколе TLS (Transport Layer Security). Современные веб-серверы из соображений безопасности отключают поддержку старых протоколов SSL 3.0, TLS 1.0 и TLS 1.1, требуя использования TLS 1.2 или выше.
Проанализируем работу платформы: поддержка протокола TLS 1.2 в 1С:Предприятие появилась начиная с версии 8.3.9. Если в вашей конфигурации установлен режим совместимости "8.2.13" или любой другой ниже "8.3.9", платформа ограничивает возможности объекта ЗащищенноеСоединениеOpenSSL. В результате попытка установить соединение происходит по устаревшему протоколу, который сервер отклоняет, возвращая ошибку 400 или просто обрывая сессию.
Это самый правильный и «чистый» способ с точки зрения разработки на 1С. Посмотрим, как это реализовать:
Важное замечание: Смена режима совместимости — ответственный шаг. Это может повлечь за собой изменение поведения других функций, появление ошибок в типовом коде (например, в УТ 10.3 могут "поплыть" некоторые экранные формы или методы работы с файлами). После смены режима необходимо провести тщательное тестирование всей системы.
Рассмотрим, как изменится работа после обновления режима. Платформа начнет корректно использовать современные библиотеки OpenSSL, и ваш запрос к ресурсу auth/sign-in отработает успешно, вернув заветный код 200 или 201.
Если вы не можете изменить режим совместимости (например, из-за огромного количества доработок, которые ломаются при переходе), можно воспользоваться системным объектом Windows — WinHttp.WinHttpRequest.5.1. Этот объект работает в обход стандартных ограничений платформы 1С и использует настройки операционной системы.
Разберем пример кода с использованием этого метода:
Процедура ПолучитьТокенЧерезWinHTTP()
Попытка
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Настройка параметров соединения
URL = "https://sintec.club:11000/auth/sign-in";
WinHttp.Open("POST", URL, Ложь); // Ложь - синхронный запрос
// Установка заголовков
WinHttp.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
// Формирование тела запроса
Данные = Новый Структура("login, password", "Логин", "Пароль");
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
ТелоЗапроса = ЗаписьJSON.Закрыть();
// Отправка
WinHttp.Send(ТелоЗапроса);
Если WinHttp.Status = 200 Тогда
ОтветТекст = WinHttp.ResponseText;
Сообщить("Токен получен!");
Иначе
Сообщить("Ошибка WinHTTP: " + WinHttp.Status + " " + WinHttp.ResponseText);
КонецЕсли;
Исключение
Сообщить("Произошла критическая ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
В некоторых случаях WinHTTP также может потребовать настройки параметров безопасности (например, если на сервере используется самоподписанный сертификат). Для этого используются специальные флаги (Option 4). Например, значение 13056 позволяет игнорировать большинство ошибок сертификатов, что бывает полезно при отладке в закрытых контурах.
Выясним, какие еще факторы могут вызывать ошибку 400 в толстом клиенте:
УстановитьТелоИзСтроки() в старых версиях 1С в начало строки может добавляться невидимый префикс BOM. Многие современные API (особенно написанные на Go или Node.js) воспринимают этот префикс как синтаксическую ошибку и возвращают 400. Чтобы этого избежать, можно формировать тело запроса как ДвоичныеДанные.Если вы столкнулись с ошибкой 400 при POST-запросе в старой конфигурации, первым делом проверьте режим совместимости. В большинстве случаев переход на версию 8.3.9 решает проблему с TLS-соединением. Если же архитектура системы не позволяет менять режим совместимости, используйте WinHttp.WinHttpRequest.5.1, который позволит гибко управлять параметрами HTTPS-запроса на уровне операционной системы.