При интеграции 1С:Предприятие со сторонними веб-сервисами и API разработчики часто сталкиваются с ситуацией, когда готовый пример взаимодействия предоставлен только в виде PHP-скрипта с использованием библиотеки cURL. Задача перевода такого кода на язык 1С требует понимания того, как сопоставлять опции cURL с объектами платформ 1С (такими как HTTPСоединение и HTTPЗапрос), а также знания нюансов кодирования данных, работы с SSL и обработки HTTP-заголовков.
В данной статье мы подробно разберем, как корректно перенести отправку POST-запроса из PHP cURL в 1С:Предприятие 8.3, рассмотрим особенности формирования тела запроса, работу с защищенными соединениями HTTPS и альтернативные способы через COM-объекты.
Проанализируем исходный PHP-код, предоставленный в качестве примера взаимодействия:
<?php
getTyres();
function getTyres(){
$ch = curl_init();
$data = array(
'secret' => 'ключ',
'id' => 'ИД',
);
curl_setopt($ch, CURLOPT_URL, 'https://сайт/parcelsApi/track');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POSTREDIR, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, '3600');
$content = trim(curl_exec($ch));
curl_close($ch);
var_dump($content);
}
Сопоставим ключевые параметры cURL с механизмами платформы 1С:
сайт) передается в конструктор объекта HTTPСоединение, а адрес ресурса (/parcelsApi/track) — в объект HTTPЗапрос.application/x-www-form-urlencoded или структуру JSON и закодировать значения с помощью функции КодироватьCтроку.HTTPСоединение в секундах.ЗащищенноеСоединениеOpenSSL.Рассмотрим по шагам создание функции на языке 1С, выполняющей аналогичный POST-запрос на сервере платформы 1С 8.3.
Сформируем полный рабочий пример кода:
Функция ПолучитьДанныеПоШинам()
// 1. Разделяем адрес на сервер и путь к ресурсу
Сервер = "сайт"; // Указывается доменное имя без "https://"
АдресРесурса = "/parcelsApi/track";
// 2. Формируем заголовки HTTP-запроса
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
// 3. Подготавливаем параметры и кодируем их для URL
ЗначениеСекрет = КодироватьCтроку("ваш_ключ", СпособКодированияСтроки.URLКодирование);
ЗначениеИД = КодироватьCтроку("ваш_ид", СпособКодированияСтроки.URLКодирование);
ТелоЗапроса = СтрШаблон("secret=%1&id=%2", ЗначениеСекрет, ЗначениеИД);
// 4. Настраиваем SSL-соединение для работы по HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
// 5. Создаем HTTPСоединение (хост, порт 443 для HTTPS, таймаут 3600 сек)
Таймаут = 3600;
Соединение = Новый HTTPСоединение(Сервер, 443, , , , Таймаут, ЗащищенноеСоединение);
// 6. Формируем HTTPЗапрос
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Попытка
// Отправляем POST-запрос методом ОтправитьДляОбработки
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
КодСостояния = Ответ.КодСостояния;
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если КодСостояния = 200 Тогда
// Декодируем полученный JSON-ответ
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстОтвета);
Данные = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
Возврат Данные;
Иначе
ЗаписьЖурналаРегистрации("Ошибка API", УровеньЖурналаРегистрации.Ошибка,,,
СтрШаблон("Код ошибки: %1. Ответ: %2", КодСостояния, ТекстОтвета));
Возврат Неопределено;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("Ошибка Подключения API", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
КонецФункции
В некоторых сценариях, когда код выполняется исключительно на сервере под управлением операционной системы Windows, удобно использовать COM-объект WinHttp.WinHttpRequest.5.1. Он автоматически обрабатывает системные сертификаты Windows и поддерживает перенаправления без написания дополнительной логики.
Разберем пример реализации через COM-объект:
Функция ВыполнитьЗапросЧерезCOM()
Попытка
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
Исключение
ЗаписьЖурналаРегистрации("Ошибка COM", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
// Настройка параметров WinHttp
// Option(6) = EnableRedirects (аналог CURLOPT_FOLLOWLOCATION в cURL)
WinHttp.Option(6, 1);
// Установка таймаутов (в миллисекундах): Resolve, Connect, Send, Receive
WinHttp.Timeouts(30000, 30000, 3600000, 3600000);
URL = "https://сайт/parcelsApi/track";
WinHttp.Open("POST", URL, Ложь); // Ложь = синхронный вызов
// Устанавливаем заголовок Content-Type
WinHttp.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
// Формируем параметры запроса
Секрет = КодироватьCтроку("ваш_ключ", СпособКодированияСтроки.URLКодирование);
ИД = КодироватьCтроку("ваш_ид", СпособКодированияСтроки.URLКодирование);
ТелоЗапроса = "secret=" + Секрет + "&id=" + ИД;
// Отправка запроса
WinHttp.Send(ТелоЗапроса);
КодСостояния = WinHttp.Status;
ТекстОтвета = WinHttp.ResponseText;
Если КодСостояния = 200 Тогда
Возврат ТекстОтвета;
Иначе
ЗаписьЖурналаРегистрации("Ошибка WinHttp", УровеньЖурналаРегистрации.Ошибка,,,
СтрШаблон("Код: %1, Ответ: %2", КодСостояния, ТекстОтвета));
Возврат Неопределено;
КонецЕсли;
КонецФункции
Важно: Вариант с COM-объектом подходит только для системы Windows. Если сервер 1С работает под управлением Linux, следует использовать исключительно встроенные объекты HTTPСоединение и HTTPЗапрос.
Рассмотрев оба варианта реализации, выясним, почему при переносе кода с PHP на 1С часто возникают ошибки вида {"error":"Unknown user"} или 400 Bad Request.
curl_setopt($ch, CURLOPT_POSTFIELDS, $array) приводит к автоматической генерации запроса вида multipart/form-data. Если же в PHP передается предварительно собранная строка http_build_query($array), отправляется тип application/x-www-form-urlencoded. В 1С тип содержимого фиксируется явно в заголовке Content-Type, поэтому важно указывать именно тот формат, который ожидает сервер.=, &, пробелы) или кириллицу, обязательна их обработка функцией КодироватьCтроку(..., СпособКодированияСтроки.URLКодирование). Без кодирования сервер не сможет правильно разобрать параметры запроса.CURLOPT_FOLLOWLOCATION = true в PHP заставляет cURL автоматически следовать по редиректам. В 1С объект HTTPСоединение при отправке POST-запроса может вернуть код 301 или 302. В таком случае необходимо извлечь из заголовков ответа заголовок Location и отправить повторный запрос по новому адресу.{"error":"Unknown user"} являются банальные опечатки в наименованиях полей (например, secret вместо key) или значениях идентификаторов, допущенные при ручном переносе кода.Если запрос из 1С не получает ожидаемый ответ от сервера, рекомендуем использовать следующие инструменты и методы отладки:
Попытка ... Исключение и фиксируйте полученный код состояния и текст ответа в ЖурналРегистрации. Это существенно упростит поиск причин ошибок на продуктовых серверах.