Как решить проблему несоответствия типов XDTO при загрузке каталога «Ресурс-Медиа» в 1С

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

Интеграция с внешними поставщиками через веб-сервисы — стандартная задача для современного разработчика 1С. Однако при работе с протоколом SOAP и механизмом XDTO часто возникают неочевидные ошибки, способные поставить в тупик даже опытного специалиста. Одной из таких проблем является ошибка «Несоответствие типов XDTO», возникающая при попытке передать параметры в методы API компании «Ресурс-Медиа». В этой статье мы подробно разберем, почему возникает эта ошибка и как правильно сформировать структуру данных для успешного обмена.

Анализ исходной ситуации и возникшей ошибки

Рассмотрим ситуацию: разработчик пытается вызвать метод GetItemsAvail (получение остатков) через WSПрокси. Для этого необходимо передать таблицу групп номенклатуры MaterialGroup_Tab. Стандартный подход к созданию объекта через фабрику XDTO выглядит логичным: мы получаем тип из пакета, создаем объект и пытаемся добавить в него элементы. Однако на этапе выполнения кода 1С выдает ошибку:

Несоответствие типов XDTO: Тип '{http://resurs-media.ru/api}MaterialGroup' не соответствует типу ''

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


// Создание объекта таблицы групп
Тип_MaterialGroup_Tab = Прокси.ФабрикаXDTO.Пакеты.Получить(ПространствоИмен).Получить("MaterialGroup_Tab");
MaterialGroup_Tab = Прокси.ФабрикаXDTO.Создать(Тип_MaterialGroup_Tab);

// Создание элемента группы
ТипЭлемента = Прокси.ФабрикаXDTO.Пакеты.Получить(ПространствоИмен).Получить("MaterialGroup");
ЗначениеЭлемента = Прокси.ФабрикаXDTO.Создать(ТипЭлемента, "Тест");

// Попытка добавления в список приводит к ошибке
MaterialGroup_Tab.Item.Добавить(ЗначениеЭлемента);

На первый взгляд всё верно. Но если мы заглянем в WSDL-описание сервиса, то увидим причину проблемы. В схеме XML тип MaterialGroup_Tab содержит последовательность элементов Item, внутри которых находится анонимный комплексный тип. 1С не может сопоставить именованный тип MaterialGroup с тем, что ожидается внутри коллекции Item.

Разбор структуры WSDL и выявление причины проблемы

Давайте внимательно изучим структуру данных в определении веб-сервиса. Проблема кроется в способе описания вложенных элементов:


<xs:complexType name="MaterialGroup_Tab">
    <xs:sequence>
        <xs:element name="Item" minOccurs="0" maxOccurs="unbounded">
            <xs:complexType> <!-- Анонимный тип! -->
                <xs:sequence>
                    <xs:element name="MaterialGroup" type="tns:MaterialGroup"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

Здесь элемент Item не имеет явно указанного имени типа (атрибут type отсутствует), вместо этого тип определен прямо внутри элемента. Когда мы используем Прокси.ФабрикаXDTO.Создать(ТипЭлемента, "Тест"), мы создаем простое значение или объект на базе именованного типа, но коллекция Item ожидает объект именно той анонимной структуры, которая описана в MaterialGroup_Tab.

Правильное решение: использование динамического определения типов

Чтобы обойти ограничение, связанное с анонимными типами, нам нужно создавать объект не «наугад» из пакета, а на основании метаданных самой коллекции, в которую мы собираемся этот объект поместить. Для этого в платформе 1С предусмотрен механизм обращения к свойству ВладеющееСвойство. Рассмотрим правильный алгоритм действий по шагам.

Шаг 1. Создаем корневой объект таблицы. С этим этапом проблем обычно нет, так как тип MaterialGroup_Tab является именованным.


Тип_MaterialGroup_Tab = Прокси.ФабрикаXDTO.Пакеты.Получить(ПространствоИмен).Получить("MaterialGroup_Tab");
MaterialGroup_Tab = Прокси.ФабрикаXDTO.Создать(Тип_MaterialGroup_Tab);

Шаг 2. Получаем тип элемента коллекции. Вместо прямого поиска типа в пакете по имени, мы обратимся к метаданным свойства Item объекта MaterialGroup_Tab.


// Получаем тип, который ожидается внутри списка Item
ТипЭлементаСписка = MaterialGroup_Tab.Свойства().Получить("Item").Тип;

Шаг 3. Создаем объект элемента и заполняем его данными. Теперь, когда у нас есть правильный тип (пусть он и анонимный в WSDL), мы можем создать объект XDTO и установить его свойства.


// Создаем объект нужного типа
НовыйЭлемент = Прокси.ФабрикаXDTO.Создать(ТипЭлементаСписка);

// Заполняем внутреннее поле MaterialGroup значением кода группы
// Здесь можно использовать простое строковое значение, 1С само приведет его к простому типу XDTO
НовыйЭлемент.MaterialGroup = "Код_Вашей_Группы";

Шаг 4. Добавляем объект в список. Теперь типы полностью соответствуют друг другу, и метод Добавить() отработает корректно.

MaterialGroup_Tab.Item.Добавить(НовыйЭлемент);

Финальный код для работы с методами GetItemsAvail и GetPrices

Объединим всё вышесказанное в законченную функцию, которую можно использовать в вашей обработке загрузки каталога. Обратите внимание на использование объекта ЗащищенноеСоединениеOpenSSL, так как API «Ресурс-Медиа» работает по защищенному протоколу HTTPS.


ПространствоИмен = "http://resurs-media.ru/api";
ssl = Новый ЗащищенноеСоединениеOpenSSL();
Определения = Новый WSОпределения(АдресWSDL, Логин, Пароль, , , ssl);
Прокси = Новый WSПрокси(Определения, ПространствоИмен, "WSAPI", "WSAPISoap12", , , ssl);
Прокси.Пользователь = Логин;
Прокси.Пароль = Пароль;

// Подготовка таблицы групп
Тип_Tab = Прокси.ФабрикаXDTO.Пакеты.Получить(ПространствоИмен).Получить("MaterialGroup_Tab");
Объект_Tab = Прокси.ФабрикаXDTO.Создать(Тип_Tab);

// Динамическое создание элемента
ТипЭлемента = Объект_Tab.Свойства().Получить("Item").Тип;
ЭлементСписка = Прокси.ФабрикаXDTO.Создать(ТипЭлемента);
ЭлементСписка.MaterialGroup = "12345"; // Пример кода группы

// Добавление в коллекцию
Объект_Tab.Item.Добавить(ЭлементСписка);

// Вызов метода сервиса
Результат = Прокси.GetItemsAvail("Склад_ID", Неопределено, Объект_Tab);

Особенности API «Ресурс-Медиа», о которых стоит знать

После того как техническая проблема с XDTO решена, важно учитывать бизнес-логику работы данного поставщика. Проанализируем несколько важных моментов, которые помогут сделать вашу интеграцию надежной:

  1. Склады и идентификаторы: Перед запросом остатков обязательно вызовите метод GetWareHouses. API требует передавать конкретный WareHouseID. Использование идентификаторов, не привязанных к вашему договору, вернет ошибку или пустой результат.
  2. Формат остатков: Метод GetItemsAvail часто возвращает остатки не в числах, а в текстовых категориях (например, "много", "мало", "средне"). Продумайте логику интерпретации этих значений в вашей системе (например, "много" = 100 шт, "мало" = 5 шт).
  3. Связка с каталогом: Метод GetCatalog возвращает только структуру папок. Чтобы получить сами товары, используйте метод GetMaterialData. В него можно передать MaterialID (код товара) или MaterialGroup (код группы).
  4. Пагинация и лимиты: При получении больших объемов данных (весь каталог) старайтесь разбивать запросы. Хотя API позволяет запрашивать данные по целым группам, слишком объемные XML-ответы могут приводить к таймаутам на стороне клиента 1С. Рекомендуется установить таймаут в WSПрокси не менее 60-120 секунд.

Резюме: Основная сложность при работе с XDTO в 1С часто заключается не в программных ошибках, а в особенностях формирования WSDL-схемы. Использование ВладеющееСвойство.Тип — это универсальный и безопасный способ создания объектов для веб-сервисов с анонимными типами данных, который гарантирует совместимость версий даже при небольших изменениях в структуре API поставщика.

← На главную