Вызов SOAP-сервиса одной базы 1С из кода другой: WSПрокси, WS-ссылки и HTTP

· 10 мин

Содержание

Чтобы обратиться к веб-сервису 1С из другой базы 1С, в серверной процедуре создают объект WSОпределения по адресу WSDL, затем WSПрокси с URI пространства имён, именем сервиса и точки подключения, и вызывают операцию как обычный метод: Прокси.GetStock("А-102"). Если WSDL известен заранее, удобнее добавить в конфигурацию объект «WS-ссылка» и создавать прокси без загрузки описания при каждом вызове.

Механизм общий для платформы 8.3 и не зависит от конфигурации: так связывают Бухгалтерию с УТ, ERP с филиальной базой, самописную базу с типовой. Ниже — рабочий код на каждый шаг, разбор ответа, ошибки и защита учётных данных.

Что проверить до первой строки кода

Сначала убедитесь, что сервис на стороне базы-источника опубликован и отвечает. Без этого отлаживать код вызова бессмысленно.

Минимум на стороне сервиса

  • 🌐 Объект «WS-сервис» в конфигурации с заполненным URI пространства имен и операциями.
  • 📤 Публикация базы на веб-сервере (IIS или Apache) с флагом «Публиковать Web-сервисы»: в Конфигураторе Администрирование → Публикация на веб-сервере.
  • 👤 Отдельный пользователь базы с ролью, где у нужных операций WS-сервиса включено право «Использование».
  • 🔒 HTTPS на веб-сервере, если запросы идут через интернет или между площадками.

Проверка простая: откройте в браузере адрес вида https://erp.example.local/trade/ws/exchange.1cws?wsdl. Здесь trade — имя публикации, exchange.1cws — свойство «Имя файла публикации» WS-сервиса. Браузер спросит логин и пароль и покажет XML-описание. Ошибка 404 — сервис не опубликован, 401 — неверный пользователь или нет прав.

Какие данные взять из WSDL

Для вызова понадобятся четыре значения. Все они есть в самом WSDL.

Что нужноГде найти в WSDLПример
URI пространства имёнатрибут targetNamespace в корнеhttp://www.example.ru/exchange
Имя сервисаэлемент service, атрибут nameExchange
Имя точки подключенияэлемент port внутри serviceExchangeSoap
Имена операцийэлементы operationGetStock, PostOrder

У сервисов 1С точек подключения обычно две: <ИмяСервиса>Soap и <ИмяСервиса>Soap12. Берите любую, для обмена между базами 1С разницы нет.

Где выполняется код

WSПрокси недоступен в тонком клиенте и веб-клиенте. Вызов размещают на сервере: в процедуре формы с директивой &НаСервереБезКонтекста или в серверном общем модуле. В толстом клиенте и внешнем соединении объект тоже работает, но держать вызов на сервере правильнее: там сертификаты, доступ к сети и единые настройки прокси.

Три способа вызвать веб-сервис 1С: какой выбрать

СпособКогда подходитМинусы
Динамический WSОпределения + WSПроксиАдрес сервиса меняется, хранится в настройкахWSDL загружается при каждом создании прокси, это лишний запрос
WS-ссылка (статический прокси)Сервис стабилен, WSDL известен при разработкеПри изменении сервиса WS-ссылку надо обновить в Конфигураторе
Ручной SOAP через HTTPСоединениеНужен полный контроль над XML, заголовками, логированиемКонверт и разбор ответа пишете сами

Для типового обмена между двумя своими базами чаще всего выбирают первый способ с кешированием прокси. WS-ссылку — когда сервис годами не меняется. Ручной HTTP — для диагностики и нестандартных случаев.

Создание прокси и подключение к веб-сервису 1С

Динамический прокси

Базовый пример: получить остаток товара из базы УТ.

&НаСервереБезКонтекста
Функция ПолучитьОстатокНаСервере(Артикул)

    АдресWSDL = "https://erp.example.local/trade/ws/exchange.1cws?wsdl";
    URI       = "http://www.example.ru/exchange";
    Таймаут   = 30;

    Пользователь = "ws_exchange";
    Пароль       = ПарольИзБезопасногоХранилища(); // см. раздел о безопасности

    SSL = Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС);

    Определения = Новый WSОпределения(АдресWSDL, Пользователь, Пароль, , Таймаут, SSL);
    Прокси = Новый WSПрокси(Определения, URI, "Exchange", "ExchangeSoap", , Таймаут, SSL);
    Прокси.Пользователь = Пользователь;
    Прокси.Пароль       = Пароль;

    Возврат Прокси.GetStock(Артикул);

КонецФункции

Обратите внимание на две вещи. Логин и пароль задаются дважды: в WSОпределения — чтобы скачать WSDL, в свойствах прокси — для самих вызовов. Если забыть второе, WSDL загрузится, а операция вернёт 401.

Таймаут по умолчанию не ограничен. Если удалённая база зависнет, сеанс пользователя будет ждать бесконечно. Ставьте явное значение: 30–60 секунд для коротких операций, больше — для тяжёлых выгрузок.

Статический прокси через WS-ссылку

В дереве конфигурации откройте ветку Общие → WS-ссылки, добавьте новую и укажите адрес WSDL. Конфигуратор скачает описание и сохранит его внутри конфигурации. Дальше код короче:

Прокси = WSСсылки.ОбменУТ.СоздатьWSПрокси(
    "http://www.example.ru/exchange", "Exchange", "ExchangeSoap", , 30, SSL);
Прокси.Пользователь = Пользователь;
Прокси.Пароль       = Пароль;
Остаток = Прокси.GetStock(Артикул);

WSDL при вызове не загружается, поэтому первый запрос быстрее. Плата за это — при добавлении операции или смене типов на стороне сервиса WS-ссылку нужно перезагрузить и обновить конфигурацию базы-клиента.

Кеш прокси в БСП

В конфигурациях на Библиотеке стандартных подсистем (БП 3.0, ЗУП 3.1, УТ 11) есть готовая обёртка: функции ОбщегоНазначения.ПараметрыПодключенияWSПрокси() и ОбщегоНазначения.СоздатьWSПрокси(). Она кеширует WSDL и учитывает настройки прокси-сервера из подсистемы получения файлов из интернета. Если пишете расширение к типовой, пользуйтесь ей, а не собственным кешем.

Как передать параметры и отправить запрос к веб-сервису

Простые типы

Строки, числа, даты и булево передаются напрямую позиционными параметрами — в том порядке, в каком они объявлены у операции. Имена параметров на стороне клиента значения не имеют.

Сложные типы через XDTO

Если операция принимает объект (заказ со строками), создайте его через фабрику XDTO самого прокси:

Фабрика = Прокси.ФабрикаXDTO;

Заказ = Фабрика.Создать(Фабрика.Тип(URI, "Order"));
Заказ.Number = "А-102";
Заказ.Date   = ТекущаяДатаСеанса();

ТипСтроки = Фабрика.Тип(URI, "OrderLine");
Для Каждого Строка Из СтрокиЗаказа Цикл
    СтрокаXDTO = Фабрика.Создать(ТипСтроки);
    СтрокаXDTO.Sku = Строка.Артикул;
    СтрокаXDTO.Qty = Строка.Количество;
    Заказ.Lines.Добавить(СтрокаXDTO);
КонецЦикла;

НомерВБазеУТ = Прокси.PostOrder(Заказ);

Заказ.Lines.Добавить() работает, когда свойство Lines описано в пакете XDTO как список (верхняя граница −1). Имена типов и свойств чувствительны к регистру и должны совпадать с пакетом XDTO сервиса до буквы.

Когда проще передать строку

Для крупных обменов многие передают одну строку с JSON или XML, а разбирают её уже внутри сервиса. Пакет XDTO при этом не нужен, а новые поля не требуют обновлять WS-ссылку. Минус — проверку структуры придётся писать вручную.

Ручной SOAP через HTTPСоединение

Тот же вызов без прокси. Полезно, когда нужно увидеть «сырой» ответ или сервис отдаёт WSDL с ошибками.

Конверт =
"<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
|   xmlns:ex=""http://www.example.ru/exchange"">
|  <soap:Body>
|    <ex:GetStock><ex:Sku>А-102</ex:Sku></ex:GetStock>
|  </soap:Body>
|</soap:Envelope>";

Соединение = Новый HTTPСоединение("erp.example.local", 443, Пользователь, Пароль, , 30, SSL);
Запрос = Новый HTTPЗапрос("/trade/ws/exchange.1cws");
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("SOAPAction", ЗначениеSOAPActionИзWSDL);
Запрос.УстановитьТелоИзСтроки(Конверт, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);

Ответ = Соединение.ОтправитьДляОбработки(Запрос);
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку("UTF-8");

Значение SOAPAction возьмите из атрибута soapAction нужной операции в WSDL. Имена элементов тела — точно как в описании операции.

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

Что возвращает операция

  • 🔢 Простой тип — сразу значение 1С: строку, число, дату.
  • 📦 Объект XDTO — читайте свойства через точку: Ответ.Status, Ответ.Lines.
  • 📋 Список — перебирайте Для Каждого, у списка XDTO есть Количество().
  • ⬜ Пустое значение — если свойство необязательное и не заполнено, придёт Неопределено. Проверяйте перед обращением к вложенным полям.

Обёртка с журналом регистрации

Любой вызов по сети может упасть. Оборачивайте его в Попытка и пишите подробности в журнал регистрации, а пользователю показывайте короткий текст:

Попытка
    Остаток = Прокси.GetStock(Артикул);
Исключение
    Инфо = ИнформацияОбОшибке();
    ЗаписьЖурналаРегистрации("Обмен.ВызовWS",
        УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеПредставлениеОшибки(Инфо));
    ВызватьИсключение "Сервис УТ недоступен: " + КраткоеПредставлениеОшибки(Инфо);
КонецПопытки;

Если внутри операции сервиса сработал ВызватьИсключение "Товар не найден", клиент получит исключение, и текст сервиса будет в описании ошибки. Это удобный способ вернуть бизнес-ошибку, но для ожидаемых ситуаций лучше возвращать код результата в ответе: исключение на клиенте не отличить от обрыва связи без разбора текста.

Частые сбои и их причины

Диагностика: выберите симптом

Правило про сервер 1С касается всех сетевых проверок: адрес, сертификаты, прокси, брандмауэр проверяют на той машине, где работает рабочий процесс 1С. Из браузера пользователя сервис может открываться, а с сервера — нет.

Долгие вызовы: фоновые задания и очередь

Синхронный вызов блокирует форму, пока сервис не ответит. Для операций дольше 5–10 секунд это неудобно, а для пакетной отправки сотен документов — недопустимо.

Фоновое задание

Вынесите вызов в экспортную процедуру серверного общего модуля и запустите её в фоне:

Параметры = Новый Массив;
Параметры.Добавить(ЗаказСсылка);
Параметры.Добавить(АдресРезультата); // временное хранилище для ответа

ФоновыеЗадания.Выполнить("ОбменСУТ.ОтправитьЗаказ", Параметры,
    "ОтправкаЗаказа_" + ЗаказСсылка.УникальныйИдентификатор(),
    "Отправка заказа в УТ");

Ключ задания не даст запустить два одинаковых процесса одновременно: повторный запуск с тем же ключом, пока первый активен, вызовет ошибку. Результат процедура кладёт во временное хранилище через ПоместитьВоВременноеХранилище, а форма периодически проверяет его обработчиком ожидания.

В типовых конфигурациях на БСП для этого есть подсистема «Длительные операции»: на сервере ДлительныеОперации.ВыполнитьВФоне, на клиенте ожидание через ДлительныеОперацииКлиент. Она сама рисует индикатор и забирает результат.

Очередь с повторами

Для обменов, которые не должны теряться, надёжнее схема с очередью:

  1. Документ при записи попадает в регистр сведений «очередь отправки» со статусом «Ожидает».
  2. Регламентное задание раз в 1–5 минут выбирает записи и вызывает сервис.
  3. Успех — статус «Отправлено» и ответ сервиса в записи.
  4. Ошибка — счётчик попыток +1 и текст ошибки; после 5 попыток статус «Ошибка» и уведомление ответственному.

Так обрыв связи с удалённой базой не мешает работе пользователей, а все неудачные отправки видны в одном списке.

Учётные данные и защита канала

Пароль, вписанный строкой в модуль, увидит любой, кто откроет конфигурацию или выгрузит её в файлы. Это самая частая дыра в самописных интеграциях.

Где хранить логин и пароль

  • 🔐 В БСП — безопасное хранилище: ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(Владелец, Пароль) и чтение через ПрочитатьДанныеИзБезопасногоХранилища. Данные недоступны обычным пользователям, читать их можно в привилегированном режиме.
  • 🗂️ Без БСП — отдельный регистр сведений или константа, права на которые есть только у роли администратора; чтение в серверном коде.
  • 🚫 Не храните пароль в реквизитах формы, обработчиках клиента и макетах.

Права пользователя сервиса

Создайте в базе-сервисе отдельного пользователя только для интеграции. Дайте ему одну роль: право «Использование» на нужные операции WS-сервиса и чтение тех данных, которые операции возвращают. Интерактивный вход ему не нужен — снимите флаг входа в программу. Если пароль утечёт, им не получится открыть базу и посмотреть бухгалтерию.

Канал и сертификаты

  • 🔒 Публикуйте сервис только по HTTPS, если трафик выходит за пределы локальной сети. При Basic-аутентификации логин и пароль идут в каждом запросе.
  • 📜 Передавайте Новый СертификатыУдостоверяющихЦентровОС в ЗащищенноеСоединениеOpenSSL: тогда платформа проверит сертификат сервера. Конструктор без этого параметра соединение шифрует, но подлинность сервера не проверяет.
  • 🧱 Ограничьте доступ к публикации на веб-сервере по IP базы-клиента, если адрес постоянный.
  • 📝 Не пишите в журнал регистрации тело запроса целиком, если в нём персональные данные или пароли.

Если на сервере работает профиль безопасности или конфигурация вызывает код в безопасном режиме, сетевой доступ к адресу сервиса нужно разрешить отдельно. В БСП это делается через запрос разрешений на использование внешних ресурсов.

Частые вопросы

Можно ли вызвать веб-сервис 1С из тонкого клиента?
Нет, объект WSПрокси в тонком и веб-клиенте недоступен. Вызов делают в серверной процедуре, а форма получает результат через серверный вызов.
Как обратиться к веб-сервису той же самой базы?
Технически так же, через публикацию на веб-сервере. Но для своей базы это лишний круг через HTTP: вызывайте общий модуль, который использует операция сервиса, напрямую.
Нужна ли отдельная лицензия на вызовы веб-сервиса?
Каждый вызов к опубликованной базе открывает сеанс веб-сервиса. Порядок лицензирования таких сеансов зависит от типа ключей и версии платформы, поэтому проверьте его по документации к вашей поставке до запуска массового обмена.
Чем WS-сервис отличается от HTTP-сервиса для обмена между базами 1С?
WS-сервис работает по SOAP с описанием WSDL и строгой типизацией через XDTO. HTTP-сервис — произвольные запросы, чаще с JSON. Для связки двух баз 1С оба подходят; SOAP проще, если нужны готовые прокси и проверка типов.
Почему первый вызов медленный, а следующие быстрые?
При первом создании WSПрокси платформа скачивает и разбирает WSDL, а база-сервис стартует сеанс. Кешируйте прокси или используйте WS-ссылку, чтобы не загружать описание при каждом вызове.