При интеграции 1С:Предприятия со сторонними веб-сервисами часто возникает задача отправить SOAP-запрос. В большинстве случаев платформа берет на себя всю рутину через вызовы WSПрокси, однако в нестандартных сценариях (например, при сложной авторизации WS-Security или необходимости получить точный XML-конверт) разработчику требуется сформировать структуру SOAP Envelope вручную через механизмы XDTO или передать сырой XML через HTTPСоединение.
Разберем типичные ошибки, возникающие при создании объекта Envelope через ФабрикаXDTO, и рассмотрим все рабочие способы отправки SOAP-запросов из 1С.
Проанализируем распространенную ситуацию: разработчик пытается программно создать SOAP Envelope с помощью глобальной или локальной фабрики XDTO, но получает ошибку о том, что указанный тип не найден.
Выясним основные причины этой ошибки:
ФабрикаXDTO содержит только базовые схемы XML-типов. Схема пространства имен SOAP Envelope (например, http://schemas.xmlsoap.org/soap/envelope/ для версии SOAP 1.1) должна быть предварительно импортирована в дерево метаданных конфигурации или загружена из внешнего файла.Новый ФабрикаXDTO() в качестве второго параметра ожидает не отдельный объект ПакетXDTO, а массив пакетов (или набор файлов схем).http://schemas.xmlsoap.org/soap/envelope/) отличается от SOAP 1.2 (http://www.w3.org/2003/05/soap-envelope). Если схема импортирована для одной версии, а обращение идет к другой, платформа не сможет обнаружить тип.Разберем по шагам, как правильно добавить схему SOAP Envelope в конфигурацию и сформировать структуру конверта программно.
http://schemas.xmlsoap.org/soap/envelope/) либо выберем предварительно сохраненный локальный файл .xsd.Посмотрим на пример кода, позволяющего создать объект Envelope через глобальную фабрику:
URI_SOAP = "http://schemas.xmlsoap.org/soap/envelope/";
EnvelopeXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(URI_SOAP, "Envelope"));
EnvelopeXDTO.Body = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(URI_SOAP, "Body"));
Если мы создаем фабрику динамически на базе внешних файлов схем без добавления в метаданные, используем метод СоздатьФабрикуXDTO():
МассивСхем = Новый Массив;
МассивСхем.Добавить("C:\Schemas\soap-envelope.xsd");
МассивСхем.Добавить("C:\Schemas\service-types.xsd");
Фабрика = СоздатьФабрикуXDTO(МассивСхем);
ТипКонверта = Фабрика.Тип("http://schemas.xmlsoap.org/soap/envelope/", "Envelope");
Конверт = Фабрика.Создать(ТипКонверта);
Если сервис предоставляет стандартный WSDL-контракт, формировать XML-конверт вручную не требуется. Платформа 1С самостоятельно создает весь Envelope, передает заголовки и преобразует ответ в объекты XDTO.
Рассмотрим типовой пример работы через WSОпределения и WSПрокси:
URL_WSDL = "http://api.service.com/service.wsdl";
Определения = Новый WSОпределения(URL_WSDL, "Логин", "Пароль");
URIПространства = "http://api.service.com/";
ИмяСервиса = "Service";
ИмяТочки = "ServiceSoapPort";
Прокси = Новый WSПрокси(Определения, URIПространства, ИмяСервиса, ИмяТочки);
Прокси.Пользователь = "Логин";
Прокси.Пароль = "Пароль";
// Вызываем метод веб-сервиса напрямую
Ответ = Прокси.GetData(Параметр1);
Когда требуется отправить сформированный вручную SOAP XML (например, при нестандартных заголовках безопасности WS-Security или при отсутствии WSDL), используем связку HTTPСоединение и HTTPЗапрос.
Разберем по шагам подготовку и отправку такого запроса:
ЗаписьXML или сериализацией объекта XDTO через Фабрика.ЗаписатьXML().Для SOAP 1.1 обязательны заголовки Content-Type: text/xml; charset=utf-8 и SOAPAction: "URI_Действия".
Для SOAP 1.2 используется Content-Type: application/soap+xml; charset=utf-8; action="URI_Действия" (заголовок SOAPAction не передается).
ОтправитьДляОбработки().Посмотрим на пример отправки SOAP 1.1 запроса:
Сервер = "api.service.com";
Ресурс = "/soap-endpoint";
// Создаем защищенное соединение (если HTTPS)
Защита = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(Сервер, 443, , , , 30, Защита);
Запрос = Новый HTTPЗапрос(Ресурс);
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("SOAPAction", """http://api.service.com/GetData""");
ТекстSOAP =
"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:web=""http://api.service.com/"">
| <soapenv:Header/>
| <soapenv:Body>
| <web:GetDataRequest>
| <web:Id>12345</web:Id>
| </web:GetDataRequest>
| </soapenv:Body>
|</soapenv:Envelope>";
Запрос.УстановитьТелоИзСтроки(ТекстSOAP, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
// Обрабатываем полученный XML-ответ
Иначе
ВызватьИсключение "Ошибка сервиса. Код: " + Ответ.КодСостояния;
КонецЕсли;
При работе с SOAP в 1С следует помнить о следующих особенностях платформы:
WSОпределения. Если структура сервиса на стороне контрагента изменилась, сеанс 1С может выдавать ошибки до перезапуска рабочего процесса сервера или клиентского приложения.minOccurs="1"), передача значения Неопределено вызовет исключение при выполнении ЗаписатьXML().