При интеграции 1С со сторонними веб-сервисами часто возникает ситуация: пример вызова API на PHP через библиотеку cURL отрабатывает корректно, а аналогичный код на 1С с использованием объекта HTTPСоединение возвращает ошибку авторизации или некорректный ответ от сервера. Разберем по шагам, в чем заключаются ключевые отличия формирования HTTP-запросов в PHP и 1С, как локализовать проблему и какими способами её можно решить.
Рассмотрим стандартный рабочий пример на PHP:
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; PHP client; ' . php_uname('s') . '; PHP/' . phpversion() . ')');
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Sign: ' . $sign,
'Key: ' . $key,
));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$res = curl_exec($ch);
При переносе этого кода на 1С разработчики часто создают соответствие заголовков и отправляют запрос через HTTPЗапрос:
ssl = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(ПутьКСайту,,,,,, ssl);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Sign", ШифрованноеЗначение);
Заголовки.Вставить("Key", Ключ);
Запрос = Новый HTTPЗапрос(ЗапросКСайту, Заголовки);
Результат = Соединение.ОтправитьДляОбработки(Запрос);
СтрокаОтвет = Результат.ПолучитьТелоКакСтроку();
Выясним причину, почему аналогичный по структуре код на платформе 1С может приводить к ошибкам со стороны веб-сервера:
User-Agent вида 1C+Enterprise/8.3... либо он отсутствует. Многие современные веб-сервисы, Cloudflare или WAF блокируют запросы со стандартными служебными клиентами, возвращая ошибку авторизации.CURLOPT_POSTFIELDS в PHP не только передает данные, но и автоматически выставляет заголовок Content-Type (например, application/x-www-form-urlencoded). В 1С метод ОтправитьДляОбработки() отправляет тело, только если оно явно установлено у объекта HTTPЗапрос.УстановитьТелоИзСтроки() без указания параметров BOM, платформа может добавить маркер последовательности байтов UTF-8, из-за чего подпись (Sign/HMAC) на сервере не сойдется.ЗащищенноеСоединениеOpenSSL может не согласовывать определенные шифры или версии протоколов TLS.Разберем, как правильно сформировать запрос средствами платформы 1С, добавив все необходимые служебные заголовки и отключив BOM при установке тела запроса.
ssl = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("api.example.com", 443,,,, 30, ssl);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Sign", ШифрованноеЗначение);
Заголовки.Вставить("Key", Ключ);
// Обязательно указываем User-Agent, идентичный браузеру или PHP-клиенту
Заголовки.Вставить("User-Agent", "Mozilla/4.0 (compatible; 1C client; Windows NT)");
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
Запрос = Новый HTTPЗапрос("/api/v1/method", Заголовки);
// Если передаются данные формы или JSON, исключаем BOM
Запрос.УстановитьТелоИзСтроки(СтрокаТелаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Результат = Соединение.ОтправитьДляОбработки(Запрос);
СтрокаОтвет = Результат.ПолучитьТелоКакСтроку();
Если сервер отклоняет запросы из-за ограничений OpenSSL в конкретной версии платформы 1С или нестандартной обработки SSL-рукопожатия, надежным решением под Windows является использование объекта WinHttp.WinHttpRequest.5.1. Он задействует системный стек операционной системы Windows (Schannel), который автоматически поддерживает актуальные версии TLS и сертификаты.
Рассмотрим пример отправки POST-запроса через WinHttpRequest:
Попытка
HTTPЗапросCOM = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
HTTPЗапросCOM.Open("POST", "https://api.example.com/api/v1/method", Ложь);
// Установка заголовков
HTTPЗапросCOM.SetRequestHeader("Sign", ШифрованноеЗначение);
HTTPЗапросCOM.SetRequestHeader("Key", Ключ);
HTTPЗапросCOM.SetRequestHeader("User-Agent", "Mozilla/4.0 (compatible; WinHttp client)");
HTTPЗапросCOM.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// Отключение проверки сертификатов при необходимости (аналог CURLOPT_SSL_VERIFYPEER = false)
// 0x0100 - игнорировать неизвестный УЦ, 0x2000 - игнорировать несоответствие имени узла
HTTPЗапросCOM.Option(4, 16896); // 0x4200 (0x0100 + 0x2000 + 0x0200 + 0x1000)
HTTPЗапросCOM.Send(СтрокаТелаЗапроса);
КодОтвета = HTTPЗапросCOM.Status;
СтрокаОтвет = HTTPЗапросCOM.ResponseText;
Исключение
Сообщить("Ошибка отправки запроса: " + ОписаниеОшибки());
КонецПопытки;
Проанализируем инструменты, которые позволяют быстро найти различия между запросами из PHP и 1С:
https://httpbin.org/anything или https://httpbin.org/headers. В ответе сервер вернет полный список заголовков и структуру тела, которые до него дошли. Сравнив оба ответа, можно мгновенно увидеть отсутствующий или искаженный заголовок.1cv8.exe, предоставляя точную побайтовую картину отправляемых HTTP-пакетов.