Свой REST-API на 1С 8.3: от объекта в конфигураторе до первого ответа по сети

· 9 мин

Содержание

Чтобы подключить HTTP-сервис в 1С, нужно три вещи: создать объект в ветке Общие → HTTP-сервисы конфигуратора, описать в нём шаблоны URL с методами и обработчиками, а затем опубликовать базу на веб-сервере через Администрирование → Публикация на веб-сервере. После этого сервис отвечает по адресу вида http://сервер/имя_публикации/hs/корневой_URL/шаблон.

Так база 1С 8.3 получает собственный REST-API: сайт, мобильное приложение, складской терминал или другая база 1С забирают и отправляют данные обычными HTTP-запросами, без COM-соединения и без обменов через файлы.

Что подготовить до настройки HTTP-сервиса

Сервис работает только через веб-сервер. Запустить его «напрямую» из файловой или клиент-серверной базы нельзя. Перед стартом проверьте:

  • 🖥️ Веб-сервер. Подходят Apache 2.2/2.4 или IIS. На Linux — Apache.
  • 🧩 Модули расширения веб-сервера. Это компонент установщика платформы. Если при установке его не отметили, запустите установщик ещё раз и добавьте компонент. Без него в списке веб-серверов при публикации будет пусто.
  • 🔑 Права администратора Windows. Конфигуратор для публикации запускают от имени администратора: он пишет в настройки IIS или в httpd.conf.
  • 👤 Пользователь для интеграции. Отдельная учётная запись в базе, под которой будет ходить внешняя система.
  • 🛠️ Доступ к конфигурации. В типовой конфигурации на поддержке удобнее создать сервис в расширении: объект добавляется туда без снятия с поддержки и не мешает обновлениям.

Заранее решите, какой будет адрес. Корневой URL и шаблоны потом попадут в код внешней системы, и переименование сломает интеграцию.

Шаг 1. Создаём HTTP-сервис в конфигураторе

  1. Откройте конфигуратор, разверните ветку Общие → HTTP-сервисы.
  2. Нажмите «Добавить». Откроется палитра свойств нового объекта.
  3. Заполните Имя — например, API. Это имя в метаданных, во внешнем адресе оно не участвует.
  4. Заполните Корневой URL — например, api. Именно он стоит в адресе после /hs/. Пишите латиницей, без пробелов и слешей.
  5. Выберите режим повторного использования сеансов.

От последнего пункта зависит скорость и расход лицензий:

РежимКак работаетКогда выбирать
Не использоватьКаждый запрос — новый сеанс, после ответа он закрываетсяРедкие вызовы, отладка
АвтоматическиПлатформа держит сеанс между вызовами и переиспользует егоБольшинство интеграций
ИспользоватьСеанс привязывается к клиенту через cookie, клиент обязан её возвращатьКлиент, который делает серию связанных запросов

Рядом задаётся время жизни сеанса — по умолчанию 20 секунд. Каждый открытый сеанс занимает клиентскую лицензию. При частых вызовах режим «Не использовать» тратит время на старт сеанса на каждом запросе.

Шаг 2. Шаблоны URL и HTTP-методы

Внутри сервиса создаются шаблоны URL, а внутри шаблонов — методы. Шаблон отвечает за путь, метод — за глагол HTTP.

  1. В дереве сервиса добавьте шаблон, задайте ему имя (Товар) и сам шаблон: /goods/{code}.
  2. Внутри шаблона добавьте метод, в свойстве «HTTP-метод» выберите GET.
  3. В свойстве «Обработчик» нажмите на лупу. Конфигуратор создаст функцию в модуле сервиса.
  4. Для приёма данных добавьте второй шаблон /goods с методом POST.

Фигурные скобки обозначают параметр. Значение из адреса /goods/00-00000012 попадёт в обработчик как параметр code.

Пример раскладки для небольшого API:

ШаблонМетодЧто делает
/goods/{code}GETОтдаёт карточку товара
/goodsGETСписок товаров, фильтры — в параметрах ?page=2&limit=50
/goodsPOSTСоздаёт товар из JSON в теле
/goods/{code}DELETEПомечает товар на удаление

Добавьте версию в путь: /v1/goods/{code}. Когда формат ответа поменяется, вы заведёте /v2/..., а старые клиенты продолжат работать.

Параметры после знака вопроса в шаблон не пишут. Они доступны в обработчике через Запрос.ПараметрыЗапроса при любом шаблоне.

Шаг 3. Пишем обработчики запросов

Обработчик — функция в модуле HTTP-сервиса. Она получает объект HTTPСервисЗапрос и обязана вернуть HTTPСервисОтвет. Что внутри запроса:

  • 📍 Запрос.ПараметрыURL — параметры из фигурных скобок шаблона;
  • ❓ Запрос.ПараметрыЗапроса — параметры после ?;
  • 📨 Запрос.Заголовки — заголовки HTTP;
  • 📦 Запрос.ПолучитьТелоКакСтроку() — тело запроса, например JSON.

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

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

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

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

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

Обработчик GET для шаблона /goods/{code}:

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

	Код = Запрос.ПараметрыURL.Получить("code");
	Ссылка = Справочники.Номенклатура.НайтиПоКоду(Код);

	Если Ссылка.Пустая() Тогда
		Возврат ОтветJSON(404, Новый Структура("error", "Товар не найден"));
	КонецЕсли;

	Данные = Новый Структура;
	Данные.Вставить("code", Ссылка.Код);
	Данные.Вставить("name", Ссылка.Наименование);
	Возврат ОтветJSON(200, Данные);

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

Обработчик POST для шаблона /goods читает JSON и создаёт элемент:

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

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

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

	Элемент = Справочники.Номенклатура.СоздатьЭлемент();
	Элемент.Наименование = Наименование;
	Попытка
		Элемент.Записать();
	Исключение
		ЗаписьЖурналаРегистрации("API.Товары", УровеньЖурналаРегистрации.Ошибка, , ,
			ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Возврат ОтветJSON(500, Новый Структура("error", "Не удалось записать товар"));
	КонецПопытки;

	Возврат ОтветJSON(201, Новый Структура("code", Элемент.Код));

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

Пояснения к коду:

  • Второй параметр Истина в ПрочитатьJSON возвращает Соответствие, а не Структуру. Так код не упадёт, если внешняя система пришлёт ключ с дефисом или цифрой в начале.
  • Ошибка записи уходит в журнал регистрации с полным текстом, а клиент получает короткое сообщение. Подробности исключения наружу не отдавайте.
  • В типовых конфигурациях у номенклатуры есть обязательные реквизиты (вид номенклатуры, единица). Перед Записать() их нужно заполнить, иначе запись не пройдёт.

Для списка с постраничной выдачей параметры берут так: Запрос.ПараметрыЗапроса.Получить("page"). Метод вернёт Неопределено, если клиент параметр не передал, поэтому задайте значение по умолчанию. Строку переведите в число через Число() внутри Попытка, иначе запрос ?page=abc обрушит обработчик с кодом 500 вместо понятного 400. Лимит записей на страницу ограничьте сверху, например 100: так один запрос не выгрузит весь справочник и не займёт рабочий процесс на минуты.

Коды ответа подбирайте по смыслу: 200 — данные отданы, 201 — объект создан, 400 — клиент прислал не то, 404 — объекта нет, 500 — сбой на стороне 1С.

Шаг 4. Публикуем HTTP-сервисы на веб-сервере

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

Итоговый адрес собирается так:

http://srv-web/trade/hs/api/v1/goods/00-00000012
         │       │    │   └─ шаблон URL
         │       │    └───── корневой URL сервиса
         │       └────────── признак HTTP-сервисов
         └────────────────── имя публикации

Мастер создаёт в каталоге публикации файл default.vrd. Блок, отвечающий за HTTP-сервисы, выглядит так:

<httpServices publishByDefault="true"/>

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

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

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

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

Шаг 5. Права доступа и аутентификация

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

Как настроить пользователя для интеграции:

  1. Создайте пользователя, например api_site. Логин латиницей избавит от проблем с кодировкой у части HTTP-клиентов.
  2. Включите «Аутентификация 1С:Предприятия» и задайте сложный пароль.
  3. Снимите «Показывать в списке выбора» — человеку под этой записью входить незачем.
  4. Создайте отдельную роль и дайте в ней только нужные права: для примера выше — чтение и добавление справочника номенклатуры.
  5. Назначьте пользователю только эту роль.

Внешняя система передаёт логин и пароль в заголовке Basic-аутентификации. Basic передаёт пароль в открытом виде (только кодирует в Base64), поэтому снаружи сети сервис публикуют только по HTTPS.

Иногда логин и пароль зашивают в строку подключения default.vrd (Usr=...;Pwd=...), чтобы сервис отвечал без авторизации. Это рабочий вариант для закрытой сети, но пароль хранится в файле открытым текстом, а любой, кто знает адрес, работает с правами этого пользователя. Для интернета так не делайте.

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

Проверка: вызов из curl и из другой базы 1С

Самый быстрый тест — curl прямо на веб-сервере:

curl -u api_site:Пароль http://localhost/trade/hs/api/v1/goods/00-00000012

Создание товара:

curl -u api_site:Пароль -X POST -H "Content-Type: application/json" -d "{\"name\":\"Тестовый товар\"}" http://localhost/trade/hs/api/v1/goods

Если в ответе JSON — сервис подключён. Удобно держать коллекцию запросов в Postman или аналоге: там видны код ответа и заголовки.

Вызов из другой базы 1С — через HTTPСоединение:

Соединение = Новый HTTPСоединение("srv-web", 80, "api_site", "Пароль", , 30);
Запрос = Новый HTTPЗапрос("/trade/hs/api/v1/goods/00-00000012");
Ответ = Соединение.Получить(Запрос);

Если Ответ.КодСостояния = 200 Тогда
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
	Данные = ПрочитатьJSON(Чтение, Истина);
	Чтение.Закрыть();
	Сообщить("Товар: " + Данные.Получить("name"));
Иначе
	Сообщить("Ошибка " + Формат(Ответ.КодСостояния, "ЧГ=0"));
КонецЕсли;

Шестой параметр — таймаут в секундах. Без него вызывающая база может долго ждать зависший сервер. Для HTTPS передайте седьмым параметром Новый ЗащищенноеСоединениеOpenSSL и порт 443.

Для пошаговой отладки обработчика в конфигураторе откройте Отладка → Подключение и включите автоматическое подключение к сеансам HTTP-сервисов. Отладку должна разрешать и публикация. Тогда точка останова в модуле сработает при вызове из curl.

Почему HTTP-сервис не отвечает: разбор ошибок

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

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

Чем HTTP-сервис отличается от веб-сервиса в 1С?
Веб-сервис работает по протоколу SOAP и описывается WSDL. HTTP-сервис — это REST: обычные запросы GET, POST и другие, формат данных вы выбираете сами. С ним проще работать из сайтов и мобильных приложений.
Нужна ли отдельная лицензия на HTTP-сервис?
Отдельной лицензии нет. Но каждый сеанс, который открывает вызов, занимает клиентскую лицензию, как обычный пользователь. Повторное использование сеансов снижает расход.
Можно ли отдавать не JSON, а файл?
Да. В HTTPСервисОтвет можно записать двоичные данные методом УстановитьТелоИзДвоичныхДанных и указать нужный Content-Type, например application/pdf.
Работает ли HTTP-сервис в файловой базе?
Работает, если база опубликована на веб-сервере. Учётной записи веб-сервера нужны права на каталог базы. Для нагрузки от нескольких систем лучше клиент-серверный вариант.
Как ограничить доступ к сервису по IP?
Средствами веб-сервера: правилами доступа к каталогу публикации в Apache или ограничениями IP-адресов в IIS. В самом объекте 1С такой настройки нет, но адрес клиента можно проверить в коде по заголовкам запроса.