При интеграции 1С со сторонними системами часто возникает необходимость передачи данных через SOAP веб-сервисы. Довольно часто разработчики сталкиваются с ситуацией, когда веб-сервис ожидает на вход сложный тип данных (например, список товаров), а при попытке передать параметр возникает ошибка: "Значение не может быть установлено свойству, имеющему объектный тип" или "Несоответствие типов XDTO". Давайте разберем по шагам, почему это происходит и как правильно сформировать запрос к веб-сервису.
Рассмотрим частый сценарий. Имеется веб-сервис, в котором есть метод SetGoods. Этот метод принимает параметр Request с типом Goods. Логичным на первый взгляд решением кажется формирование XML-строки с нужными данными и присвоение этой строки параметру веб-сервиса. Однако, при таком подходе код выдает ошибку:
WSПараметр.Request = ЗаписьХМЛ; // ЗаписьХМЛ - это сформированная строка
// Ошибка: Значение не может быть установлено свойству, имеющему объектный тип
Выясним причину этой ошибки. Дело в том, что свойство Request имеет объектный тип XDTO, и платформа 1С строго следит за соответствием типов. Мы не можем просто передать текстовую строку (даже если это валидный XML) в свойство, которое ожидает конкретный объект ОбъектXDTO с типом Goods из определенного пространства имен.
Чтобы метод веб-сервиса отработал корректно, нам нужно использовать ФабрикаXDTO, которая автоматически создается в объекте WSПрокси, и конструировать объекты именно через нее. Посмотрим на пример, как правильно инициализировать типы и создавать объекты.
Определение = Новый WSОпределения(СокрЛП(Объект.АдресТест), СокрЛП(Объект.ЛогинТест), СокрЛП(Объект.ПарольТест));
Прокси = Новый WSПрокси(Определение, "IntegratedExchange", "IntegratedExchangeSoap");
// Получаем правильный тип из фабрики XDTO прокси
ТипОбъектаТовары = Прокси.ФабрикаXDTO.Тип("http://example.com/namespace", "Goods");
// Создаем корневой объект
Товары = Прокси.ФабрикаXDTO.Создать(ТипОбъектаТовары);
// Получаем тип для подчиненного элемента - конкретного товара
ТипОбъектаТовар = Прокси.ФабрикаXDTO.Тип("http://example.com/namespace", "GoodItem");
// Создаем объект товара
Товар = Прокси.ФабрикаXDTO.Создать(ТипОбъектаТовар);
// Заполняем свойства товара
Товар.ID = "34343";
Товар.Name = "Тестовый товар";
Если веб-сервис ожидает список товаров, то в XDTO схеме (WSDL) у параметра обычно указано свойство maxOccurs="unbounded". Платформа 1С в таком случае автоматически формирует для свойства тип СписокXDTO. Посмотрим, как добавлять элементы в этот список. Мы не можем просто присвоить значение, нам необходимо использовать метод Добавить().
// Добавляем созданный товар в коллекцию
Товары.Good.Добавить(Товар);
// Вызываем метод веб-сервиса и передаем сформированный XDTO объект
Ответ = Прокси.SetGoods(Товары);
Давайте подробно рассмотрим дополнительные технические аспекты, которые помогут сделать интеграцию стабильной и избежать скрытых проблем.
Прокси.ФабрикаXDTO.Тип("Namespace", "TypeName") критически важно указывать точное URI пространства имен. Часто оно выглядит как веб-адрес. Если передать неверный URI (или оставить строку пустой), фабрика XDTO вернет Неопределено, и метод Создать() упадет с ошибкой.nillable="true" или minOccurs="0"), и вы не хотите их заполнять, передавайте туда значение Неопределено. В этом случае 1С автоматически сформирует правильный XML-тег с атрибутом xsi:nil="true".WSПрокси есть свойство Таймаут. Также, если сервис работает по HTTPS, в параметры конструктора WSОпределения рекомендуется передавать объект Новый ЗащищенноеСоединениеOpenSSL() для корректной работы с сертификатами.Если структура веб-сервиса меняется редко, мы рекомендуем использовать статические WS-ссылки. Добавив WS-ссылку прямо в дерево метаданных конфигурации, вы получите ряд преимуществ:
Прокси = WSСсылки.ИмяСервиса.СоздатьWSПрокси(...).Goods или GoodItem), что исключает ошибки в написании имен свойств в коде.Часто бывает так, что вызов метода 1С проходит без ошибок, но сторонняя система возвращает отказ или сообщает о неверном формате данных. Разберем, как посмотреть "сырой" XML, который 1С отправляет на сервер. Для этого можно сериализовать наш подготовленный объект XDTO в строку:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
// Записываем наш объект "Товары" в формате XML
Прокси.ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, Товары);
СтрокаXML = ЗаписьXML.Закрыть();
Сообщить(СтрокаXML); // Теперь можно визуально проверить сформированный запрос
Этот простой метод позволит вам сравнить отправляемый 1С файл с эталонным XML-запросом (например, сформированным в SoapUI) и быстро найти недостающие поля или некорректно заполненные списки.