Как в 1С правильно выполнить операцию SOAP веб-сервиса и получить данные из выходных параметров?

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

Интеграция 1С с внешними SOAP-сервисами — одна из самых распространенных и в то же время трудоемких задач. Часто разработчики сталкиваются с ситуацией, когда веб-сервис успешно подключается, но при попытке вызвать метод возникают ошибки или данные возвращаются пустыми. Особенно это характерно для государственных сервисов (например, ФОМС или СМЭВ). В этой статье мы подробно разберем, как победить типичные ошибки при работе с WSПрокси и правильно извлечь данные из ответа.

Разбираемся с ошибкой: обращение к процедуре как к функции

Проанализируем типичную ситуацию: вы вызываете метод веб-сервиса и получаете ошибку: "Метод объекта не обнаружен" или "Ошибка обращения к процедуре как к функции". Выясним причину этого поведения. В архитектуре SOAP методы могут быть двух типов: возвращающие значение (аналог функции в 1С) и не возвращающие значения (аналог процедуры).

Если в WSDL-описании сервиса для конкретной операции не определен возвращаемый тип (например, указан void), то 1С интерпретирует такой метод именно как процедуру. Попытка присвоить результат выполнения такой процедуры переменной через Результат = Прокси.ИмяМетода() приведет к ошибке. Рассмотрим, как это выглядит в коде, который "не взлетает":


// Ошибочный подход, если метод является процедурой
Данные = Прокси.getPolicyInfo3(WSПараметр); 
// 1С выдаст ошибку, так как функция ничего не возвращает

Однако отсутствие возвращаемого значения не означает, что данных в ответе нет. В таких случаях данные передаются через так называемые выходные (out) параметры. Это переменные, которые вы передаете в метод «пустыми», а веб-сервис наполняет их информацией в процессе выполнения.

Механизм работы с выходными (out) параметрами в 1С

Рассмотрим подробнее, как работать с методами, которые возвращают данные через параметры. Платформа 1С поддерживает передачу параметров «по ссылке». Это значит, что если в WSDL-описании метода указано несколько элементов в секции сообщения ответа (Output), то в 1С они сопоставляются с аргументами вызова по порядку их следования.

Разберем по шагам правильный алгоритм вызова:

  1. Определяем количество параметров, которые ожидает метод (включая все выходные поля).
  2. Инициализируем переменные для получения данных.
  3. Вызываем метод как процедуру, передавая все аргументы по порядку.

Посмотрим на рабочий пример кода, который позволил автору темы получить результат:


// Инициализируем переменные для получения данных ответа
п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);

Нюансы заполнения параметров: Неопределено vs Пустая строка

Проанализируем ситуацию с типами данных. Часто веб-сервисы, написанные на Java или .NET, очень чувствительны к передаче пустых значений. В 1С мы привыкли использовать Неопределено, но при сериализации в SOAP это может привести к двум результатам в XML-пакете:

Если веб-сервис ожидает обязательный тег, но допускает его пустоту (параметр nillable="false" в схеме XSD), использование Неопределено вызовет ошибку "недостаточно параметров" или "некорректный формат запроса". В этом случае, как показывает практика, помогает замена Неопределено на пустую строку "". Это заставляет 1С сформировать в теле запроса пустой тег вида <param/>, который корректно воспринимается сервисом.

Также обратим внимание на формат даты. При интеграции с внешними системами лучше избегать передачи объекта Дата напрямую, если вы не уверены в настройках фабрики XDTO. Безопаснее использовать функцию XMLСтрока(ВашаДата) или передавать дату строкой в формате ISO (ГГГГ-ММ-ДД), например: "2023-10-25".

Альтернатива: Использование объектов XDTO

Если метод веб-сервиса содержит огромное количество параметров (30 и более), писать их через запятую становится неудобно и велик риск ошибиться в позиции. Проанализируем более современный подход через ФабрикаXDTO. Вместо передачи длинного списка аргументов мы можем создать один объект, описывающий всё входное сообщение.


// Получаем тип входного параметра из фабрики прокси
ТипПараметра = Прокси.ФабрикаXDTO.Пакеты.Получить("http://namespace.uri").Получить("getPolicyInfo3Request");
WSПараметр = Прокси.ФабрикаXDTO.Создать(ТипПараметр);

// Заполняем только нужные свойства объекта
WSПараметр.policyNumber = "2312345678901234";
WSПараметр.birthDate = "1980-01-01";

// Передаем объект как единственный аргумент
Попытка
    Данные = Прокси.getPolicyInfo3(WSПараметр);
Исключение
    Инфо = ИнформацияОбОшибке();
    Сообщить("Ошибка вызова: " + Инфо.Описание);
КонецПопытки;

Когда WSПрокси бессилен: использование HTTPЗапроса

Бывают случаи, когда WSDL-файл настолько сложен или некорректно составлен, что стандартный механизм WSПрокси в 1С не может его правильно интерпретировать (например, путает типы или не видит выходные параметры). В такой ситуации рассмотрим "тяжелую артиллерию" — прямое формирование XML-пакета и отправку его через HTTPСоединение.

Разберем основные шаги этого метода:

  1. Формируем текстовую строку XML, содержащую SOAP-конверт (Envelope), заголовок (Header) и тело (Body).
  2. Создаем объект HTTPСоединение.
  3. Создаем HTTPЗапрос, устанавливаем адрес ресурса.
  4. Критически важно: устанавливаем заголовки Content-Type: text/xml; charset=utf-8 и SOAPAction (значение берется из WSDL).
  5. Отправляем запрос методом POST и получаем HTTPОтвет.
  6. Парсим полученный XML-ответ через ЧтениеXML или ФабрикаXDTO.ПрочитатьXML().

Этот метод сложнее в реализации, но он дает полный контроль над передаваемыми данными и позволяет избежать ограничений платформенного парсера WSDL.

Резюме: Если вы столкнулись с проблемой при работе с SOAP, первым делом проверьте в SoapUI, является ли метод функцией или процедурой. Если процедурой — подготовьте переменные для всех out параметров и передавайте их в вызов по порядку. Не забывайте про формат дат и используйте пустые строки вместо Неопределено для обязательных полей.

← На главную