Интеграция с внешними системами через SOAP-протокол — это стандартная, но зачастую сложная задача для разработчика 1С. Основные трудности возникают не столько в создании самой WSСсылки, сколько в правильном формировании структуры данных с помощью ФабрикиXDTO. В данной статье мы подробно разберем, как интегрировать 1С с сервисом планирования маршрутов (на примере «Белтрансспутник»), выясним, что скрывается за кастомными общими модулями, и научимся избегать ошибки «Несоответствие типов» при вызове методов веб-сервиса.
Часто в примерах кода от сторонних сервисов можно встретить вызовы функций вроде инВебСервисы.ПолучитьОбъектВебСервиса. Проанализируем ситуацию: если в вашей конфигурации нет такого модуля, значит, это была внутренняя разработка компании-интегратора. Однако это не повод для паники. Проанализировав контекст, мы понимаем, что эта функция является «оберткой» над стандартными методами платформы 1С для работы с XDTO.
Основная задача подобных функций — сократить код создания объекта нужного типа. Вместо того чтобы каждый раз прописывать пространство имен (URI) и искать тип в фабрике, разработчики создают универсальную процедуру. Рассмотрим, как мы можем заменить этот модуль стандартными средствами 1С.
Прежде чем отправлять данные, нам нужно создать объект прокси. Это «мост», через который 1С общается с сервером. Разберем процесс инициализации по шагам:
Процедура ИнициализироватьВебСервис(Сервис, Пользователь = "", Пароль = "")
// Если прокси уже создан, повторно инициализировать не нужно
Если Сервис <> Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
// Создаем прокси на основании WS-ссылки, добавленной в конфигурацию
// "инМаршрутыБТС" - это имя WS-ссылки в дереве метаданных
Сервис = WSСсылки.инМаршрутыБТС.СоздатьWSПрокси("VrpWebServiceService", "VrpWebServicePort", , 300);
// Устанавливаем учетные данные для Basic-авторизации
Сервис.Пользователь = Пользователь;
Сервис.Пароль = Пароль;
Исключение
ЗаписьЖурналаРегистрации("Интеграция.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
ВызватьИсключение "Не удалось подключиться к веб-сервису!";
КонецПопытки;
КонецПроцедуры
Обратите внимание на параметр таймаута (300 секунд). При передаче больших массивов заказов логистические сервисы могут долго обрабатывать запрос, поэтому стандартных 30 секунд может не хватить.
Теперь перейдем к главной проблеме: как получить объект customerDataJaxb, который ожидает сервер. Ошибка «Несоответствие типов (параметр номер '1')» возникает, когда вы пытаетесь передать методу объект, созданный не из той фабрики или с неправильным типом. Рассмотрим правильный способ получения типа:
Выясним причину ошибки: использование конструкций вида Сервис.ФабрикаXDTO.Пакеты[2][9] крайне опасно. Если структура WSDL на сервере изменится (добавится новое поле или тип), индексы сместятся, и ваша интеграция «сломается». Правильнее всего обращаться к типу по его имени и URI пространства имен.
// Определяем URI пространства имен (обычно указано в свойствах WS-ссылки)
ПространствоИмен = "http://service.mms.beltranssat.com/";
// Получаем тип объекта из фабрики прокси
ТипОбъекта = Сервис.ФабрикаXDTO.Тип(ПространствоИмен, "customerDataJaxb");
// Создаем экземпляр объекта
ОбъектСервисаГеоТочка = Сервис.ФабрикаXDTO.Создать(ТипОбъекта);
Этот код полностью заменяет функцию инВебСервисы.ПолучитьОбъектВебСервиса и делает ваш алгоритм устойчивым к изменениям API.
Часто объект веб-сервиса содержит вложенные коллекции (например, список товаров в заказе). В XDTO это описывается как свойства с неограниченным количеством вхождений. Проанализируем, как правильно заполнить такие данные.
Рассмотрим по шагам процесс добавления товаров в точку доставки:
good.goods основного объекта.
// Заполняем основные свойства
ЗаполнитьЗначенияСвойств(ОбъектСервисаГеоТочка, СтрокаДанных);
// Работа со списком товаров
Для Каждого СтрокаТовар Из СтрокаДанных.Товары Цикл
// Важно! Тип товара также берем из фабрики
ТипТовара = Сервис.ФабрикаXDTO.Тип(ПространствоИмен, "good");
ОбъектТовар = Сервис.ФабрикаXDTO.Создать(ТипТовара);
// Заполняем реквизиты товара (артикул, количество, вес)
ЗаполнитьЗначенияСвойств(ОбъектТовар, СтрокаТовар);
// Добавляем в список (свойство goods должно быть описано в XDTO как список)
ОбъектСервисаГеоТочка.goods.Добавить(ОбъектТовар);
КонецЦикла;
Многие современные API не имеют отдельного метода «Создать или Обновить». Вместо этого используется попытка создания, и если объект с таким ID уже существует, вызывается метод обновления. Разберем, как это реализовать в 1С:
Попытка
// Пытаемся добавить новую точку
Сервис.addPoint(ОбъектСервисаГеоТочка);
Исключение
// Если возникла ошибка (например, точка с таким ID уже есть), пытаемся обновить
Попытка
Сервис.updatePoint(ОбъектСервисаГеоТочка);
Исключение
// Если и тут ошибка - значит, проблема в данных
Сообщить("Ошибка при передаче точки " + ОбъектСервисаГеоТочка.id + ": " + ОписаниеОшибки());
КонецПопытки;
КонецПопытки;
Если вы продолжаете получать ошибку несоответствия типов, проанализируйте ситуацию с помощью встроенного отладчика 1С. Вычислите выражение Сервис.ФабрикаXDTO.Тип(ПространствоИмен, "customerDataJaxb"). В появившемся окне вы увидите структуру Properties. Убедитесь, что:
double, передавайте Число, если dateTime — передавайте Дата.Неопределено.Использование прямой работы с ФабрикойXDTO вашего WSПрокси — это наиболее надежный и «чистый» способ реализации интеграции, который не зависит от сторонних модулей и гарантирует правильную передачу типов данных на сторону веб-сервиса.