Интеграция 1С с внешними информационными системами через веб-службы (REST API) стала повседневной задачей для современного разработчика. Одним из наиболее популярных стандартов обмена данными сегодня является формат JSON. Однако при реализации взаимодействия часто возникают технические трудности, связанные с тем, как именно передавать эти данные в HTTP-запросах. Особенно много вопросов вызывают GET-запросы со сложными фильтрами.
В этой статье мы детально разберем проблему, с которой сталкиваются разработчики при интеграции 1С с популярной системой ServiceDesk Plus (SDP) API v3. Мы выясним, почему исходный код автора темы не работал, подробно изучим ограничения HTTP-методов в платформе 1С и реализуем два гарантированно рабочих решения для GET и POST запросов.
Давайте проанализируем исходный код автора и разберем допущенные им ошибки. В своем первом сообщении автор пытается получить данные из ServiceDesk Plus, выполняя GET-запрос с фильтрацией. Для этого он формирует JSON-строку input_data и пытается передать ее двумя способами одновременно:
УстановитьТелоИзСтроки().HTTPЗапрос.Заголовки.Вставить("input_data", СтрокаJSN).Оба этих подхода содержат критические ошибки, из-за которых интеграция дает сбой:
Во-первых, спецификация HTTP-метода GET не предусматривает отправку тела (body). Хотя технически некоторые библиотеки позволяют прикрепить тело к GET-запросу, стандарт RFC и большинство веб-серверов (включая платформу 1С и сам сервер ServiceDesk Plus) либо полностью игнорируют тело в GET-запросах, либо возвращают ошибку. При вызове метода HTTPСоединение.Получить() платформа 1С просто отбрасывает тело запроса, поэтому сервер возвращает данные без учета фильтров.
Во-вторых, параметр input_data не является HTTP-заголовком. Заголовки HTTP используются для служебной информации (например, авторизация, тип контента, кодировка). Попытка передать структуру данных в заголовке бессмысленна — сервер просто проигнорирует неизвестное поле.
В-третьих, при попытке использовать POST-запрос через метод ОтправитьДляОбработки() автор отправляет «чистый» JSON в теле запроса, но оставляет заголовок Content-Type в значении application/x-www-form-urlencoded. В этом формате сервер ожидает данные вида ключ=значение, а не сырой JSON-текст. Это несоответствие и вызывает ошибку на стороне сервера.
Давайте разберем, как обойти ограничение GET-запроса на передачу тела. В ServiceDesk Plus API v3 для получения списков (запросы GET) разработчики предусмотрели передачу параметра input_data непосредственно в строке запроса (Query Parameters).
Поскольку JSON содержит спецсимволы (двоеточия, фигурные скобки, кавычки, пробелы), его нельзя передавать в исходном виде в URL-адресе. Строку обязательно нужно закодировать. В 1С для этого используется встроенная функция КодироватьСтроку() со значением кодирования СпособКодированияСтроки.КодировкаURL. Все спецсимволы будут заменены на соответствующие шестнадцатеричные коды (например, пробел превратится в %20).
Рассмотрим по шагам правильную реализацию GET-запроса в 1С:
// Функция выполняет запрос к API и возвращает полученные данные
Функция ПолучитьСписокЗаявокИзServiceDesk() Экспорт
// 1. Формируем структуру параметров
СтруктураФильтра = Новый Структура;
СтруктураФильтра.Вставить("name", "8702_MyView");
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("row_count", 20);
СтруктураПараметров.Вставить("start_index", 1);
СтруктураПараметров.Вставить("filter_by", СтруктураФильтра);
СтруктураList = Новый Структура;
СтруктураList.Вставить("list_info", СтруктураПараметров);
// 2. Сериализуем структуру в JSON
СтрокаJSON = СформироватьСтрокуJSON(СтруктураList);
// 3. Кодируем строку JSON для вставки в URL
ЗакодированныйJSON = КодироватьСтроку(СтрокаJSON, СпособКодированияСтроки.КодировкаURL);
// 4. Формируем адрес ресурса с параметром input_data
АдресСервиса = "sd-srv-01";
АдресРесурса = "/api/v3/requests?input_data=" + ЗакодированныйJSON;
// 5. Создаем HTTP-запрос
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
// Устанавливаем необходимые заголовки
HTTPЗапрос.Заголовки.Вставить("Authtoken", "FC645540-6424-4A07-8A05-A865F4B8168A");
// Крайне важный заголовок для API v3, гарантирующий получение ответа в нужном формате
HTTPЗапрос.Заголовки.Вставить("Accept", "application/vnd.manageengine.sdp.v3+json");
// 6. Выполняем GET-запрос
HTTPСоединение = Новый HTTPСоединение(АдресСервиса);
Попытка
Ответ = HTTPСоединение.Получить(HTTPЗапрос);
Исключение
ВызватьИсключение "Ошибка при отправке GET-запроса: " + ОписаниеОшибки();
КонецПопытки;
// 7. Обрабатываем ответ сервера
Если Ответ.КодСостояния = 200 Тогда
СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Возврат СтрокаОтвета;
Иначе
Сообщить("Сервер вернул ошибку с кодом: " + Ответ.КодСостояния);
Сообщить(Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
Возврат Неопределено;
КонецЕсли;
КонецФункции
Если ваша задача требует изменения состояния объектов на сервере (например, создание новой заявки или редактирование существующей), то правилами хорошего тона и архитектурой REST предписано использовать метод POST или PUT. В этом случае параметры действительно нужно передавать в теле запроса.
Однако, помня об особенностях работы ServiceDesk Plus с типом контента application/x-www-form-urlencoded, мы должны сформировать тело запроса специальным образом. Оно должно выглядеть как строка вида: input_data=Закодированный_JSON_Текст.
Давайте посмотрим, как реализовать этот алгоритм на практике в 1С:
Процедура СоздатьЗаявкуВServiceDesk(СтруктураДанныхЗаявки)
АдресСервиса = "sd-srv-01";
АдресРесурса = "/api/v3/requests";
// 1. Сериализуем данные в JSON
СтрокаJSON = СформироватьСтрокуJSON(СтруктураДанныхЗаявки);
// 2. Создаем HTTP-запрос
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
// Настраиваем обязательные заголовки
HTTPЗапрос.Заголовки.Вставить("Authtoken", "FC645540-6424-4A07-8A05-A865F4B8168A");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
HTTPЗапрос.Заголовки.Вставить("Accept", "application/vnd.manageengine.sdp.v3+json");
// 3. Формируем тело запроса по стандарту x-www-form-urlencoded
ЗакодированныйJSON = КодироватьСтроку(СтрокаJSON, СпособКодированияСтроки.КодировкаURL);
СтрокаТелаЗапроса = "input_data=" + ЗакодированныйJSON;
// Устанавливаем тело запроса
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаТелаЗапроса, КодировкаТекста.UTF8);
// 4. Отправляем запрос методом POST
HTTPСоединение = Новый HTTPСоединение(АдресСервиса);
Попытка
// Для отправки POST используем ОтправитьДляОбработки
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Исключение
ВызватьИсключение "Ошибка при отправке POST-запроса: " + ОписаниеОшибки();
КонецПопытки;
// 5. Проверяем результат
Если Ответ.КодСостояния = 200 Или Ответ.КодСостояния = 201 Тогда
Сообщить("Запрос успешно обработан сервером.");
Сообщить(Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
Иначе
Сообщить("Ошибка выполнения POST. Код ответа: " + Ответ.КодСостояния);
Сообщить(Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
КонецЕсли;
КонецПроцедуры
Для успешной интеграции критически важно правильно генерировать саму JSON-строку. Платформа 1С:Предприятие предоставляет удобные механизмы потоковой и объектной записи. Давайте напишем вспомогательную функцию, которая быстро преобразует любую переданную структуру 1С в чистую JSON-строку без лишних переносов и служебных символов:
Функция СформироватьСтрокуJSON(ВходнаяСтруктура) Экспорт
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, СпособПредставленияЧиселJSON.Десятичный);
// Настраиваем запись во внутреннюю память
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
// Выполняем сериализацию
ЗаписатьJSON(ЗаписьJSON, ВходнаяСтруктура, Новый НастройкиСериализацииJSON);
СтрокаJSON = ЗаписьJSON.Закрыть();
Возврат СтрокаJSON;
КонецФункции
Помимо корректного формирования сетевых запросов, при интеграции с SDP API v3 необходимо помнить о нескольких важных архитектурных особенностях этой системы:
list_info, row_count, filter_by) должны передаваться исключительно в нижнем регистре. Если вы случайно запишете Row_count с большой буквы, сервер вернет ошибку валидации схемы.Accept: application/vnd.manageengine.sdp.v3+json. Это сообщает серверу о необходимости использовать именно логику API v3. В противном случае поведение сервера на некоторых версиях ПО может быть непредсказуемым.Authtoken актуальна для On-Premise версий продукта (локальные сервера). Если ваша компания использует облачное решение ServiceDesk Plus Cloud, авторизация строится на базе OAuth 2.0. В этом случае вместо заголовка Authtoken необходимо использовать стандартный заголовок авторизации: Authorization: Zoho-oauthtoken [Ваш_Токен].Использование предложенных шаблонов кода и понимание специфики работы HTTP-протокола позволит вам быстро и безболезненно настроить интеграцию любой сложности между вашей базой 1С и системой ServiceDesk Plus.