Вызов SOAP-сервиса одной базы 1С из кода другой: WSПрокси, WS-ссылки и HTTP
Содержание
Чтобы обратиться к веб-сервису
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, атрибут name | Exchange |
| Имя точки подключения | элемент port внутри service | ExchangeSoap |
| Имена операций | элементы operation | GetStock, 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–5 минут выбирает записи и вызывает сервис.
- Успех — статус «Отправлено» и ответ сервиса в записи.
- Ошибка — счётчик попыток +1 и текст ошибки; после 5 попыток статус «Ошибка» и уведомление ответственному.
Так обрыв связи с удалённой базой не мешает работе пользователей, а все неудачные отправки видны в одном списке.
Учётные данные и защита канала
Пароль, вписанный строкой в модуль, увидит любой, кто откроет конфигурацию или выгрузит её в файлы. Это самая частая дыра в самописных интеграциях.
Где хранить логин и пароль
- 🔐 В БСП — безопасное хранилище:
ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(Владелец, Пароль)и чтение черезПрочитатьДанныеИзБезопасногоХранилища. Данные недоступны обычным пользователям, читать их можно в привилегированном режиме. - 🗂️ Без БСП — отдельный регистр сведений или константа, права на которые есть только у роли администратора; чтение в серверном коде.
- 🚫 Не храните пароль в реквизитах формы, обработчиках клиента и макетах.
Права пользователя сервиса
Создайте в базе-сервисе отдельного пользователя только для интеграции. Дайте ему одну роль: право «Использование» на нужные операции WS-сервиса и чтение тех данных, которые операции возвращают. Интерактивный вход ему не нужен — снимите флаг входа в программу. Если пароль утечёт, им не получится открыть базу и посмотреть бухгалтерию.
Канал и сертификаты
- 🔒 Публикуйте сервис только по HTTPS, если трафик выходит за пределы локальной сети. При Basic-аутентификации логин и пароль идут в каждом запросе.
- 📜 Передавайте
Новый СертификатыУдостоверяющихЦентровОСвЗащищенноеСоединениеOpenSSL: тогда платформа проверит сертификат сервера. Конструктор без этого параметра соединение шифрует, но подлинность сервера не проверяет. - 🧱 Ограничьте доступ к публикации на веб-сервере по IP базы-клиента, если адрес постоянный.
- 📝 Не пишите в журнал регистрации тело запроса целиком, если в нём персональные данные или пароли.
Если на сервере работает профиль безопасности или конфигурация вызывает код в безопасном режиме, сетевой доступ к адресу сервиса нужно разрешить отдельно. В БСП это делается через запрос разрешений на использование внешних ресурсов.