Свой REST-API на 1С 8.3: от объекта в конфигураторе до первого ответа по сети
Содержание
Чтобы подключить 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-сервис в конфигураторе
- Откройте конфигуратор, разверните ветку
Общие → HTTP-сервисы. - Нажмите «Добавить». Откроется палитра свойств нового объекта.
- Заполните Имя — например,
API. Это имя в метаданных, во внешнем адресе оно не участвует. - Заполните Корневой URL — например,
api. Именно он стоит в адресе после/hs/. Пишите латиницей, без пробелов и слешей. - Выберите режим повторного использования сеансов.
От последнего пункта зависит скорость и расход лицензий:
| Режим | Как работает | Когда выбирать |
|---|---|---|
| Не использовать | Каждый запрос — новый сеанс, после ответа он закрывается | Редкие вызовы, отладка |
| Автоматически | Платформа держит сеанс между вызовами и переиспользует его | Большинство интеграций |
| Использовать | Сеанс привязывается к клиенту через cookie, клиент обязан её возвращать | Клиент, который делает серию связанных запросов |
Рядом задаётся время жизни сеанса — по умолчанию 20 секунд. Каждый открытый сеанс занимает клиентскую лицензию. При частых вызовах режим «Не использовать» тратит время на старт сеанса на каждом запросе.
Шаг 2. Шаблоны URL и HTTP-методы
Внутри сервиса создаются шаблоны URL, а внутри шаблонов — методы. Шаблон отвечает за путь, метод — за глагол HTTP.
- В дереве сервиса добавьте шаблон, задайте ему имя (
Товар) и сам шаблон:/goods/{code}. - Внутри шаблона добавьте метод, в свойстве «HTTP-метод» выберите
GET. - В свойстве «Обработчик» нажмите на лупу. Конфигуратор создаст функцию в модуле сервиса.
- Для приёма данных добавьте второй шаблон
/goodsс методомPOST.
Фигурные скобки обозначают параметр. Значение из адреса /goods/00-00000012 попадёт в обработчик как параметр code.
Пример раскладки для небольшого API:
| Шаблон | Метод | Что делает |
|---|---|---|
/goods/{code} | GET | Отдаёт карточку товара |
/goods | GET | Список товаров, фильтры — в параметрах ?page=2&limit=50 |
/goods | POST | Создаёт товар из 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-сервисы на веб-сервере
- Запустите конфигуратор от имени администратора.
- Откройте
Администрирование → Публикация на веб-сервере. - Укажите имя публикации — например,
trade. Оно станет частью адреса. - Выберите веб-сервер и каталог публикации.
- Откройте вкладку «HTTP-сервисы». Поставьте флажок публикации по умолчанию или отметьте только нужные сервисы.
- Нажмите «Опубликовать». Для 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. Права доступа и аутентификация
Каждый вызов сервиса открывает сеанс конкретного пользователя базы. Обработчик выполняется с его правами: читать и писать он может только то, что разрешают роли.
Как настроить пользователя для интеграции:
- Создайте пользователя, например
api_site. Логин латиницей избавит от проблем с кодировкой у части HTTP-клиентов. - Включите «Аутентификация 1С:Предприятия» и задайте сложный пароль.
- Снимите «Показывать в списке выбора» — человеку под этой записью входить незачем.
- Создайте отдельную роль и дайте в ней только нужные права: для примера выше — чтение и добавление справочника номенклатуры.
- Назначьте пользователю только эту роль.
Внешняя система передаёт логин и пароль в заголовке 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.