HTTP-сервис в 1С 8.3 от пустой ветки до рабочего API

· 11 мин

Содержание

Веб-сервис в 1С 8.3 создают в конфигураторе: ветка Общие → HTTP-сервисы (REST) или Общие → Web-сервисы (SOAP). Добавляете сервис, задаёте корневой URL и шаблон адреса, пишете функцию-обработчик метода и публикуете базу на веб-сервере. После этого сервис отвечает по адресу вида http://сервер/база/hs/корневой-url/шаблон.

Внешняя система стучится в базу, а вы не знаете, с какой стороны браться? Хватит одного рабочего дня: объект метаданных, два обработчика, публикация и проверка через curl.

Какой сервис выбрать: HTTP или SOAP

В платформе два механизма. Оба живут в ветке Общие дерева метаданных и оба публикуются через веб-сервер.

HTTP-сервисWeb-сервис (SOAP)
Протоколобычный HTTP, любой формат телаSOAP поверх HTTP, XML
Формат данныхJSON, XML, текст, файлы — на ваше усмотрениеXML по схеме XDTO-пакета
Описание для клиентапишете самиWSDL генерируется автоматически
Адрес в публикации/hs//ws/
Когда братьсайты, мобильные приложения, интеграции на JSONбанки, госсистемы, старые интеграции, где SOAP задан требованием

HTTP-сервисы появились в платформе 8.3.5. Сегодня почти все новые интеграции делают на них: сайт или маркетплейс-коннектор ждёт JSON, а не SOAP-конверт.

💡 Если партнёр прислал WSDL и просит «поднять веб-сервис по этой схеме» — нужен именно SOAP. Во всех остальных случаях начинайте с HTTP-сервиса.

Как устроен запрос к HTTP-сервису

Путь запроса проходит четыре звена:

  1. 🌐 Клиент отправляет запрос на веб-сервер (IIS или Apache).
  2. 🔌 Модуль расширения веб-сервера 1С принимает его и находит публикацию по имени (/база/).
  3. 🔑 Платформа аутентифицирует пользователя информационной базы и открывает сеанс.
  4. ⚙️ По корневому URL и шаблону выбирается метод, вызывается его функция в модуле сервиса. Функция возвращает объект HTTPСервисОтвет.

Весь код обработчика выполняется на сервере 1С с правами того пользователя, под которым пришёл запрос. От этого зависят и безопасность, и многие ошибки 500.

Создание HTTP-сервиса в конфигураторе

Работаем в конфигураторе с правами на изменение конфигурации. Если база на поддержке, удобнее вынести сервис в расширение: HTTP-сервисы можно добавлять в расширения, и обновления типовой конфигурации его не затронут.

Шаг 1. Объект и корневой URL

  1. В дереве метаданных раскройте Общие, щёлкните правой кнопкой по HTTP-сервисы → Добавить.
  2. Задайте Имя — например, Заказы.
  3. Заполните Корневой URL — латиницей, без пробелов: orders.

Корневой URL — первая часть адреса после /hs/. Имя объекта в адрес не попадает, поэтому его можно писать по-русски.

Шаг 2. Шаблоны URL

На вкладке шаблонов добавьте адреса, которые сервис будет обслуживать:

  • / — список заказов;
  • /{number} — один заказ, где number — параметр;
  • /* — «всё остальное», удобно для собственного разбора пути.

Параметр в фигурных скобках платформа извлекает сама. В коде он доступен через Запрос.ПараметрыURL["number"].

Шаг 3. Методы

Внутри каждого шаблона добавьте методы — GET, POST, PUT, DELETE и другие. Для каждого метода в свойстве Обработчик нажмите лупу: платформа создаст в модуле сервиса пустую функцию с параметром Запрос.

В нашем примере:

  • шаблон /{number}, метод GET — получить заказ;
  • шаблон /, метод POST — создать заказ.

Шаг 4. Свойства сеанса

У объекта сервиса есть ещё два свойства, о которых часто забывают:

  • Повторное использование сеансов — Не использовать, Использовать или Автоматически. При частых коротких запросах повторное использование экономит время на открытие сеанса.
  • Время жизни сеанса — сколько секунд держать неиспользуемый сеанс.

Каждый живой сеанс HTTP-сервиса занимает лицензию, как обычный пользователь. Большое время жизни при всплеске запросов быстро съедает пул лицензий.

Обработчики запросов: код GET и POST

Функция-обработчик получает объект HTTPСервисЗапрос и обязана вернуть HTTPСервисОтвет. Из запроса вы берёте всё, что прислал клиент.

Что нужноКак получить
Параметр из шаблона {number}Запрос.ПараметрыURL["number"]
Параметр строки ?status=newЗапрос.ПараметрыЗапроса.Получить("status")
ЗаголовокЗапрос.Заголовки.Получить("Content-Type")
Тело как текстЗапрос.ПолучитьТелоКакСтроку()
Тело как файлЗапрос.ПолучитьТелоКакДвоичныеДанные()
HTTP-методЗапрос.HTTPМетод

ПараметрыЗапроса.Получить() возвращает Неопределено, если параметра нет. Проверяйте это до использования, иначе первый же запрос без параметра упадёт с ошибкой 500.

Метод GET: отдать заказ по номеру

Название документа и реквизитов у вас может быть другим — подставьте свои.

Функция ЗаказGET(Запрос)

	Номер = Запрос.ПараметрыURL["number"];

	ЗапросДанных = Новый Запрос(
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Заказ.Номер КАК Номер,
	|	Заказ.Дата КАК Дата,
	|	Заказ.СуммаДокумента КАК Сумма
	|ИЗ
	|	Документ.ЗаказКлиента КАК Заказ
	|ГДЕ
	|	Заказ.Номер = &Номер");
	ЗапросДанных.УстановитьПараметр("Номер", Номер);

	Выборка = ЗапросДанных.Выполнить().Выбрать();
	Если Не Выборка.Следующий() Тогда
		Возврат ОтветJSON(404, Новый Структура("error", "Заказ не найден"));
	КонецЕсли;

	Данные = Новый Структура;
	Данные.Вставить("number", Выборка.Номер);
	Данные.Вставить("date", Выборка.Дата);
	Данные.Вставить("sum", Выборка.Сумма);

	Возврат ОтветJSON(200, Данные);

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

Переменная называется ЗапросДанных, а не Запрос: имя Запрос уже занято параметром функции. Это частая причина странных ошибок у тех, кто пишет первый сервис.

Общая функция ответа

Чтобы не повторять одни и те же пять строк в каждом методе, вынесите сборку ответа в отдельную функцию модуля:

Функция ОтветJSON(КодСостояния, Данные)

	Запись = Новый ЗаписьJSON;
	Запись.УстановитьСтроку();

	Настройки = Новый НастройкиСериализацииJSON;
	Настройки.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
	ЗаписатьJSON(Запись, Данные, Настройки);

	Ответ = Новый HTTPСервисОтвет(КодСостояния);
	Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
	Ответ.УстановитьТелоИзСтроки(Запись.Закрыть(), КодировкаТекста.UTF8,
		ИспользованиеByteOrderMark.НеИспользовать);

	Возврат Ответ;

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

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

  • 💡 charset=utf-8 в заголовке — без него кириллица у части клиентов превращается в «кракозябры».
  • 💡 ИспользованиеByteOrderMark.НеИспользовать — без явного запрета в начало тела может попасть метка BOM, и строгие JSON-парсеры (например, в PHP) отказываются разбирать ответ.

Метод POST: принять данные

Функция ЗаказыPOST(Запрос)

	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
	Попытка
		Данные = ПрочитатьJSON(Чтение, Истина, "date", ФорматДатыJSON.ISO);
	Исключение
		Возврат ОтветJSON(400, Новый Структура("error", "Некорректный JSON"));
	КонецПопытки;
	Чтение.Закрыть();

	Клиент = Данные.Получить("client");
	Если Клиент = Неопределено Тогда
		Возврат ОтветJSON(400, Новый Структура("error", "Не указан client"));
	КонецЕсли;

	// здесь создание и запись документа

	Возврат ОтветJSON(201, Новый Структура("result", "created"));

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

Второй параметр Истина читает объекты JSON в Соответствие, а не в Структуру. Так безопаснее: ключи вида order-id или 1c недопустимы как имена полей структуры, и чтение без этого флага упадёт.

Третий и четвёртый параметры говорят платформе, что поле date нужно сразу превратить в тип Дата из формата ISO.

JSON в 1С: как типы превращаются в текст и обратно

ЗаписатьJSON понимает только примитивы и коллекции. Ссылку на справочник или документ «как есть» он не запишет — будет исключение.

Тип 1СВ JSONКомментарий
Строка"текст"
Число1250.5дробная часть через точку
Булевоtrue / false
Дата"2026-10-07T12:00:00"только с НастройкиСериализацииJSON, иначе исключение
Неопределеноnull
Структура, Соответствиеобъект {}у соответствия ключи должны быть строками
Массивмассив []
Ссылка на объект—передавайте код, номер или Строка(Ссылка.УникальныйИдентификатор())

Ссылки и идентификаторы

Самый надёжный ключ для связи с внешней системой — уникальный идентификатор объекта. Он не меняется при перенумерации и одинаков во всех копиях базы.

  • 📤 Отдать: Строка(Ссылка.УникальныйИдентификатор()).
  • 📥 Найти по присланному: Справочники.Контрагенты.ПолучитьСсылку(Новый УникальныйИдентификатор(Строка)).

Ссылку, полученную через ПолучитьСсылку, проверьте на существование объекта: метод вернёт ссылку и на несуществующий объект, ошибка вылезет позже, при обращении к реквизитам.

Сериализация XDTO, если нужен объект целиком

Когда нужно выгрузить документ со всеми табличными частями «один в один» для другой базы 1С, используйте СериализаторXDTO.ЗаписатьJSON(Запись, Объект). Получится JSON в формате платформы, громоздкий, но без ручного перечисления полей. Для внешних систем он неудобен — им отдавайте собственную структуру, как в примере выше.

Публикация базы на веб-сервере

Пока база не опубликована, сервис существует только в метаданных. Для публикации нужны:

  • 🖥️ веб-сервер — IIS на Windows или Apache 2.4;
  • 🔌 модули расширения веб-сервера — компонент ставится из дистрибутива платформы той же разрядности, что и веб-сервер;
  • 🔐 конфигуратор, запущенный от имени администратора Windows — иначе он не сможет записать настройки веб-сервера.

Публикация из конфигуратора

  1. Меню Администрирование → Публикация на веб-сервере.
  2. Укажите Имя публикации — это часть адреса, например trade.
  3. Выберите веб-сервер и каталог публикации.
  4. На вкладке HTTP-сервисов отметьте флаг публикации по умолчанию или конкретные сервисы.
  5. Нажмите Опубликовать. Для Apache после этого перезапустите службу веб-сервера.

Перезапуск Apache или пула IIS обрывает все текущие веб-сеансы этого сервера: веб-клиент, другие сервисы, мобильные приложения. Делайте это вне рабочего пика.

Публикация командой webinst

На сервере без графического интерфейса или в скрипте развёртывания используйте утилиту webinst из каталога bin платформы:

webinst -publish -apache24 -wsdir trade -dir "C:\Apache24\htdocs\trade" ^
  -connstr "Srvr=app-srv;Ref=trade;" -confpath "C:\Apache24\conf\httpd.conf"

Для IIS вместо -apache24 указывают -iis, параметр -confpath не нужен. Подробности по ключам — в выводе webinst без параметров.

Итоговый адрес и проверка

Адрес собирается из трёх частей:

http://сервер/trade/hs/orders/000000123
         │      │    │      └─ параметр шаблона {number}
         │      │    └──────── корневой URL сервиса
         │      └───────────── имя публикации
         └──────────────────── веб-сервер

Проверьте ответ из командной строки:

curl -u Integration:Пароль http://сервер/trade/hs/orders/000000123

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

Права и безопасность HTTP-сервиса

Сервис открывает базу наружу. Ошибка в настройке доступа — это утечка данных, а не просто неудобство.

Отдельный пользователь под интеграцию

  • 👤 Заведите в базе пользователя только для интеграции, например Integration, с аутентификацией 1С:Предприятия.
  • 🎭 Дайте ему роль, в которой есть права только на нужные объекты: чтение заказов, добавление документов — и ничего больше.
  • 🚫 Не давайте этой учётной записи полные права и не запускайте под ней интерактивный клиент.

Клиент передаёт логин и пароль в заголовке Authorization по схеме Basic. Если пользователя нет или пароль неверный, веб-сервер вернёт 401.

HTTPS обязателен

Basic-аутентификация пересылает пароль в кодировке Base64 — это не шифрование. По голому HTTP пароль читается из трафика.

Публикуйте сервис наружу только по HTTPS. Сертификат настраивается на стороне веб-сервера, сама 1С в этом не участвует.

Чего не делать

  • ❌ Не прописывайте логин и пароль в строке соединения публикации (Usr=, Pwd=) ради «анонимного» доступа: тогда сервис открыт любому, кто узнал адрес.
  • ❌ Не включайте УстановитьПривилегированныйРежим(Истина) в обработчике целиком. Привилегированный режим нужен точечно — например, чтобы записать служебный регистр, — и его надо выключать сразу после этого.
  • ❌ Не собирайте текст запроса склейкой строк из параметров URL. Используйте УстановитьПараметр, как в примере GET: это закрывает подстановку чужого кода в запрос.

💡 Если наружу смотрит только один сервис, создайте под него отдельную публикацию, где отмечен только он. Веб-клиент и остальные сервисы тогда снаружи просто не видны.

Отладка и диагностика HTTP-запросов

Обработчик выполняется на сервере, поэтому точку останова в модуле сервиса просто так не поймать. Нужно подключить отладку к сеансам HTTP-сервисов.

Отладка в конфигураторе

  1. Включите отладку в публикации: в файле default.vrd добавьте элемент <debug enable="true" protocol="tcp" url="tcp://имя-компьютера-с-конфигуратором"/> или включите отладку в окне публикации, если ваша версия платформы это показывает.
  2. В конфигураторе откройте Отладка → Подключение, нажмите Автоматическое подключение и отметьте HTTP-сервисы.
  3. Поставьте точку останова в функции-обработчике и отправьте запрос через curl или Postman.

Конфигуратор остановится на точке, и можно смотреть содержимое Запрос: заголовки, параметры, тело.

Не оставляйте отладку включённой в рабочей публикации: каждый запрос пытается подключиться к отладчику, что замедляет ответы.

Журнал регистрации

В рабочей базе отладчик не подключишь. Пишите ключевые события в журнал:

ЗаписьЖурналаРегистрации("HTTPСервис.Заказы",
	УровеньЖурналаРегистрации.Ошибка, , ,
	"Не удалось записать заказ: " + ОписаниеОшибки());

Потом фильтруйте журнал по этому событию — увидите, кто, когда и с каким текстом ошибки обращался. Код вызывается внутри блока Исключение, иначе ОписаниеОшибки() вернёт пустую строку.

Что означает код ответа

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

Если нужен SOAP-вариант

Для Web-сервиса порядок похож, но вместо шаблонов URL — операции с типами параметров из XDTO-пакета:

  1. Создайте XDTO-пакет (Общие → XDTO-пакеты) с типами данных или используйте стандартные типы из пространства имён XML Schema.
  2. В Общие → Web-сервисы добавьте сервис, укажите Пространство имён URI и список XDTO-пакетов.
  3. Добавьте операции, параметры и тип возвращаемого значения, создайте процедуры-обработчики.
  4. Опубликуйте на вкладке Web-сервисов. Описание для клиента будет доступно по адресу http://сервер/база/ws/имя?wsdl.

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

Нужна ли отдельная лицензия на HTTP-сервис?
Отдельного вида лицензии нет. Каждый открытый сеанс HTTP-сервиса занимает клиентскую лицензию, как пользователь. Учитывайте это при выборе времени жизни сеанса.
Работает ли HTTP-сервис в файловой базе?
Да. Файловую базу тоже можно опубликовать на веб-сервере. Для рабочей нагрузки с параллельными запросами лучше клиент-серверный вариант: файловая база плохо переносит одновременную запись.
Как отдать файл, а не JSON?
Установите тело через УстановитьТелоИзДвоичныхДанных и задайте свой Content-Type, например application/pdf. Для скачивания добавьте заголовок Content-Disposition с именем файла.
Можно ли вызвать HTTP-сервис из другой базы 1С?
Да, через объекты HTTPСоединение и HTTPЗапрос. Для HTTPS передайте в HTTPСоединение объект ЗащищенноеСоединениеOpenSSL.
Почему сервис отвечает медленно на первый запрос?
На первом запросе открывается сеанс и загружается конфигурация в рабочий процесс. Включите повторное использование сеансов — последующие запросы пойдут быстрее.