При интеграции 1С с внешними веб-сервисами (например, платежными системами, CRM или сервисами рассылок типа JustClick) программисты часто сталкиваются с ситуацией, когда запрос идеально работает в Postman, но возвращает ошибки или пустые данные при выполнении из кода 1С. В данной статье мы подробно разберем, как правильно подготовить POST-запрос, почему стандартные методы могут не срабатывать и как обрабатывать специфические ответы сервера, такие как перенаправление 307.
Рассмотрим ситуацию: необходимо отправить данные для создания заказа во внешнюю систему. Сервис ожидает POST-запрос с тремя параметрами: ключ API, email клиента и наименование продукта. Типичная ошибка начинающего разработчика — попытка передать в метод УстановитьТелоИзСтроки объект Структура напрямую или передача JSON-данных там, где сервер ожидает формат application/x-www-form-urlencoded.
Проанализируем типичный некорректный ответ сервера: "Customer email cannot be empty". Это происходит потому, что сервер не смог распознать структуру переданных данных и «увидел» пустое тело запроса. Чтобы этого избежать, нам необходимо строго соблюдать формат передачи данных и кодировку.
Первым делом создадим объект HTTPСоединение. Обратите внимание, что для работы с защищенными ресурсами (https) необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Разберем код настройки:
// Настройка защищенного соединения
Защита = Новый ЗащищенноеСоединениеOpenSSL();
// Создаем соединение с сервером
HTTPСоединение = Новый HTTPСоединение("uchi.justclick.ru", 443, , , , , Защита);
// Подготавливаем запрос к конкретному методу API
HTTPЗапрос = Новый HTTPЗапрос("/api/createorder");
// Устанавливаем обязательный заголовок для передачи параметров формы
HTTPЗапрос.Заголовки.Вставить("Content-type", "application/x-www-form-urlencoded");
HTTPЗапрос.Заголовки.Вставить("Accept-Charset", "utf-8");
Важный момент: использование заголовка Content-type: application/x-www-form-urlencoded сообщает серверу, что данные в теле запроса будут переданы в виде строки параметр1=значение1&параметр2=значение2.
Просто соединить строки через символ & недостаточно. Если в email содержится символ @, а в названии продукта — пробелы или кириллица, сервер может неправильно интерпретировать строку. Для этого в 1С используется функция КодироватьСтроку. Рассмотрим правильный способ сборки параметров:
Функция КодироватьСтрокуПараметра(Параметр, Значение)
// Преобразуем спецсимволы в формат, понятный URL (например, @ в %40)
Возврат КодироватьСтроку(Параметр, СпособКодированияСтроки.КодировкаURL)
+ "=" +
КодироватьСтроку(Значение, СпособКодированияСтроки.КодировкаURL);
КонецФункции
// Сборка общей строки параметров
СтрокаПараметров = КодироватьСтрокуПараметра("rpsKey", КлючApi) + "&" +
КодироватьСтрокуПараметра("customer_email", "test@mail.ru") + "&" +
КодироватьСтрокуПараметра("product_names", "BP1C");
// Установка тела запроса без использования BOM (Byte Order Mark)
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаПараметров, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Использование ИспользованиеByteOrderMark.НеИспользовать критично, так как многие веб-серверы не понимают префикс BOM в начале строки и выдают ошибку синтаксиса.
Иногда после отправки корректного запроса сервер возвращает код состояния 307 (Temporary Redirect). В отличие от браузеров или Postman, объект HTTPСоединение в 1С не переходит по ссылке автоматически. Это означает, что нам нужно программно прочитать адрес перенаправления из заголовка Location и отправить запрос повторно.
Выясним причину: код 307 означает, что ресурс временно перемещен, но метод запроса (POST) должен остаться неизменным при переходе. Проанализируем ситуацию на примере кода:
// Отправляем первый запрос
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
// Проверяем, не требует ли сервер перенаправления
Если HTTPОтвет.КодСостояния = 307 Тогда
// Получаем новый адрес из заголовка Location
НовыйАдрес = HTTPОтвет.Заголовки.Получить("Location");
Если ЗначениеЗаполнено(НовыйАдрес) Тогда
// Создаем новый запрос по новому адресу
// Если адрес в Location полный (с http), нужно будет пересоздать соединение,
// если относительный (как в нашем случае), используем текущее.
HTTPЗапросРегирект = Новый HTTPЗапрос(НовыйАдрес);
// Копируем заголовки и тело из исходного запроса
HTTPЗапросРегирект.Заголовки.Вставить("Content-type", "application/x-www-form-urlencoded");
HTTPЗапросРегирект.УстановитьТелоИзСтроки(СтрокаПараметров, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Повторная отправка
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапросРегирект);
КонецЕсли;
КонецЕсли;
// Проверяем итоговый результат
Если HTTPОтвет.КодСостояния = 200 Тогда
Сообщить("Заказ успешно создан: " + HTTPОтвет.ПолучитьТелоКакСтроку());
Иначе
Сообщить("Ошибка API: " + HTTPОтвет.ПолучитьТелоКакСтроку());
КонецЕсли;
В процессе отладки часто возникает соблазн переключиться на application/json, так как с ним удобнее работать в 1С через ЗаписьJSON. Однако, если документация API (или структура ответа, полученная ранее) явно указывает на ошибки заполнения полей при использовании x-www-form-urlencoded, значит сервер ожидает именно этот формат. Отправка JSON-строки на сервер, настроенный на прием параметров формы, приведет к ошибке "No transmitted data", так как сервер будет искать ключи в массиве $_POST (в случае PHP), а JSON прилетает в потоке php://input.
Для стабильной работы интеграций через HTTP-запросы в 1С рекомендуем придерживаться следующих правил:
КодироватьСтроку со способом КодировкаURL.
Content-type соответствует ожиданиям сервера (чаще всего это application/x-www-form-urlencoded или application/json).
HTTPОтвет.ПолучитьТелоКакСтроку() — ваш главный инструмент для понимания того, почему внешняя система отклонила запрос.
Рассмотренный подход позволяет обходить ограничения автоматических систем перенаправления и гарантирует доставку данных даже в тех случаях, когда API сервиса выполняет внутреннюю маршрутизацию запросов между своими серверами.