При интеграции 1С с внешними государственными или корпоративными системами (например, сервисы ЕПГУ, Россети и др.) через механизм WS-ссылок (SOAP), разработчики часто сталкиваются с ошибками валидации ответов. Одной из распространенных проблем является ситуация, когда метод веб-сервиса отрабатывает успешно, но 1С не может разобрать полученный XML-ответ, выдавая ошибку несоответствия структуры XDTO.
Разберем подробно природу этой ошибки, почему она возникает даже при визуально корректном ответе, и рассмотрим рабочие методы ее устранения на примере реальной задачи интеграции.
Рассмотрим типичный сценарий. Вы импортировали WSDL-описание сервиса в конфигурацию 1С как WS-ссылку. При вызове метода сервиса соединение устанавливается, запрос уходит, но при попытке получить результат возникает исключение.
Текст ошибки обычно выглядит следующим образом:
Ошибка преобразования данных XDTO: Чтение объекта типа: {URI_Пространства_Имен}ТипОбъекта
- [12,19] Проверка свойства 'ИмяСвойства1': форма: Элемент имя: {URI}ИмяСвойства1 тип: {URI}ТипСвойства
по причине:
Ошибка проверки данных XDTO: Структура объекта не соответствует типу: {URI_Пространства_Имен}ТипОбъекта
Не установлено значение одного из следующих свойств: ИмяСвойства2
В примере из обсуждения ошибка звучала так: Не установлено значение одного из следующих свойств: RequestId_EPGU. При этом, если посмотреть сырой XML-ответ через сниффер или отладчик, тег RequestId_EPGU в нем присутствует.
Корень проблемы кроется в строгом соответствии стандарту XML Schema (XSD), который использует 1С. В WSDL-описании сложные типы данных часто определяются через конструкцию sequence (последовательность).
Для парсера XDTO в 1С это означает жесткое правило: элементы внутри родительского тега должны следовать строго в том порядке, в котором они описаны в схеме.
Проанализируем ситуацию на примере:
RequestId_Portal, а за ним — RequestId_EPGU.RequestId_EPGU.RequestId_Portal.RequestId_EPGU.RequestId_Portal отсутствует или последовательность нарушена, и выбрасывает исключение.Если бы в схеме использовалась конструкция all вместо sequence, порядок полей был бы неважен, но мы вынуждены работать с тем WSDL, который предоставляет поставщик услуг.
Поскольку исправить сервис поставщика мы, как правило, не можем, рассмотрим способы обхода этой проблемы на стороне 1С.
Часто проблема усугубляется некорректными ссылками внутри самого WSDL (например, ссылки на http вместо https) или проблемами с сертификатами. Наиболее надежный способ — создавать подключение программно, явно указывая параметры.
Рассмотрим пример кода, который решает проблему подключения и корректной обработки данных. Обратите внимание на использование защищенного соединения OpenSSL, что критично для государственных сервисов.
// Определение параметров подключения
// Эти данные берутся из документации к сервису или WSDL
URIПространстваИменСервиса = "http://адрес.пространства.имен/service"; // Уточните в WSDL
ИмяСервиса = "RequestServices";
ИмяПорта = "RequestServicesEndpoint";
// Настройка защищенного соединения
// OpenSSL необходим для корректной работы с https-сервисами
SSL = Новый ЗащищенноеСоединениеOpenSSL;
// Создание прокси программно на основе статической WS-ссылки
// WSСсылкаЕПГУ - это имя вашей WS-ссылки в дереве метаданных
Соединение = WSСсылки.WSСсылкаЕПГУ.СоздатьWSПрокси(
URIПространстваИменСервиса,
ИмяСервиса,
ИмяПорта,
, // Адрес WSDL (если отличается)
, // Таймаут
SSL
);
// Установка учетных данных, если требуются
Соединение.Пользователь = "UserLogin";
Соединение.Пароль = "UserPassword";
// Формирование параметра запроса через Фабрику XDTO
// Это позволяет создать объект, строго соответствующий схеме
ТипПараметра = Соединение.ФабрикаXDTO.Пакеты.Получить(URIПространстваИменСервиса).Получить("GetRequest");
КоличествоЗаявок = Соединение.ФабрикаXDTO.Создать(ТипПараметра);
// Заполнение свойств
КоличествоЗаявок.count = 1;
// Выполнение метода
Попытка
Результат = Соединение.GetRequest(КоличествоЗаявок);
// Результат уже будет объектом XDTO, который можно обходить
Исключение
Сообщить("Ошибка вызова сервиса: " + ОписаниеОшибки());
КонецПопытки;
Если программное создание прокси не помогает и ошибка Структура объекта не соответствует типу сохраняется из-за перепутанных полей, нам необходимо "обмануть" 1С, заставив ее ожидать поля в том порядке, в котором их присылает сервер.
Выполним следующие шаги:
<xs:sequence> или <xsd:sequence> вручную поменяем местами строки с описанием элементов RequestId_EPGU и RequestId_Portal (или других проблемных полей).После этого платформа сгенерирует внутреннюю схему, соответствующую реальному ответу сервера, и ошибка исчезнет.
В самых сложных случаях, когда структура ответа меняется динамически или содержит грубые нарушения стандартов XML, использование механизма WS-ссылок и XDTO становится невозможным. В этом случае переходим на низкоуровневую работу.
Рассмотрим алгоритм действий:
HTTPСоединение методом POST.ЧтениеXML или ОбъектDOM.При использовании ОбъектDOM мы можем искать нужные узлы по именам тегов, игнорируя их порядок следования. Это самый надежный, но и самый трудоемкий способ.
Если вы столкнулись с подобной ошибкой, воспользуйтесь следующими инструментами для анализа:
ЗащищенноеСоединениеOpenSSL.