Интеграция сторонних веб-сервисов в экосистему 1С — задача стандартная, но часто сопровождающаяся трудностями. Одной из самых коварных проблем является лаконичное сообщение «Неверный формат», возникающее при попытке импортировать внешнюю WS-ссылку в конфигураторе или программно создать объект WSОпределения. При этом на сторонних платформах или в специализированных утилитах (например, SoapUI) сервис может открываться и работать абсолютно корректно.
В этой статье мы подробно разберем причины возникновения данной ошибки, проанализируем внутренние механизмы платформы 1С по работе с XML-схемами и рассмотрим практические шаги по устранению этой проблемы.
Платформа 1С предъявляет крайне жесткие требования к описанию WSDL-схем и строго следует стандартам консорциума W3C. Если сторонний сервис, разработанный на .NET, PHP, Java или SAP, генерирует описание с минимальными отклонениями от стандартов 1С (или использует расширения, не поддерживаемые платформой), парсер 1С прерывает работу. Вместо детального отчета об ошибке разработчик получает лишь малоинформативное сообщение: «Неверный формат».
Давайте по шагам разберем основные технические причины этой проблемы и найдем способы их решения.
Современные веб-сервисы практически всегда работают по шифрованному протоколу HTTPS. Сам файл WSDL может успешно скачиваться, но внутри него часто содержатся теги <wsdl:import> или <xsd:import>, которые ссылаются на внешние XSD-схемы, также расположенные на защищенных ресурсах.
Если при инициализации WSОпределения не указать параметры защищенного соединения, 1С не сможет скачать дочерние схемы по ссылкам. Вместо XML-файла веб-сервер вернет платформе HTML-страницу с ошибкой авторизации (например, 401 или 403) либо ошибку перенаправления. Попытка распарсить этот HTML-код приводит к падению платформы с ошибкой формата.
Решение проблемы:
Для устранения этой проблемы при программном создании соединения необходимо явно передавать объект ЗащищенноеСоединениеOpenSSL. Рассмотрим следующий пример кода:
// Инициализируем защищенное соединение с использованием системных сертификатов
СертификатыДляВызова = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
Попытка
// Передаем параметры защищенного соединения в конструктор WSОпределения
Определение = Новый WSОпределения(
"https://api.myservice.com/service.wsdl",
"ИмяПользователя",
"ПарольПользователя",
,
,
СертификатыДляВызова
);
Сообщить("WSDL-схема успешно загружена и разобрана!");
Исключение
Сообщить("Ошибка при загрузке WSDL: " + ОписаниеОшибки());
КонецПопытки;
Если загрузка происходит в конфигураторе при добавлении объекта WS-ссылка, убедитесь, что в операционной системе Windows, под которой запущен конфигуратор, установлены все необходимые корневые и промежуточные сертификаты целевого веб-сервиса. В некоторых случаях помогает предварительный импорт сертификатов в хранилище доверенных корневых сертификатов Windows.
Веб-сервисы, развернутые на серверах IIS (WCF/.NET) или SAP, часто генерируют WSDL с поддержкой расширенных стандартов безопасности (WS-SecurityPolicy). В теле XML-документа это проявляется наличием тегов <wsp:Policy> и ссылок на них <wsp:PolicyReference>.
Парсер конфигуратора и встроенного языка 1С не умеет обрабатывать сложные политики безопасности WS-Policy на этапе импорта схемы. Обнаружив эти теги, 1С немедленно выдает ошибку «Неверный формат».
Решение проблемы:
В этом случае нам потребуется провести локальную «модернизацию» файла описания схемы. Выполним следующие шаги:
service.wsdl).<xsd:import schemaLocation="..."/>), скачаем их тоже и сохраним локально в ту же папку. В самом WSDL изменим адреса импорта на локальные пути.service.wsdl в любом продвинутом текстовом редакторе (например, Notepad++, VS Code).<wsp:Policy> ... </wsp:Policy> (включая сами эти теги).<wsp:PolicyReference URI="..." />.service.wsdl вместо интернет-ссылки. Конфигуратор успешно проглотит очищенную схему.Часто веб-сервисы, написанные на старых версиях PHP или Java, описывают коллекции данных (массивы) с типом soapenc:Array. Однако платформа 1С строго привязана к стандартам XML Schema (XSD), где концепция массивов реализуется через последовательности элементов sequence с атрибутом количества вхождений maxOccurs.
Встречая конструкцию type="soapenc:Array", парсер 1С не понимает структуру передаваемой коллекции, что вызывает сбой валидации схемы.
Решение проблемы:
Рассмотрим структуру описания типа в исходном WSDL:
<complexType name="ArrayOfItems">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="tns:Item[]"/>
</restriction>
</complexContent>
</complexType>
Нам необходимо вручную переписать этот фрагмент в локальном файле схемы под стандарт, понятный 1С (стиль Document/Literal):
<complexType name="ArrayOfItems">
<sequence>
<element name="Item" type="tns:Item" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</sequence>
</complexType>
Такое описание структуры данных будет без проблем прочитано платформой, и 1С создаст корректные XDTO-пакеты для передачи списков объектов.
Бывают ситуации, когда веб-сервис требует обязательной предварительной авторизации. Если мы пытаемся загрузить WSDL напрямую через конструктор Новый WSОпределения(Адрес) без указания логина и пароля, сервер возвращает редирект (код HTTP 301/302) на форму авторизации или ошибку 401 Unauthorized.
Поскольку парсер ожидает увидеть XML-структуру WSDL, а получает HTML-код страницы авторизации или текст ошибки, мы снова сталкиваемся с ошибкой формата.
Решение проблемы:
Проанализируем доступность сервиса с помощью сторонних инструментов (SoapUI или просто в браузере в режиме инкогнито). Если для доступа требуется авторизация, мы должны обязательно передать учетные данные:
ИмяПользователя = "WS_User";
ПарольПользователя = "SuperSecretPassword123";
АдресWSDL = "https://api.myservice.com/service?wsdl";
SSLСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Попытка
Определение = Новый WSОпределения(АдресWSDL, ИмяПользователя, ПарольПользователя, , , SSLСоединение);
WSПрокси = Новый WSПрокси(Определение, "http://tempuri.org/", "MyService", "MyPort");
Исключение
ВызватьИсключение "Ошибка подключения к сервису: " + ОписаниеОшибки();
КонецПопытки;
Если WSDL-схема слишком сложная, динамически меняется, содержит несовместимые типы данных или у вас нет возможности постоянно править локальный WSDL-файл при обновлении стороннего API, лучшим решением будет полный отказ от использования механизмов WSОпределения, WS-ссылок и WSПрокси.
Вместо этого мы можем работать с веб-сервисом напрямую с помощью низкоуровневых HTTP-запросов. Мы сами формируем SOAP-пакет в виде строки XML, отправляем его через HTTPСоединение и самостоятельно парсим пришедший XML-ответ.
Рассмотрим детальный пример реализации такого подхода:
// Настраиваем параметры подключения
Сервер = "api.myservice.com";
Порт = 443; // Используем стандартный порт HTTPS
SSL = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(Сервер, Порт, , , , 30, SSL);
// Создаем HTTP-запрос
Запрос = Новый HTTPЗапрос("/soap/endpoint");
// SOAP требует установки корректного Content-Type и заголовка SOAPAction
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("SOAPAction", "http://tempuri.org/GetContractData");
// Формируем тело XML SOAP-конверта вручную
ТелоXML =
"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/"">" +
" <soapenv:Header/>" +
" <soapenv:Body>" +
" <tem:GetContractData>" +
" <tem:ContractNumber>12345-А</tem:ContractNumber>" +
" </tem:GetContractData>" +
" </soapenv:Body>" +
"</soapenv:Envelope>";
Запрос.УстановитьТелоИзСтроки(ТелоXML, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Отправляем запрос на сервер
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Исключение
Сообщить("Сетевая ошибка отправки SOAP-запроса: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Обрабатываем ответ сервера
Если Ответ.КодСостояния = 200 Тогда
СтрокаXML = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Используем ЧтениеXML для разбора полученных данных
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Пока Чтение.Прочитать() Цикл
// Обработка узлов XML-документа
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "ContractStatus" Тогда
Чтение.Прочитать();
Сообщить("Статус договора: " + Чтение.Значение);
КонецЕсли;
КонецЦикла;
Иначе
Сообщить("Сервер вернул ошибку с кодом состояния: " + Ответ.КодСостояния);
Сообщить("Текст ошибки: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
Этот метод полностью изолирует код 1С от капризов парсера WSDL-схем. Вы полностью контролируете структуру отправляемого XML и процесс разбора ответа, что гарантирует стабильность работы интеграции независимо от обновлений платформы 1С или изменений политики безопасности на сторонней стороне.
Если вы все же хотите заставить работать механизмы WSОпределения, воспользуйтесь следующей памяткой для локализации сбойного участка схемы: