OData 1С — это автоматический REST-интерфейс платформы: после публикации базы с флажком «Публиковать стандартный интерфейс OData» и указания состава объектов внешнее приложение может читать, создавать, изменять и удалять справочники, документы, регистры и константы по HTTP. Адрес строится как http://сервер/ИмяПубликации/odata/standard.odata/Catalog_Номенклатура?$format=json, а отборы, выбор полей и сортировка задаются параметрами $filter, $select, $orderby.

Ниже — настройка, синтаксис ресурсов, рабочие примеры запросов и кода, а также ограничения, из-за которых я в части проектов выбираю HTTP-сервисы вместо OData.

Что умеет стандартный интерфейс OData

ВозможностьКак выглядит
Чтение списка с отбором и полямиGET Catalog_Номенклатура?$filter=...&$select=...
Чтение одного объектаGET Catalog_Номенклатура(guid'...')
СозданиеPOST Catalog_Номенклатура с JSON в теле
Изменение части полейPATCH Catalog_Номенклатура(guid'...')
УдалениеDELETE Catalog_Номенклатура(guid'...')
Проведение и отменаPOST Document_Имя(guid'...')/Post() и /Unpost()
Виртуальные таблицы регистровSliceLast(), SliceFirst(), Balance(), Turnovers() и др.
Описание всех ресурсовGET $metadata

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

Публикация и настройка состава

1. Публикация. В конфигураторе «Администрирование» → «Публикация на веб-сервере»: имя публикации (например, trade), веб-сервер, каталог и флажок «Публиковать стандартный интерфейс OData». На Linux то же самое делается утилитой webinst и правкой default.vrd: нужен элемент <standardOdata enable="true" .../>.

2. Состав объектов. По умолчанию интерфейс пустой. Состав задается методом платформы УстановитьСоставСтандартногоИнтерфейсаOData:

1С
// Открывает доступ по OData к номенклатуре, ценам и реализациям.
Процедура НастроитьСоставOData() Экспорт

	Состав = Новый Массив;
	Состав.Добавить(Метаданные.Справочники.Номенклатура);
	Состав.Добавить(Метаданные.Справочники.Валюты);
	Состав.Добавить(Метаданные.РегистрыСведений.ЦеныНоменклатуры);
	Состав.Добавить(Метаданные.Документы.РеализацияТоваровУслуг);

	УстановитьСоставСтандартногоИнтерфейсаOData(Состав);

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

Объекты, на которые ссылаются реквизиты, тоже нужно включить, иначе платформа не даст сохранить состав. В конфигурациях на БСП для этого есть форма настройки стандартного интерфейса OData, а также распространялась обработка «Настройка автоматического REST-сервиса»: они подбирают зависимые объекты и создают служебного пользователя.

3. Пользователь. Заведите отдельного пользователя только для интеграции, с минимальными правами на нужные объекты. В конфигурациях на БСП для этого предназначена роль удаленного доступа к OData. Не используйте администратора: OData дает полный CRUD в пределах прав.

Синтаксис URL

Общий вид:

text
http://<сервер>:<порт>/<публикация>/odata/standard.odata/<ресурс>?<параметры>

Имена ресурсов строятся из английского префикса типа и имени объекта:

ПрефиксОбъект
Catalog_Справочник
Document_Документ
DocumentJournal_Журнал документов
Constant_Константа
ExchangePlan_План обмена
ChartOfAccounts_, ChartOfCalculationTypes_, ChartOfCharacteristicTypes_Планы счетов, видов расчета, видов характеристик
InformationRegister_, AccumulationRegister_, AccountingRegister_, CalculationRegister_Регистры
BusinessProcess_, Task_Бизнес-процессы и задачи

Суффиксы: _ИмяТабличнойЧасти — табличная часть, _RowType — тип строки табличной части, _RecordType — тип записи регистра.

Литералы: строки в апострофах 'Конфеты', идентификаторы guid'27b04ad1-...', даты datetime'2024-10-03T12:30:59'.

Стандартные реквизиты называются по-английски: Ref_Key, Code, Description, DeletionMark, Date, Number, Posted. Ссылочные реквизиты отдаются как Имя_Key с GUID; чтобы получить представление, используйте $expand.

Основные параметры:

ПараметрНазначение
$format=jsonОтвет в JSON (по умолчанию XML/Atom)
$filterОтбор: eq, ne, gt, lt, and, or, функции вроде like
$selectСписок возвращаемых полей
$expandРазвернуть ссылочные поля в объекты
$orderbyСортировка
$top, $skipПорционное чтение
/$countКоличество записей
OData 1С: запрос проходит через отбор, выбор полей и сортировку
OData 1С: запрос проходит через отбор, выбор полей и сортировку

Примеры запросов на чтение

Номенклатура по артикулу, только нужные поля:

text
/trade/odata/standard.odata/Catalog_Номенклатура?$format=json&$filter=Артикул eq 'Арт-980000'&$select=Ref_Key,Description,Артикул

Поиск по части наименования, первые три записи с сортировкой по коду:

text
/trade/odata/standard.odata/Catalog_Номенклатура?$format=json&$filter=like(Description,'%хар%')&$select=Description,Артикул,Code&$top=3&$orderby=Code

Количество элементов справочника:

text
/trade/odata/standard.odata/Catalog_Номенклатура/$count

Один объект по ссылке:

text
/trade/odata/standard.odata/Catalog_Номенклатура(guid'f01bb2c2-427a-11dd-ac9e-0015e9b8c48d')?$format=json

Срез последних цен в долларах с развернутыми ссылками:

text
/trade/odata/standard.odata/InformationRegister_ЦеныНоменклатуры/SliceLast(Period=datetime'2024-09-30T00:00:00',Condition='Валюта/Description eq ''USD''')?$format=json&$expand=Номенклатура,Валюта&$select=Номенклатура/Description,Цена,Валюта/Description,Period

Обратите внимание на удвоенные апострофы внутри Condition: строковый литерал внутри строкового параметра экранируется именно так. Для проверки удобно использовать curl под отдельным пользователем:

bash
curl -s -u odata_user:Пароль \
  "https://erp.example.ru/trade/odata/standard.odata/Catalog_Номенклатура?\$format=json&\$top=5"

Не передавайте логин и пароль в URL вида user:pass@host: такие адреса оседают в логах прокси и истории браузера. Используйте заголовок Authorization (Basic) поверх HTTPS.

Создание, изменение и проведение из кода

Пример клиента на встроенном языке — например, для обмена между двумя базами 1С без доработки базы-приемника.

1С
// Выполняет запрос к стандартному интерфейсу OData и возвращает разобранный JSON.
Функция ВыполнитьЗапросOData(Метод, Ресурс, Данные = Неопределено)

	Соединение = Новый HTTPСоединение("erp.example.ru", 443, ИмяПользователяOData(), ПарольOData(), , 60,
		Новый ЗащищенноеСоединениеOpenSSL);

	Запрос = Новый HTTPЗапрос("/trade/odata/standard.odata/" + Ресурс);
	Запрос.Заголовки.Вставить("Accept", "application/json");

	Если Данные <> Неопределено Тогда
		ЗаписьJSON = Новый ЗаписьJSON;
		ЗаписьJSON.УстановитьСтроку();
		ЗаписатьJSON(ЗаписьJSON, Данные);
		Запрос.Заголовки.Вставить("Content-Type", "application/json");
		Запрос.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8);
	КонецЕсли;

	Ответ = Соединение.ВызватьHTTPМетод(Метод, Запрос);
	ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();

	Если Ответ.КодСостояния >= 300 Тогда
		ВызватьИсключение СтрШаблон("OData %1 %2: код %3. %4", Метод, Ресурс, Ответ.КодСостояния, ТелоОтвета);
	КонецЕсли;

	Если ПустаяСтрока(ТелоОтвета) Тогда
		Возврат Неопределено; // Например, 204 No Content после DELETE.
	КонецЕсли;

	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
	Возврат ПрочитатьJSON(ЧтениеJSON);

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

Использование:

1С
// Создать элемент справочника.
СозданныйЭлемент = ВыполнитьЗапросOData("POST", "Catalog_Номенклатура?$format=json",
	Новый Структура("Description, Артикул", "Новая номенклатура", "Арт-808"));
Ссылка = СозданныйЭлемент["Ref_Key"];

// Изменить одно поле.
ВыполнитьЗапросOData("PATCH", СтрШаблон("Catalog_Номенклатура(guid'%1')?$format=json", Ссылка),
	Новый Структура("Артикул", "Арт-809"));

// Перепровести документ.
РесурсДокумента = СтрШаблон("Document_РеализацияТоваровУслуг(guid'%1')", ГУИДДокумента);
ВыполнитьЗапросOData("POST", РесурсДокумента + "/Unpost()");
ВыполнитьЗапросOData("POST", РесурсДокумента + "/Post()");

// Удалить элемент.
ВыполнитьЗапросOData("DELETE", СтрШаблон("Catalog_Номенклатура(guid'%1')", Ссылка));

Ссылочные реквизиты при записи передаются как ИмяРеквизита_Key с GUID в строке. Табличная часть передается массивом объектов в свойстве с именем табличной части.

Ограничения и подводные камни

  • Каждый запрос — сеанс 1С. Тысячи мелких запросов в минуту нагружают сервер и расходуют лицензии. Читайте порциями через $top/$skip и только нужные поля.
  • Нет произвольных запросов. Соединения таблиц, группировки и сложные вычисления на стороне 1С через OData не сделать — только отборы по ресурсу и виртуальные таблицы регистров.
  • Контракт зависит от метаданных. Переименовали реквизит — внешний клиент сломался. Для внешних разработчиков стабильнее HTTP-сервис с документированным JSON.
  • Удаление — непосредственное. DELETE удаляет объект без пометки и контроля ссылок. Для справочников безопаснее PATCH с DeletionMark: true.
  • Права решают всё. Пользователю OData нужны права не только на объект, но и на связанные данные, иначе получите ошибку доступа при записи или проведении.
  • Кириллица в URL. Внешние клиенты обычно кодируют адрес сами; при ручной сборке URL в других языках не забывайте URL-кодирование параметров $filter.

OData или HTTP-сервис

КритерийODataHTTP-сервис
Доработка конфигурацииНе нужнаНужна
Скорость запуска интеграцииВысокаяНужна разработка
Бизнес-логика и проверкиТолько логика модулей объектовЛюбая
Сложные выборкиНетДа
Стабильность контрактаЗависит от метаданныхПод вашим контролем
Подходит дляBI, разовые выгрузки, простые обменыСайты, маркетплейсы, мобильные приложения

На проектах я часто комбинирую: BI-система и внутренние скрипты читают данные через OData, а критичные операции с проверками идут через HTTP-сервис. Настройку такой связки делаю в рамках интеграции 1С по API и веб-доступа к 1С; выгрузку для дашбордов — в BI-аналитике для 1С.

Итог

  • OData 1С включается флажком при публикации и методом УстановитьСоставСтандартногоИнтерфейсаOData.
  • Ресурсы именуются по схеме Catalog_, Document_, InformationRegister_ и т. д., стандартные поля — по-английски.
  • $filter, $select, $expand, $top и виртуальные таблицы регистров покрывают большинство задач чтения.
  • Запись, проведение и удаление работают с правами пользователя интеграции — давайте ему минимум прав.
  • Для сложной логики и стабильного внешнего контракта выбирайте HTTP-сервис.