Интеграция 1С с внешними SOAP-сервисами — одна из самых распространенных и в то же время трудоемких задач. Часто разработчики сталкиваются с ситуацией, когда веб-сервис успешно подключается, но при попытке вызвать метод возникают ошибки или данные возвращаются пустыми. Особенно это характерно для государственных сервисов (например, ФОМС или СМЭВ). В этой статье мы подробно разберем, как победить типичные ошибки при работе с WSПрокси и правильно извлечь данные из ответа.
Проанализируем типичную ситуацию: вы вызываете метод веб-сервиса и получаете ошибку: "Метод объекта не обнаружен" или "Ошибка обращения к процедуре как к функции". Выясним причину этого поведения. В архитектуре SOAP методы могут быть двух типов: возвращающие значение (аналог функции в 1С) и не возвращающие значения (аналог процедуры).
Если в WSDL-описании сервиса для конкретной операции не определен возвращаемый тип (например, указан void), то 1С интерпретирует такой метод именно как процедуру. Попытка присвоить результат выполнения такой процедуры переменной через Результат = Прокси.ИмяМетода() приведет к ошибке. Рассмотрим, как это выглядит в коде, который "не взлетает":
// Ошибочный подход, если метод является процедурой
Данные = Прокси.getPolicyInfo3(WSПараметр);
// 1С выдаст ошибку, так как функция ничего не возвращает
Однако отсутствие возвращаемого значения не означает, что данных в ответе нет. В таких случаях данные передаются через так называемые выходные (out) параметры. Это переменные, которые вы передаете в метод «пустыми», а веб-сервис наполняет их информацией в процессе выполнения.
Рассмотрим подробнее, как работать с методами, которые возвращают данные через параметры. Платформа 1С поддерживает передачу параметров «по ссылке». Это значит, что если в WSDL-описании метода указано несколько элементов в секции сообщения ответа (Output), то в 1С они сопоставляются с аргументами вызова по порядку их следования.
Разберем по шагам правильный алгоритм вызова:
Посмотрим на рабочий пример кода, который позволил автору темы получить результат:
// Инициализируем переменные для получения данных ответа
п1 = ""; п2 = ""; п3 = ""; п4 = ""; п5 = ""; п6 = ""; п7 = ""; п8 = ""; п9 = ""; п10 = "";
// Вызываем метод как процедуру.
// Важно: количество аргументов должно строго соответствовать описанию в WSDL
Прокси.getPolicyInfo3("", 3353, "2018-06-04", п1, п2, п3, п4, п5, п6, п7, п8, п9, 3, п10, "2312345678901234");
// После выполнения метода переменные п1...п10 будут содержать данные от сервиса
Сообщить("ФИО пациента: " + п5);
Проанализируем ситуацию с типами данных. Часто веб-сервисы, написанные на Java или .NET, очень чувствительны к передаче пустых значений. В 1С мы привыкли использовать Неопределено, но при сериализации в SOAP это может привести к двум результатам в XML-пакете:
xsi:nil="true".Если веб-сервис ожидает обязательный тег, но допускает его пустоту (параметр nillable="false" в схеме XSD), использование Неопределено вызовет ошибку "недостаточно параметров" или "некорректный формат запроса". В этом случае, как показывает практика, помогает замена Неопределено на пустую строку "". Это заставляет 1С сформировать в теле запроса пустой тег вида <param/>, который корректно воспринимается сервисом.
Также обратим внимание на формат даты. При интеграции с внешними системами лучше избегать передачи объекта Дата напрямую, если вы не уверены в настройках фабрики XDTO. Безопаснее использовать функцию XMLСтрока(ВашаДата) или передавать дату строкой в формате ISO (ГГГГ-ММ-ДД), например: "2023-10-25".
Если метод веб-сервиса содержит огромное количество параметров (30 и более), писать их через запятую становится неудобно и велик риск ошибиться в позиции. Проанализируем более современный подход через ФабрикаXDTO. Вместо передачи длинного списка аргументов мы можем создать один объект, описывающий всё входное сообщение.
// Получаем тип входного параметра из фабрики прокси
ТипПараметра = Прокси.ФабрикаXDTO.Пакеты.Получить("http://namespace.uri").Получить("getPolicyInfo3Request");
WSПараметр = Прокси.ФабрикаXDTO.Создать(ТипПараметр);
// Заполняем только нужные свойства объекта
WSПараметр.policyNumber = "2312345678901234";
WSПараметр.birthDate = "1980-01-01";
// Передаем объект как единственный аргумент
Попытка
Данные = Прокси.getPolicyInfo3(WSПараметр);
Исключение
Инфо = ИнформацияОбОшибке();
Сообщить("Ошибка вызова: " + Инфо.Описание);
КонецПопытки;
Бывают случаи, когда WSDL-файл настолько сложен или некорректно составлен, что стандартный механизм WSПрокси в 1С не может его правильно интерпретировать (например, путает типы или не видит выходные параметры). В такой ситуации рассмотрим "тяжелую артиллерию" — прямое формирование XML-пакета и отправку его через HTTPСоединение.
Разберем основные шаги этого метода:
HTTPСоединение.HTTPЗапрос, устанавливаем адрес ресурса.Content-Type: text/xml; charset=utf-8 и SOAPAction (значение берется из WSDL).POST и получаем HTTPОтвет.ЧтениеXML или ФабрикаXDTO.ПрочитатьXML().Этот метод сложнее в реализации, но он дает полный контроль над передаваемыми данными и позволяет избежать ограничений платформенного парсера WSDL.
Резюме: Если вы столкнулись с проблемой при работе с SOAP, первым делом проверьте в SoapUI, является ли метод функцией или процедурой. Если процедурой — подготовьте переменные для всех out параметров и передавайте их в вызов по порядку. Не забывайте про формат дат и используйте пустые строки вместо Неопределено для обязательных полей.