Как правильно отправить POST-запрос с JSON из 1С и избежать ошибок сервера

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

Интеграция систем 1С с внешними веб-сервисами (REST API) — одна из самых частых задач современного разработчика. При её реализации мы регулярно сталкиваемся с неочевидными техническими нюансами. Неверно выбранный метод отправки, некорректно сформированный адрес ресурса или скрытые служебные символы в теле запроса могут привести к ошибкам на стороне веб-сервера, которые крайне трудно диагностировать.

В этой статье мы подробно разберем практический кейс интеграции 1С с банковским API. Мы проанализируем причины возникновения таких ошибок, как NotSupportedException и внутренних ошибок сервера с кодом 500 Internal Server Error, и найдем надежные способы их решения.

Входные данные задачи

Перед нами стоит задача — выполнить авторизационный POST-запрос к тестовому контуру API банка для получения токена доступа (accessToken). Сервер принимает JSON-пакет с логином, паролем и кодом партнера.

Успешный пример запроса через утилиту cURL выглядит следующим образом:


curl -X POST "https://api-test-bridge.alfabank.by:8036/api/Account/postCreds" \
-H "accept: application/json" \
-H "Content-Type: application/json-patch+json" \
-d "{ \"login\": \"МойЛогин\", \"password\": \"МойПароль\", \"partnerCode\": \"0160\"}"

Давайте разберем по шагам, какие ошибки часто допускают разработчики при переносе этого запроса в код 1С, и как написать решение правильно.

---

Ошибка 1. Путаница между GET и POST методами в 1С

Рассмотрим фрагмент исходного кода, который часто пишется по невнимательности:


HTTP = Новый HTTPСоединение(ИмяСервера, Порт, , , , , ssl1);
// ... формирование запроса ...
Результат = HTTP.Получить(HTTPЗапрос); 

Выясним причину проблемы. Метод Получить() объекта HTTPСоединение предназначен исключительно для отправки GET-запросов. По спецификации HTTP-протокола, GET-запросы не должны содержать тела (Request Body). Если мы передаем заполненный объект HTTPЗапрос с телом через метод Получить(), веб-сервер либо проигнорирует переданные данные, либо вернет ошибку некорректного запроса.

Решение: Для отправки POST-запроса в старых версиях платформы используется метод ОтправитьДляОбработки(), а в современных релизах 1С (начиная с 8.3.10) — явный метод Post() или универсальный метод ВызватьHTTPМетод().

---

Ошибка 2. Неверный формат адреса ресурса (NotSupportedException)

В процессе разработки часто возникает ошибка веб-сервера:

NotSupportedException: The given path's format is not supported.

Это происходит из-за того, что разработчики указывают полный URL, включая протокол и порт, внутри самого запроса:


ИмяСервера = "api-test-bridge.alfabank.by";
Порт = 8036;
РесурсНаСервере = "https://api-test-bridge.alfabank.by:8036/api/Account/postCreds"; // Ошибка!

Проанализируем ситуацию на стороне сервера. Веб-сервер (в данном случае на платформе .NET/ServiceStack) получает относительный путь запроса. Если в параметре пути передается строка, содержащая двоеточие или протокол (например, https://...), внутренние обработчики сервера пытаются сопоставить это с физическими путями операционной системы. Двоеточие распознается как некорректный символ для пути файла, что и вызывает исключение NotSupportedException.

Решение: Четко разделяйте зону ответственности объектов 1С:

Правильный вариант распределения параметров:


ИмяСервера = "api-test-bridge.alfabank.by";
Порт = 8036; // Порт передается числом в соединение
РесурсНаСервере = "/api/Account/postCreds"; // Только относительный путь!

---

Ошибка 3. Неправильная работа с коллекцией заголовков

При добавлении заголовков в запрос часто совершают ошибку при работе с типами данных:


ЗаголовокHTTP = Новый Соответствие;
ЗаголовокHTTP.Вставить("accept", "application/json");
ЗаголовокHTTP.Вставить("Content-Type", "application/json-patch+json");

HTTPЗапрос = Новый HTTPЗапрос(РесурсНаСервере);
HTTPЗапрос.Заголовки.Вставить(ЗаголовокHTTP); // Ошибка выполнения 1С!

Метод Вставить() объекта Соответствие (которым является свойство Заголовки) ожидает на вход пару Ключ и Значение в качестве двух раздельных параметров. Попытка передать туда другое соответствие целиком приводит к падению системы.

Решение: Заголовки можно передать либо непосредственно в конструктор запроса вторым параметром, либо добавлять их поочередно:


// Вариант А: Передача соответствия в конструктор
ЗаголовкиЗапроса = Новый Соответствие;
ЗаголовкиЗапроса.Вставить("accept", "application/json");
ЗаголовкиЗапроса.Вставить("Content-Type", "application/json-patch+json");

HTTPЗапрос = Новый HTTPЗапрос(РесурсНаСервере, ЗаголовкиЗапроса);

// Вариант Б: Построчное добавление в существующий объект
HTTPЗапрос = Новый HTTPЗапрос(РесурсНаСервере);
HTTPЗапрос.Заголовки.Вставить("accept", "application/json");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json-patch+json");

---

Ошибка 4. Невидимый враг — маркер последовательности байтов UTF-8 (BOM)

Даже если мы исправили адрес ресурса, перешли на POST-запрос и правильно прописали заголовки, сервер всё равно может отвечать неопределенной ошибкой 500 Internal Server Error.

Разберем причину этого явления. По умолчанию при преобразовании строки JSON в двоичные данные методом УстановитьТелоИзСтроки() платформа 1С добавляет в начало файла три невидимых служебных байта (EF BB BF) — так называемый **Byte Order Mark (BOM)**. Он сигнализирует текстовым редакторам о том, что файл записан в кодировке UTF-8.

Однако современные REST-серверы строго следуют стандарту RFC 8259. Согласно стандарту, JSON-документ обязан начинаться непосредственно со знака открывающей фигурной скобки { или квадратной скобки [. Обнаружив посторонние символы BOM в начале входящего потока данных, парсер сервера выдает ошибку десериализации (часто приводящую к `NullPointerException` или ошибке `500` на стороне бэкенда).

Решение: Принудительно отключайте запись BOM при формировании тела запроса:


HTTPЗапрос.УстановитьТелоИзСтроки(ПараметрыPOST, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

---

Итоговый правильный шаблон реализации POST-запроса

Объединим все исправления в один надежный, рабочий и современный шаблон кода на языке 1С:


// 1. Инициализируем параметры подключения
ИмяСервера = "api-test-bridge.alfabank.by";
Порт = 8036;
РесурсНаСервере = "/api/Account/postCreds";

// Используем защищенное соединение SSL
SSLСоединение = Новый ЗащищенноеСоединениеOpenSSL;
HTTPСоединение = Новый HTTPСоединение(ИмяСервера, Порт, , , , , SSLСоединение);

// 2. Формируем тело запроса (JSON)
ДанныеЗапроса = Новый Структура;
ДанныеЗапроса.Вставить("login", "МойЛогин");
ДанныеЗапроса.Вставить("password", "МойПароль");
ДанныеЗапроса.Вставить("partnerCode", "0160");

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку;
ЗаписатьJSON(ЗаписьJSON, ДанныеЗапроса);
СтрокаJSON = ЗаписьJSON.Закрыть();

// 3. Создаем HTTP-запрос и заполняем заголовки
Заголовки = Новый Соответствие;
Заголовки.Вставить("accept", "application/json");
// Обратите внимание: для обычного JSON используем стандартный Content-Type
Заголовки.Вставить("Content-Type", "application/json"); 

HTTPЗапрос = Новый HTTPЗапрос(РесурсНаСервере, Заголовки);

// КРИТИЧЕСКИ ВАЖНО: Отключаем Byte Order Mark (BOM)
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

// 4. Отправляем запрос и анализируем ответ
Попытка
    // Использование современного метода Post() платформы 8.3
    ОтветСервера = HTTPСоединение.Post(HTTPЗапрос);
    
    КодСостояния = ОтветСервера.КодСостояния;
    СтрокаОтвета = ОтветСервера.ПолучитьТелоКакСтроку();
    
    Если КодСостояния = 200 Тогда
        Сообщить("Запрос выполнен успешно!");
        Сообщить("Ответ сервера: " + СтрокаОтвета);
        // Здесь можно распарсить полученный токен через ЧтениеJSON
    Иначе
        Сообщить("Ошибка сервера! Код состояния: " + КодСостояния);
        Сообщить("Детали ошибки: " + СтрокаОтвета);
    КонецЕсли;
Исключение
    Сообщить("Ошибка при выполнении HTTP-запроса: " + ОписаниеОшибки());
КонецПопытки;

Используя этот шаблон, вы гарантируете корректную передачу данных без скрытых символов разметки, правильную адресацию и надежную обработку исключений при интеграции с любыми внешними веб-сервисами.

← На главную