Как подключиться к базе 1С по OData и работать с ней из кода

· 10 мин

Содержание

Чтобы работать с базой 1С по протоколу OData, опубликуйте её на веб-сервере с флажком Публиковать стандартный интерфейс OData, включите нужные объекты в состав интерфейса и обращайтесь к адресу http://сервер/имя_публикации/odata/standard.odata/. Дальше это обычный REST: GET читает, POST создаёт, PATCH изменяет, ответ приходит в JSON или XML.

Стандартный интерфейс OData есть в платформе 8.3 и не требует программирования в самой конфигурации. Им пользуются сайты, мобильные приложения, BI-системы и другие базы 1С, когда нужно быстро забрать справочники, документы или остатки. Протокол — OData версии 3.0, это важно при выборе клиентских библиотек.

Публикация стандартного интерфейса OData в 1С

Без веб-сервера OData не работает : интерфейс отдаёт модуль расширения веб-сервера 1С. Подойдут Apache или IIS. Сама публикация делается из Конфигуратора.

Шаг 1. Публикация на веб-сервере

  1. Запустите Конфигуратор от имени администратора Windows (иначе он не сможет записать настройки IIS или Apache).
  2. Откройте Администрирование → Публикация на веб-сервере.
  3. Укажите имя публикации латиницей, например buh. Оно станет частью адреса.
  4. Выберите веб-сервер и каталог публикации.
  5. Поставьте флажок Публиковать стандартный интерфейс OData.
  6. Нажмите Опубликовать. Для Apache после этого перезапустите службу веб-сервера.

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

Шаг 2. Состав интерфейса

После публикации по адресу /odata/standard.odata/ вы увидите почти пустой список. Так и задумано: по умолчанию ни один объект конфигурации через OData не доступен. Состав задают отдельно.

Есть два способа:

  • 🧩 В типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) — раздел Администрирование → Синхронизация данных, ссылка на настройку стандартного интерфейса OData. Там отмечают объекты флажками и сразу создают пользователя для доступа.
  • 🛠 Программно — методом УстановитьСоставСтандартногоИнтерфейсаOData(). Его вызывают в режиме 1С:Предприятие, например из внешней обработки, под пользователем с административными правами.
&НаСервере
Процедура НастроитьСоставODataНаСервере()

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

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

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

Метод заменяет состав целиком, а не добавляет к нему. Если раньше в интерфейсе были другие объекты, сначала получите текущий список функцией ПолучитьСоставСтандартногоИнтерфейсаOData() и дополните его.

💡 Если объект ссылается на другой справочник (документ — на контрагента), включите в состав и его. Иначе вы получите только GUID ссылки без возможности развернуть её.

Шаг 3. Пользователь для интеграции

Заведите в базе отдельного пользователя, например odata_user, с аутентификацией 1С:Предприятия и паролем. Дайте ему роль только на нужные объекты: чтение, если внешней системе нужны данные, и запись — только туда, куда она действительно пишет. Работать под администратором можно в тесте, в рабочей базе — нельзя.

Подключение по OData занимает лицензию, как обычный сеанс. Учитывайте это при расчёте количества клиентских лицензий.

Адреса ресурсов OData: как устроен URL

Корень интерфейса — http://сервер/buh/odata/standard.odata/. По нему приходит список доступных коллекций, а по адресу .../standard.odata/$metadata — полное описание полей и типов. Метаданные стоит открыть первым делом: в них видны точные имена всех свойств.

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

Объект конфигурацииПрефиксПример
СправочникCatalog_Catalog_Номенклатура
ДокументDocument_Document_РеализацияТоваровУслуг
Табличная часть_ + имя ТЧDocument_РеализацияТоваровУслуг_Товары
Регистр сведенийInformationRegister_InformationRegister_ЦеныНоменклатуры
Регистр накопленияAccumulationRegister_AccumulationRegister_ТоварыНаСкладах
Регистр бухгалтерииAccountingRegister_AccountingRegister_Хозрасчетный
План счетовChartOfAccounts_ChartOfAccounts_Хозрасчетный
ПеречислениеEnum_Enum_ВидыДоговоров
КонстантаConstant_Constant_ОсновнаяВалюта

Один элемент справочника или документ адресуют по ссылке:

/odata/standard.odata/Catalog_Номенклатура(guid'3f2c9a10-5b7e-11ee-9c1a-00155d0a1b02')

У стандартных реквизитов английские имена: Ref_Key, Code, Description, Number, Date, Posted, DeletionMark, Parent_Key, DataVersion. Реквизиты-ссылки получают суффикс _Key и содержат GUID: Контрагент_Key, Склад_Key. Для составного типа добавляется поле с суффиксом _Type, где указан тип значения.

Виртуальные таблицы регистров

Остатки и срезы не нужно собирать из движений вручную. Платформа отдаёт виртуальные таблицы как функции:

AccumulationRegister_ТоварыНаСкладах/Balance(Period=datetime'2026-09-30T23:59:59')
AccumulationRegister_ТоварыНаСкладах/Turnovers(StartPeriod=datetime'2026-09-01T00:00:00',EndPeriod=datetime'2026-09-30T23:59:59')
InformationRegister_ЦеныНоменклатуры/SliceLast(Period=datetime'2026-10-01T00:00:00')

Отбор внутри виртуальной таблицы передают параметром Condition. Он работает быстрее, чем $filter поверх готового результата, потому что условие применяется до расчёта остатков.

Параметры запросов OData: $filter, $select, $expand

Параметры дописывают к адресу после ? и соединяют через &. Набор стандартный для OData 3.0:

ПараметрЧто делаетПример
$formatформат ответа$format=json
$selectтолько нужные поля$select=Ref_Key,Code,Description
$filterотбор$filter=DeletionMark eq false
$orderbyсортировка$orderby=Date desc
$top / $skipпорция и сдвиг$top=100&$skip=200
$expandразвернуть ссылку$expand=Контрагент
$inlinecountобщее число записей$inlinecount=allpages
$metadataописание модели.../standard.odata/$metadata

Литералы в $filter записывают по правилам протокола:

  • 🔤 строка — в одинарных кавычках: Description eq 'Стол офисный';
  • 🆔 ссылка — Контрагент_Key eq guid'...';
  • 📅 дата — Date ge datetime'2026-09-01T00:00:00';
  • 🔢 число и булево — без кавычек: СуммаДокумента gt 10000, Posted eq true.

Операторы сравнения — eq, ne, gt, ge, lt, le, логика — and, or, not. Для строк есть функции substringof('стол', Description) и startswith(Description, 'Стол').

Пример — проведённые реализации за сентябрь, только номер, дата и сумма:

Document_РеализацияТоваровУслуг?$format=json&$select=Number,Date,СуммаДокумента&$filter=Posted eq true and Date ge datetime'2026-09-01T00:00:00' and Date lt datetime'2026-10-01T00:00:00'&$orderby=Date

$expand разворачивает ссылку прямо в ответе. Указывают имя реквизита без суффикса _Key: $expand=Контрагент вернёт объект контрагента вложенным полем. Удобно, но тяжело для больших выборок.

Запись через OData: создание, изменение и проведение документов

OData в 1С умеет не только читать. Для записи используют те же адреса и другие HTTP-методы:

ОперацияМетодАдрес
Создать элементPOST/Catalog_Номенклатура
Изменить поляPATCH/Catalog_Номенклатура(guid'...')
УдалитьDELETE/Catalog_Номенклатура(guid'...')
Провести документPOST/Document_X(guid'...')/Post?PostingModeOperational=false
Отменить проведениеPOST/Document_X(guid'...')/Unpost

В PATCH передают только меняемые поля, остальные не трогаются. При создании в теле POST — JSON с реквизитами, при успехе сервер отвечает кодом 201 и возвращает созданный объект вместе с новым Ref_Key.

DELETE удаляет объект непосредственно, минуя пометку на удаление и проверку ссылок. Для справочников и документов безопаснее изменить поле DeletionMark на true через PATCH, а удаление помеченных оставить штатной обработке.

Документ, созданный через POST, записывается непроведённым. Проведение — отдельный вызов Post. Если документ провести нельзя (не хватает остатков, не заполнен склад), сервер вернёт ошибку с текстом из модуля проведения, а сам документ останется записанным.

HTTP-запросы к OData из кода 1С

Когда одна база 1С забирает данные из другой, OData вызывают объектами HTTPСоединение и HTTPЗапрос. Ниже — рабочий пример: найти номенклатуру по наименованию и вернуть массив ссылок.

Функция НайтиНоменклатуру(Наименование) Экспорт

    Соединение = Новый HTTPСоединение("srv1c.local", 443, "odata_user", "Пароль",
        , 30, Новый ЗащищенноеСоединениеOpenSSL);

    // Апостроф внутри строки удваивается по правилам OData
    Значение = СтрЗаменить(Наименование, "'", "''");
    Фильтр = СтрШаблон("Description eq '%1' and DeletionMark eq false", Значение);

    Адрес = "/buh/odata/standard.odata/Catalog_"
        + КодироватьСтроку("Номенклатура", СпособКодированияСтроки.КодировкаURL)
        + "?$format=json&$select=Ref_Key,Code,Description"
        + "&$filter=" + КодироватьСтроку(Фильтр, СпособКодированияСтроки.КодировкаURL);

    Запрос = Новый HTTPЗапрос(Адрес);
    Запрос.Заголовки.Вставить("Accept", "application/json");

    Ответ = Соединение.Получить(Запрос);
    Тело = Ответ.ПолучитьТелоКакСтроку("UTF-8");

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

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

    Результат = Новый Массив;
    Для Каждого Элемент Из Данные["value"] Цикл
        Результат.Добавить(Элемент["Ref_Key"]);
    КонецЦикла;

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

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

Три приёма, на которых спотыкаются чаще всего:

  1. Кодирование адреса. Кириллица в имени объекта, пробелы и кавычки в $filter должны уйти в URL закодированными. Кодируйте части адреса, а не весь адрес целиком: иначе закодируются и /, ?, &.
  2. Методы соединения. Получить() — это GET, ОтправитьДляОбработки() — POST, Изменить() — PATCH, Удалить() — DELETE.
  3. Таймаут. Шестой параметр конструктора HTTPСоединение — таймаут в секундах. Без него запрос к зависшему серверу будет висеть неопределённо долго и держать сеанс.

Для обычного HTTP без шифрования уберите ЗащищенноеСоединениеOpenSSL и укажите порт 80. Пароль в коде держать нельзя — храните его в безопасном хранилище или в константе с ограниченным доступом.

Обработка JSON: разбор ответа и формирование тела

Список объектов приходит в обёртке: служебное поле odata.metadata и массив value. Один объект по ссылке приходит без value, сразу полями.

{
  "odata.metadata": "http://srv1c.local/buh/odata/standard.odata/$metadata#Catalog_Номенклатура",
  "value": [
    { "Ref_Key": "3f2c9a10-5b7e-11ee-9c1a-00155d0a1b02", "Code": "00-00000017", "Description": "Стол офисный" }
  ]
}

Поэтому в примере выше ПрочитатьJSON вызывается со вторым параметром Истина — результат читается в Соответствие. В Структуру ключ odata.metadata не прочитается: точка недопустима в имени ключа, и чтение упадёт с ошибкой.

Даты в ответе — строки вида 2026-09-15T10:30:00. Чтобы получить сразу тип Дата, перечислите такие поля третьим параметром:

Данные = ПрочитатьJSON(Чтение, Истина, "Date,Period", ФорматДатыJSON.ISO);

Пустые значения выглядят так: пустая ссылка — 00000000-0000-0000-0000-000000000000, пустая дата — 0001-01-01T00:00:00. Проверяйте их явно, иначе «пустой» контрагент уедет во внешнюю систему как настоящий GUID.

Тело для POST и PATCH собирают из структуры:

Объект = Новый Структура;
Объект.Вставить("Description", "Стул офисный");
Объект.Вставить("Parent_Key", "6a1d0c44-5b7e-11ee-9c1a-00155d0a1b02");

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

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

Ответ = Соединение.ОтправитьДляОбработки(Запрос);

💡 Не добавляйте BOM в начало тела. Часть серверов воспринимает его как мусор перед JSON и отвечает ошибкой разбора.

Ошибки интеграции через OData и отладка

Начинайте отладку не с кода, а с браузера или curl. Если запрос не работает из адресной строки, он не заработает и из 1С.

curl -u odata_user:Пароль "http://srv1c.local/buh/odata/standard.odata/\$metadata"

Ошибки сервер возвращает в теле ответа, в поле odata.error: там код и текст на русском. Всегда выводите тело ответа в лог — код состояния сам по себе мало что скажет.

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

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

Как ускорить обмен через OData

OData удобен, но каждый запрос — это полноценная выборка на сервере 1С. На больших базах медленный обмен почти всегда вызван тем, что клиент просит лишнее.

  • 📉 Всегда указывайте $select. Документ с табличными частями без $select тянет все реквизиты, а табличные части — целиком. Список из трёх полей приходит в разы быстрее.
  • 📦 Читайте порциями. $top=500 плюс $skip и сортировка по Ref_Key или дате. Без сортировки порции могут перекрываться.
  • 🗂 Остатки — через Balance и SliceLast. Выгрузка всех движений регистра и расчёт на стороне клиента в десятки раз дольше.
  • 🔎 Отбор по индексируемым полям. Ссылки, дата и номер документа отбираются быстро. substringof по наименованию на большом справочнике — медленно.
  • 🔗 Осторожнее с $expand. Он удобен для десятка записей, но на тысячах строк умножает объём ответа.
  • 🔄 Забирайте только изменения. Храните дату последнего обмена и отбирайте документы по дате или по номеру версии DataVersion.

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

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

Нужно ли менять конфигурацию, чтобы включить OData?
Нет. Стандартный интерфейс есть в платформе. Достаточно публикации на веб-сервере и настройки состава объектов, конфигурацию снимать с поддержки не нужно.
Работает ли OData с файловой базой?
Да. Файловую базу тоже публикуют на веб-сервере, и интерфейс работает. Для постоянного обмена под нагрузкой лучше клиент-серверный вариант.
Чем OData отличается от HTTP-сервиса?
OData отдаёт объекты конфигурации в стандартном виде без программирования. HTTP-сервис пишет разработчик: он задаёт адреса, логику и формат ответа сам.
Можно ли получить данные в XML вместо JSON?
Да. Без параметра $format интерфейс отвечает в формате Atom XML. Для JSON добавьте $format=json или заголовок Accept: application/json.
Почему через OData видны не все реквизиты?
Реквизиты, на которые у пользователя нет прав, и объекты вне состава интерфейса не выводятся. Проверьте роли пользователя интеграции и список объектов в составе.