Как реализовать обмен с веб-сервисом в 1С при использовании нестандартной авторизации через заголовки?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С со сторонними веб-сервисами разработчики часто сталкиваются с ситуацией, когда стандартные механизмы платформы, такие как WSОпределения и WSПрокси, оказываются недостаточно гибкими. Типичный пример — необходимость передачи специфического токена авторизации в заголовках HTTP-запроса (например, Authorization: Token testtoken). Стандартный конструктор WSПрокси поддерживает только базовую авторизацию (логин и пароль), что приводит к ошибке 403 Forbidden или 401 Unauthorized при попытке обращения к защищенным методам. В этой статье мы подробно разберем, как обойти эти ограничения и успешно реализовать обмен.

Разбор проблемы: почему не работает стандартный WSПрокси

Рассмотрим ситуацию: у нас есть адрес сервиса и токен доступа. Попытка создать WSОпределения напрямую по ссылке часто заканчивается неудачей, так как сервер требует авторизации уже на этапе получения WSDL-описания. Если же нам удается получить WSDL через HTTPСоединение, мы сталкиваемся со следующей проблемой: объект WSПрокси, созданный на основе этого определения, не позволяет динамически добавлять произвольные заголовки в исходящие SOAP-запросы.

Проанализируем типичный ошибочный код:


URLобмена = "Testtest.ru:8012";
АдресСервиса = "http://Testtest.ru:8012/?wsdl";
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Token testtoken");
HTTPЗапрос = Новый HTTPЗапрос(АдресСервиса, Заголовки);
// Здесь мы получаем описание сервиса, но как вызвать метод?
HTTPОтвет = Соединение.Получить(HTTPЗапрос);

Получив тело ответа в виде строки, мы видим XML-описание сервиса. Однако напрямую «превратить» эту строку в работающий объект WSПрокси с поддержкой токена в 1С невозможно. Для решения этой задачи существует два основных пути: использование локального файла WSDL и переход на ручное формирование SOAP-пакетов.

Решение 1: Использование локального файла WSDL для создания определений

Первый шаг к решению — корректная инициализация объекта WSОпределения. Если сервер не отдает WSDL без заголовка авторизации, мы должны сначала скачать его как файл, а затем инициализировать определение локально. Рассмотрим, как это сделать правильно:

  1. Создаем HTTPСоединение и добавляем необходимые заголовки.
  2. Скачиваем текст WSDL и сохраняем его во временный файл.
  3. Создаем WSОпределения, указывая путь к этому файлу.

// 1. Получаем WSDL через HTTP с авторизацией
Соединение = Новый HTTPСоединение("Testtest.ru", 8012);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Token testtoken");
ЗапросWSDL = Новый HTTPЗапрос("/?wsdl", Заголовки);
ОтветWSDL = Соединение.Получить(ЗапросWSDL);

Если ОтветWSDL.КодСостояния = 200 Тогда
    // 2. Сохраняем во временный файл
    ПутьКФайлу = ПолучитьИмяВременногоФайла("xml");
    ОтветWSDL.ПолучитьТелоКакСтроку(ПутьКФайлу);
    
    // 3. Создаем определение из файла
    Определения = Новый WSОпределения(ПутьКФайлу);
Иначе
    Сообщить("Ошибка получения WSDL: " + ОтветWSDL.КодСостояния);
КонецЕсли;

Этот способ позволяет нам увидеть структуру методов сервиса в дереве объектов (если мы добавляем WS-ссылку в конфигурацию) или работать с ними динамически. Однако, даже имея Определения, вызов Новый WSПрокси(Определения, ...) все равно не позволит нам передать токен при вызове конкретного метода. Поэтому перейдем к самому надежному способу.

Решение 2: Ручное формирование SOAP-запроса через HTTPСоединение

Это наиболее гибкий и профессиональный подход. Вместо того чтобы полагаться на высокоуровневый объект WSПрокси, мы сами формируем XML Envelope (конверт) и отправляем его обычным POST-запросом. Проанализируем структуру этого процесса.

Для начала нам нужно узнать, какой именно XML ожидает сервис. Это можно сделать, изучив ранее скачанный WSDL или воспользовавшись бесплатными инструментами вроде SoapUI. Выяснив структуру, реализуем отправку в 1С:


// Формируем тело SOAP-запроса
ТекстЗапроса = 
"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:test=""http://www.test.ru"">
|   <soapenv:Header/>
|   <soapenv:Body>
|      <test:ИмяВашегоМетода>
|         <test:Параметр1>Значение</test:Параметр1>
|      </test:ИмяВашегоМетода>
|   </soapenv:Body>
|</soapenv:Envelope>";

// Настраиваем запрос
Запрос = Новый HTTPЗапрос("/?wsdl"); // Или путь к точке входа (endpoint)
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("Authorization", "Token your_token_here");
// Если сервис требует SOAPAction, его нужно взять из WSDL
Запрос.Заголовки.Вставить("SOAPAction", "http://www.test.ru/ИмяВашегоМетода"); 

Запрос.УстановитьТелоИзСтроки(ТекстЗапроса, КодировкаТекста.UTF8);

// Отправляем запрос
Ответ = Соединение.ОтправитьДляОбъекта(Запрос);

Если Ответ.КодСостояния = 200 Тогда
    Чтение = Новый ЧтениеXML;
    Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    // Далее разбираем XML ответ
Иначе
    Сообщить("Ошибка вызова метода: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;

Использование объекта WinHttp.WinHttpRequest для сложных случаев

В некоторых случаях стандартное HTTPСоединение в 1С может вести себя специфично (например, при работе через сложные прокси-серверы или с определенными типами сертификатов). Тогда мы можем воспользоваться COM-объектом Windows. Это позволяет нам напрямую управлять заголовками на уровне системных библиотек.

Разберем пример использования WinHttp:


WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", "http://Testtest.ru:8012/", Ложь);
WinHttp.SetRequestHeader("Content-Type", "text/xml; charset=utf-8");
WinHttp.SetRequestHeader("Authorization", "Token testtoken");
WinHttp.SetRequestHeader("SOAPAction", "http://tempuri.org/YourMethod");

WinHttp.Send(ТекстЗапроса);

Если WinHttp.Status = 200 Тогда
    Результат = WinHttp.ResponseText;
    // Обработка результата
КонецЕсли;

Как извлечь пользу из WSDL при ручном формировании запроса

Многие разработчики боятся ручного формирования XML, так как структура запроса может быть очень сложной. Проанализируем, как облегчить себе задачу:

Таким образом, если стандартный WSПрокси не справляется с авторизацией, не стоит пытаться «взломать» его поведение. Наиболее правильным и прозрачным решением будет использование HTTPСоединение или WinHttp для прямой отправки SOAP-сообщений. Это дает полный контроль над заголовками и позволяет реализовать обмен с любым современным веб-сервисом, независимо от используемых им методов защиты данных.

← На главную