Как подключиться к базе 1С по OData и работать с ней из кода
Содержание
Чтобы работать с базой 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. Публикация на веб-сервере
- Запустите Конфигуратор от имени администратора Windows (иначе он не сможет записать настройки IIS или Apache).
- Откройте
Администрирование → Публикация на веб-сервере. - Укажите имя публикации латиницей, например
buh. Оно станет частью адреса. - Выберите веб-сервер и каталог публикации.
- Поставьте флажок
Публиковать стандартный интерфейс OData. - Нажмите
Опубликовать. Для 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"]);
КонецЦикла;
Возврат Результат;
КонецФункции
Три приёма, на которых спотыкаются чаще всего:
- Кодирование адреса. Кириллица в имени объекта, пробелы и кавычки в
$filterдолжны уйти в URL закодированными. Кодируйте части адреса, а не весь адрес целиком: иначе закодируются и/,?,&. - Методы соединения.
Получить()— этоGET,ОтправитьДляОбработки()—POST,Изменить()—PATCH,Удалить()—DELETE. - Таймаут. Шестой параметр конструктора
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 нужной формы.