При интеграции 1С с внешними веб-сервисами и REST API (например, вебхуками Битрикс24) разработчики часто сталкиваются с необходимостью отправки сложных составных параметров. Простые значения легко объединяются в строку вида Параметр1=Значение1&Параметр2=Значение2. Однако при попытке передать вложенные данные (например, блок полей FIELDS, содержащий NAME, свойства или вложенные объекты) сервер может вернуть ошибку HTTP 400 Bad Request с сообщением о незаполненных обязательных полях.
Выясним причину такого поведения веб-сервиса и подробно рассмотрим два способа решения задачи: классический (через кодирование параметров формы application/x-www-form-urlencoded) и современный универсальный способ (через передачу данных в формате application/json с использованием платформенных механизмов 1С).
Разберем, почему сервер не принимает стандартную сериализацию в виде строки. При использовании заголовка Content-Type: application/x-www-form-urlencoded веб-серверы (в частности, на базе PHP) ожидают вложенные массивы и объекты в формате ключей с квадратными скобками:
FIELDS[NAME]=Test+element или с URL-экранированием: FIELDS%5BNAME%5D=Test%20element
Если передать вложенную структуру как строку через фигурные скобки FIELDS={NAME: "Test"} или просто через запятую, сервер воспримет значение как обычную плоскую строку, не сможет распарсить внутренний ассоциативный массив и вернет ошибку проверки данных.
Проанализируем первый вариант, когда веб-сервер принимает строго тело запроса формата application/x-www-form-urlencoded. В этом случае нам необходимо обойти структуру параметров, выделить вложенные структуры и корректно экранировать спецсимволы.
Для кодирования строковых значений в формат URL в платформе 1С предусмотрена штатная функция КодироватьСтроку с параметром СпособКодированияСтроки.КодировкаURL. Важно помнить: кодировать нужно только сами значения и имена полей, но не управляющие разделители &, = и квадратные скобки структуры.
Напишем функцию для формирования строки POST-параметров:
Функция ПреобразоватьСтруктуруПараметровВСтроку(ПараметрыСтруктурой)
Результат = "";
Для Каждого КлючИЗначение Из ПараметрыСтруктурой Цикл
Если ТипЗнч(КлючИЗначение.Значение) = Тип("Структура") Тогда
// Обрабатываем вложенный уровень структуры (например, FIELDS)
Для Каждого ВложенныйКлюч Из КлючИЗначение.Значение Цикл
ИмяПараметра = КлючИЗначение.Ключ + "[" + ВложенныйКлюч.Ключ + "]";
ЗначениеПараметра = КодироватьСтроку(Строка(ВложенныйКлюч.Значение), СпособКодированияСтроки.КодировкаURL);
Результат = Результат + ?(ПустаяСтрока(Результат), "", "&") + ИмяПараметра + "=" + ЗначениеПараметра;
КонецЦикла;
Иначе
// Обрабатываем обычные плоские параметры
ИмяПараметра = КлючИЗначение.Ключ;
ЗначениеПараметра = КодироватьСтроку(Строка(КлючИЗначение.Значение), СпособКодированияСтроки.КодировкаURL);
Результат = Результат + ?(ПустаяСтрока(Результат), "", "&") + ИмяПараметра + "=" + ЗначениеПараметра;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Посмотрим, как теперь подготовить и отправить запрос:
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("IBLOCK_TYPE_ID", "bitrix_processes");
ПараметрыЗапроса.Вставить("IBLOCK_ID", "276");
ПараметрыЗапроса.Вставить("ELEMENT_CODE", "element_1");
// Формируем вложенную структуру
ПоляЭлемента = Новый Структура;
ПоляЭлемента.Вставить("NAME", "Тестовый элемент");
ПараметрыЗапроса.Вставить("FIELDS", ПоляЭлемента);
СтрокаПараметров = ПреобразоватьСтруктуруПараметровВСтроку(ПараметрыЗапроса);
Важное замечание: если структура имеет уровень вложенности глубже двух (например, передаются пользовательские свойства FIELDS[PROPERTY_123][n0]), функцию обхода следует реализовать рекурсивно.
Использование устаревшего объекта COMОбъект("WinHttp.WinHttpRequest.5.1") имеет существенный недостаток: он работает исключительно под операционными системами Windows. Если сервер 1С функционирует под управлением Linux, регламентные задания и серверные вызовы завершатся аварийно.
Большинство современных REST API (включая вебхуки Битрикс24) полноценно поддерживают прием параметров в теле POST-запроса в формате application/json. Это избавляет от необходимости вручную формировать квадратные скобки и следить за кодированием строк.
Разберем по шагам правильную реализацию через штатные объекты HTTPСоединение и HTTPЗапрос:
Структура, Соответствие, Массив).ЗаписьJSON.Content-Type: application/json; charset=utf-8.Посмотрим на практический пример кода:
// 1. Формируем тело запроса во вложенной структуре
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("IBLOCK_TYPE_ID", "bitrix_processes");
ПараметрыЗапроса.Вставить("IBLOCK_ID", 276);
ПараметрыЗапроса.Вставить("ELEMENT_CODE", "element_1");
ВложенныеПоля = Новый Структура;
ВложенныеПоля.Вставить("NAME", "Тестовый элемент");
ПараметрыЗапроса.Вставить("FIELDS", ВложенныеПоля);
// 2. Сериализуем структуру в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
СтрокаJSON = ЗаписьJSON.Закрыть();
// 3. Настраиваем защищенное HTTP-соединение
ИмяСервера = "your-domain.bitrix24.ru";
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение(ИмяСервера, 443, , , , 30, ЗащищенноеСоединение);
// 4. Формируем и отправляем HTTP-запрос
ПутьКВебхуку = "/rest/1/webhook_code/lists.element.add";
HTTPЗапрос = Новый HTTPЗапрос(ПутьКВебхуку);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
ОтветHTTP = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ТекстОтвета = ОтветHTTP.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если даже после корректного формирования тела запроса сервис возвращает ошибку о незаполненном названии, обратим внимание на следующие нюансы API:
lists.element.* надежнее передавать числовой IBLOCK_ID, так как строковый IBLOCK_CODE поддерживается не во всех редакциях и контекстах.NAME, а пользовательское свойство инфоблока. В таком случае в структуре FIELDS должны присутствовать ключи вида PROPERTY_<ID> или PROPERTY_<CODE>.Таким образом, для простых сценариев внутри среды Windows подходит кодирование вложенных параметров в формат FIELDS[NAME]=значение с вызовом КодироватьСтроку, а для надежных кроссплатформенных решений оптимальным выбором является связка ЗаписьJSON и HTTPСоединение.