Веб-сервис 1С — это объект конфигурации, который публикует операции информационной базы по протоколу SOAP. Структура передаваемых данных описывается в XDTO-пакете, у веб-сервиса задаются операции с параметрами и типом возвращаемого значения, а у каждой операции — функция-обработчик в модуле сервиса. После публикации базы на веб-сервере платформа сама отдаёт WSDL по адресу http://сервер/ИмяПубликации/ws/ИмяФайла?wsdl, и другая база вызывает операции через WSОпределения и WSПрокси.

Соберём рабочий пример: операция возвращает таблицу продаж за период (контрагент, номенклатура, количество, сумма), а другая база 1С получает её и заполняет табличную часть.

Когда выбирать веб-сервис, а не HTTP-сервис

Веб-сервис (SOAP)HTTP-сервис (REST)
КонтрактСтрогий, WSDL генерируется платформойОписывается вручную
ФорматXML по XDTO-схемеЛюбой, обычно JSON
Вызов из 1СWSПрокси — операции вызываются как методыHTTPСоединение, разбор ответа вручную
Кому удобенОбмен между базами 1С, корпоративные SOAP-системыСайты, мобильные приложения, сервисы на других языках

Для интеграции 1С с 1С веб-сервис по-прежнему удобен: типы проверяются автоматически, а вызов операции выглядит как обычная функция. Для внешних систем я чаще делаю HTTP-сервисы.

Шаг 1. XDTO-пакет с типами данных

В дереве метаданных: Общие → XDTO-пакеты → Добавить. В свойствах укажите URI пространства имён — уникальную строку, обычно в виде адреса, например http://example.local/sales. Она понадобится и в коде сервиса, и на стороне клиента.

Добавьте два типа объектов.

СтрокаПродаж — одна строка таблицы:

СвойствоТипПространство имён типа
GUIDКонтрагентаstringhttp://www.w3.org/2001/XMLSchema
GUIDНоменклатурыstringhttp://www.w3.org/2001/XMLSchema
Количествоdecimalhttp://www.w3.org/2001/XMLSchema
Суммаdecimalhttp://www.w3.org/2001/XMLSchema

ТаблицаПродаж — контейнер с одним свойством Строка типа СтрокаПродаж из нашего пакета. У этого свойства установите верхнюю границу (максимальное количество) = -1 и нижнюю = 0: свойство станет списком из произвольного числа строк.

Веб-сервис 1С: XDTO-тип таблицы как контейнер со множеством строк
Веб-сервис 1С: XDTO-тип таблицы как контейнер со множеством строк

Для денег и количества используйте decimal, а не float: двоичная плавающая точка даёт погрешности в копейках.

Шаг 2. Веб-сервис и операция

Общие → Web-сервисы → Добавить, имя Продажи.

  1. Закладка «Прочее»: URI пространства имён сервиса (можно тот же, что у пакета), в Пакеты XDTO выберите созданный пакет, Имя файла публикации — например sales.1cws.
  2. Закладка «Операции»: добавьте операцию ПродажиЗаПериод. Тип возвращаемого значения — ТаблицаПродаж из нашего пакета, установите «Возможно пустое».
  3. У операции добавьте параметры ДатаНачала и ДатаОкончания с типом dateTime из http://www.w3.org/2001/XMLSchema, направление — входной.
  4. В свойстве «Имя процедуры» операции нажмите кнопку открытия — платформа создаст функцию в модуле сервиса.

Шаг 3. Функция операции

1С
// Возвращает продажи за период в виде объекта XDTO «ТаблицаПродаж».
Функция ПродажиЗаПериод(ДатаНачала, ДатаОкончания)

	ПространствоИмен = "http://example.local/sales";
	ТипТаблица = ФабрикаXDTO.Тип(ПространствоИмен, "ТаблицаПродаж");
	ТипСтрока = ФабрикаXDTO.Тип(ПространствоИмен, "СтрокаПродаж");

	Результат = ФабрикаXDTO.Создать(ТипТаблица);

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Продажи.Контрагент КАК Контрагент,
	|	Продажи.Номенклатура КАК Номенклатура,
	|	Продажи.КоличествоОборот КАК Количество,
	|	Продажи.СуммаОборот КАК Сумма
	|ИЗ
	|	РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаОкончания, , ) КАК Продажи";
	Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаНачала));
	Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Строка = ФабрикаXDTO.Создать(ТипСтрока);
		Строка.GUIDКонтрагента = Строка(Выборка.Контрагент.УникальныйИдентификатор());
		Строка.GUIDНоменклатуры = Строка(Выборка.Номенклатура.УникальныйИдентификатор());
		Строка.Количество = Выборка.Количество;
		Строка.Сумма = Выборка.Сумма;
		Результат.Строка.Добавить(Строка);
	КонецЦикла;

	Возврат Результат;

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

Несколько моментов:

  • ФабрикаXDTO.Тип(URI, Имя) короче, чем получение через коллекцию пакетов, и делает то же самое.
  • Одиночные свойства присваиваются напрямую. Метод Добавить есть только у свойств-списков (с верхней границей -1), в нашем случае — у Строка.
  • Вызов УникальныйИдентификатор() у ссылки не обращается к базе — GUID берётся из самой ссылки.
  • Если продаж нет, возвращается пустая таблица, а не Неопределено — клиенту не нужно проверять два варианта.

Шаг 4. Публикация

Веб-сервис доступен только после публикации базы на веб-сервере (Apache или IIS) с включённой публикацией веб-сервисов. В конфигураторе это «Администрирование → Публикация на веб-сервере», где нужно отметить сам сервис. Проверка — открыть в браузере:

bash
curl -u Пользователь:Пароль "http://srv/trade/ws/sales.1cws?wsdl"

Должен вернуться XML с описанием WSDL. Если приходит 404 или ошибка 500 — проблема в публикации или правах, а не в коде. Настройку веб-сервера под 1С с HTTPS я делаю в рамках услуги веб-доступ к 1С.

Шаг 5. Вызов из другой базы

1С
&НаСервере
Процедура ЗагрузитьПродажиНаСервере()

	АдресWSDL = "http://srv/trade/ws/sales.1cws?wsdl";
	Пользователь = "exchange";
	Пароль = ПарольОбмена(); // храните пароль не в коде, а в безопасном хранилище

	Определения = Новый WSОпределения(АдресWSDL, Пользователь, Пароль);
	Прокси = Новый WSПрокси(Определения, "http://example.local/sales", "Продажи", "ПродажиSoap");
	Прокси.Пользователь = Пользователь;
	Прокси.Пароль = Пароль;

	Таблица = Прокси.ПродажиЗаПериод(Объект.ДатаНачала, Объект.ДатаОкончания);

	Объект.Продажи.Очистить();
	Если Таблица = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Для Каждого СтрокаXDTO Из Таблица.Строка Цикл
		НоваяСтрока = Объект.Продажи.Добавить();
		НоваяСтрока.Контрагент = Справочники.Контрагенты.ПолучитьСсылку(
			Новый УникальныйИдентификатор(СтрокаXDTO.GUIDКонтрагента));
		НоваяСтрока.Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(
			Новый УникальныйИдентификатор(СтрокаXDTO.GUIDНоменклатуры));
		НоваяСтрока.Количество = СтрокаXDTO.Количество;
		НоваяСтрока.Сумма = СтрокаXDTO.Сумма;
	КонецЦикла;

КонецПроцедуры

Параметры конструктора WSПрокси — URI пространства имён сервиса, имя сервиса и имя точки подключения. Все три значения берите из WSDL: targetNamespace, элемент service и port. Точки подключения у сервисов 1С обычно называются <Имя>Soap и <Имя>Soap12.

ПолучитьСсылку по GUID работает, только если справочники в двух базах синхронизированы по идентификаторам (например, ведутся обменом). Если нет — ищите элементы по ИНН, артикулу или коду и обрабатывайте ненайденные.

Типичные ошибки

  • Добавить для обычного свойства. Ошибка «Метод объекта не обнаружен» — свойство не является списком; присваивайте значение напрямую.
  • Неверный URI пространства имён. Строка в коде должна совпадать с URI пакета до символа, включая регистр и завершающий слеш.
  • float для сумм. Погрешности округления; используйте decimal.
  • WSDL каждый раз. Новый WSОпределения скачивает и разбирает WSDL при каждом вызове. При частых обращениях кэшируйте определения или используйте объект конфигурации «WS-ссылка».
  • Пароль в коде. Храните учётные данные в защищённом хранилище, а не в модуле.
  • Большие выборки одним ответом. Сотни тысяч строк в одном SOAP-сообщении — это гигабайты XML и таймауты. Делите период или добавляйте постраничную выгрузку.

Если базам нужно не разовое получение данных, а постоянный двусторонний обмен, разумнее смотреть на обмен между базами 1С штатными средствами; интеграции с внешними системами по SOAP и REST я делаю в рамках услуги интеграция 1С по API.

Коротко

  • Веб-сервис 1С = XDTO-пакет с типами + объект «Web-сервис» с операциями + функции-обработчики в модуле.
  • Таблица передаётся типом-контейнером со свойством-списком (верхняя граница -1).
  • WSDL доступен после публикации по адресу /ws/ИмяФайла?wsdl.
  • В другой базе вызов идёт через WSОпределения и WSПрокси, параметры берутся из WSDL.
  • Для сумм используйте decimal, для ссылок — GUID и учитывайте, совпадают ли идентификаторы в базах.