Рассмотрим ситуацию, с которой часто сталкиваются разработчики при интеграции 1С со сторонними системами (например, с SAP PI/PO). Внешняя организация предоставляет ссылку на WSDL-описание веб-сервиса и, возможно, сам WSDL в виде отдельного файла. При попытке открыть ссылку в браузере все работает (запрашивается логин и пароль), но при добавлении в конфигуратор через WS-ссылки возникает ошибка: WSDL должен содержать элемент definitions по причине: Неверный формат.
Если же мы пытаемся подключиться программно, используя конструктор WSОпределения, то получаем ошибку: При создании описания сервиса произошла ошибка. URL сервиса: Код ответа сервера: 403. Давайте разберем по шагам, почему так происходит и как правильно организовать подключение.
Проанализируем механику работы платформы 1С, опираясь на основы, изложенные в курсе по HTTP-запросам. При добавлении WS-ссылки или вызове Новый WSОпределения по URL, платформа строго ожидает получить в ответ корректный XML-документ (WSDL-схему), корневым элементом которого является тег <definitions> или <wsdl:definitions>.
Ошибка "Неверный формат" означает, что 1С получает по указанной ссылке не XML, а обычную HTML-страницу. Чаще всего это страница заглушки с текстом ошибки 403 (Forbidden) или форма ввода логина и пароля от шлюза внешней системы. Парсер 1С пытается прочитать HTML-теги, естественно, не находит обязательный элемент определения веб-сервиса и прерывает работу с ошибкой.
Почему в браузере доступ есть, а 1С выдает ошибку 403? Тут кроется важный нюанс контекста выполнения. Когда мы открываем ссылку в браузере на рабочем компьютере, браузер автоматически применяет наши текущие пользовательские сессии, доменные учетные данные или клиентские сертификаты, установленные в личном хранилище Windows.
Когда же код инициализации выполняется на стороне сервера 1С:Предприятия (в фоновом задании или серверном модуле), он работает от имени учетной записи службы операционной системы (например, USR1CV8). В отличие от работы через WebSocket Клиент, у этого системного пользователя нет доступа к вашему личному хранилищу сертификатов.
Посмотрим на пример кода, который часто вызывает проблемы:
ssl1 = Новый ЗащищенноеСоединениеOpenSSL(
Новый СертификатКлиентаWindows(СпособВыбораСертификатаWindows.Авто),
Новый СертификатыУдостоверяющихЦентровWindows
);
Определение = Новый WSОпределения("https://...", Пользователь, Пароль, , , ssl1);
Использование параметра СпособВыбораСертификатаWindows.Авто крайне ненадежно в серверном контексте 1С. Платформа может выбрать некорректный сертификат, либо вообще его не найти, если в хранилище службы пусто. Результат — отказ в доступе (403).
Чтобы обойти проблему с получением WSDL по защищенному HTTPS соединению, воспользуемся локальным файлом (например, BC_SYS_CLNT_si_DataLoad_outb_syncService.wsdl), который нам прислала внешняя организация. Инициализировать WSОпределения из локального файла — абсолютно правильный подход.
Рассмотрим, как это выглядит в коде:
// Указываем путь к физическому файлу на диске сервера 1С
ПутьКФайлуWSDL = "C:\Integrations\BC_SYS_CLNT_si_DataLoad_outb_syncService.wsdl";
// Читаем определение сервиса из файла (без сетевых запросов)
Определение = Новый WSОпределения(ПутьКФайлуWSDL, Пользователь, Пароль, , , ssl1);
Это мгновенно избавит нас от ошибки 403 на этапе чтения структуры сервиса, так как серверу 1С не придется скачивать схему из интернета.
После успешного создания определения из файла, следующая задача — создать сам прокси для вызова методов. Здесь многие сталкиваются с ошибкой: Сервис не найден. Проанализируем типичный ошибочный код:
Прокси = Новый WSПрокси(Определение, " ""si_DataLoad_outb_syncService", "si_DataLoad_outb_syncServiceSoap");
Ошибка "Сервис не найден" возникает из-за неверно переданных параметров при инициализации WSПрокси. Во-первых, обратите внимание на синтаксическую ошибку (лишний пробел и двойная кавычка). Во-вторых, разработчики часто путают пространства имен и имена сервисов, что критично и при создании HTTP API сервисов.
Разберем параметры конструктора WSПрокси по шагам, что полезно знать для написания общего модуля организации HTTP сервиса. Вам необходимо открыть локальный файл WSDL в любом текстовом редакторе (например, в Notepad++) и найти три ключевых значения:
<wsdl:definitions> и скопируйте значение его атрибута targetNamespace. Обычно оно выглядит как URL (например, http://sap.com/xi/Company) или URN.<wsdl:service>. Скопируйте точное значение атрибута name.<wsdl:port>. Скопируйте значение его атрибута name.Теперь создадим прокси правильно:
URIПространстваИмен = "http://sap.com/xi/ВашаКомпания/Интеграция"; // Значение из targetNamespace
ИмяСервиса = "si_DataLoad_outb_syncService"; // Значение из wsdl:service name="..."
ИмяТочкиПодключения = "si_DataLoad_outb_syncPort"; // Значение из wsdl:port name="..."
Прокси = Новый WSПрокси(Определение, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);
Теперь, когда прокси успешно инициализирован, нам необходимо выполнить реальный запрос (вызвать операцию веб-сервиса). Вот тут 1С снова обратится в интернет, и если для доступа нужен клиентский сертификат, нам нужно передать его явно, а не через СертификатКлиентаWindows.
Для надежной работы на сервере рекомендуется экспортировать клиентский сертификат (с закрытым ключом) в файл формата .p12 или .pfx и положить его рядом с WSDL-файлом.
Посмотрим на итоговый пример настройки соединения:
// 1. Читаем клиентский сертификат из файла
ИмяФайлаСертификата = "C:\Integrations\client_cert.p12";
ПарольСертификата = "MySecretPassword";
Сертификат = Новый СертификатКриптографии(ИмяФайлаСертификата, ПарольСертификата);
// 2. Настраиваем SSL-соединение
ssl1 = Новый ЗащищенноеСоединениеOpenSSL(Сертификат, Новый СертификатыУдостоверяющихЦентровОС);
// 3. Загружаем WSDL из локального файла
ПутьКФайлуWSDL = "C:\Integrations\BC_SYS_CLNT_si_DataLoad_outb_syncService.wsdl";
Определение = Новый WSОпределения(ПутьКФайлуWSDL, Пользователь, Пароль, , , ssl1);
// 4. Создаем WSПрокси, используя точные данные из текста WSDL
Прокси = Новый WSПрокси(Определение, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);
// 5. Обязательно указываем логин и пароль для Basic-авторизации, если она требуется поверх SSL
Прокси.Пользователь = Пользователь;
Прокси.Пароль = Пароль;
// 6. Вызываем метод сервиса
Ответ = Прокси.ИмяВашейОперации(ПараметрыЗапроса);
Используя этот пошаговый алгоритм, мы исключаем ошибки автоматического поиска сертификатов в хранилище операционной системы и обходим проблему блокировки при первичном чтении WSDL-схемы. Внимательно проверяйте пространства имен в WSDL, и ваше подключение к сторонним веб-сервисам заработает стабильно.