ПолучитьОбъект(), HTTP-сервис, OData и COM: доступ к данным 1С на стороне сервера

· 10 мин

Содержание

Объект на сервере 1С получают методом ПолучитьОбъект() у ссылки: НоменклатураОбъект = Ссылка.ПолучитьОбъект();. Код должен выполняться в серверном контексте — в общем модуле с флагом «Сервер» или в процедуре формы с директивой &НаСервере / &НаСервереБезКонтекста. Ссылку сначала находят: НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту() или запросом.

Если объект нужен внешней системе, к серверу 1С обращаются снаружи: через HTTP-сервис (свой REST API), стандартный интерфейс OData или COM-соединение. Все способы ниже относятся к платформе 8.3 и работают одинаково в любой конфигурации — БП, ЗУП, УТ, ERP.

СпособКогда подходитЧто нужно
ПолучитьОбъект() в серверном кодеДоработки внутри базы, обработки, расширенияПрава на объект
Вызов сервера из формыНужны данные объекта на клиентеСерверная процедура, возврат структуры
HTTP-сервисСайт, мобильное приложение, интеграция по своему форматуПубликация на веб-сервере, код обработчика
ODataБыстро отдать справочники и документы без программированияПубликация + состав интерфейса
COM-соединениеОбмен двух баз на Windows, скриптыЗарегистрированный comcntr.dll, лицензия

Получение объекта по ссылке встроенным языком

В 1С различают ссылку и объект. Ссылка — лёгкий указатель на запись в базе. Объект — полная копия записи со всеми реквизитами и табличными частями, которую можно изменить и записать.

Шаг 1. Найти ссылку

Типовые менеджеры дают несколько способов поиска:

  • 🔎 Справочники.Номенклатура.НайтиПоКоду("00-00000015") — по коду;
  • 🔎 Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина) — по наименованию, второй параметр включает точное совпадение;
  • 🔎 Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7701234567") — по значению реквизита;
  • 🔎 Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0000-000123", ТекущаяДата()) — по номеру в пределах периода нумерации;
  • 🔎 Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор("...")) — по GUID из внешней системы.

Если ничего не найдено, методы НайтиПо… возвращают пустую ссылку, а не Неопределено. Проверяйте результат через Ссылка.Пустая() или ЗначениеЗаполнено(Ссылка).

ПолучитьСсылку() по GUID не проверяет, существует ли запись. Вы получите «правильную на вид» ссылку даже на удалённый объект. Существование проверяйте отдельно — запросом или через ПолучитьОбъект().

Шаг 2. Получить объект и изменить его

// Общий модуль РаботаСНоменклатуройСервер, флаг «Сервер»
Процедура УстановитьКомментарий(Ссылка, ТекстКомментария) Экспорт

    НоменклатураОбъект = Ссылка.ПолучитьОбъект();
    Если НоменклатураОбъект = Неопределено Тогда
        ВызватьИсключение "Объект не найден в базе: " + Строка(Ссылка.УникальныйИдентификатор());
    КонецЕсли;

    НоменклатураОбъект.Заблокировать();   // объектная блокировка на время правки
    НоменклатураОбъект.Комментарий = ТекстКомментария;
    НоменклатураОбъект.Записать();

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

Три момента, которые часто упускают:

  1. ПолучитьОбъект() возвращает Неопределено, если записи в базе нет (битая ссылка). Без проверки код упадёт с ошибкой «Значение не является значением объектного типа ».
  2. Заблокировать() ставит объектную блокировку. Если документ в это время открыт у другого пользователя, вызов завершится исключением — его стоит перехватить и показать понятный текст.
  3. Для документов запись с проведением — ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение).

💡 Если объект нужен только для чтения, ПолучитьОбъект() избыточен. Платформа читает всю запись вместе с табличными частями. Для пары полей быстрее запрос — подробнее в разделе про оптимизацию.

Как получить объект на сервере из формы и тонкого клиента

В тонком клиенте и веб-клиенте метода ПолучитьОбъект() нет. Попытка вызвать его в клиентской процедуре даёт ошибку Метод объекта не обнаружен (ПолучитьОбъект). Объекты базы между клиентом и сервером не передаются — передаются ссылки и простые значения: строки, числа, структуры, массивы.

Правильная схема: клиент передаёт ссылку на сервер, сервер получает объект и возвращает структуру с нужными полями.

&НаКлиенте
Процедура ПоказатьАртикул(Команда)
    Данные = ДанныеНоменклатуры(Объект.Номенклатура);
    Если Данные <> Неопределено Тогда
        Сообщить("Артикул: " + Данные.Артикул);
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ДанныеНоменклатуры(Ссылка)
    Если Не ЗначениеЗаполнено(Ссылка) Тогда
        Возврат Неопределено;
    КонецЕсли;
    НоменклатураОбъект = Ссылка.ПолучитьОбъект();
    Если НоменклатураОбъект = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;
    Результат = Новый Структура("Наименование, Артикул");
    ЗаполнитьЗначенияСвойств(Результат, НоменклатураОбъект);
    Возврат Результат;
КонецФункции

&НаСервереБезКонтекста предпочтительнее &НаСервере: форма не гоняется на сервер целиком, вызов легче.

Объект самой формы

Если нужно поработать с объектом, который открыт в форме (вызвать его экспортный метод, заполнить табличную часть по правилам модуля объекта), используйте пару методов формы:

&НаСервере
Процедура ЗаполнитьНаСервере()
    ДокументОбъект = РеквизитФормыВЗначение("Объект");
    ДокументОбъект.ЗаполнитьТоварыПоОстаткам();   // экспортный метод модуля объекта
    ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры

Здесь ЗаполнитьТоварыПоОстаткам() — пример вашего собственного экспортного метода. Изменения попадут в форму, но в базу запишутся только когда пользователь нажмёт «Записать».

HTTP-сервис: отдаём объект 1С наружу по REST

HTTP-сервис — это свой REST API внутри конфигурации. Внешняя система шлёт GET-запрос, обработчик на сервере 1С находит объект и отвечает JSON.

Создание сервиса

  1. В Конфигураторе (или в расширении) откройте ветку Общие → HTTP-сервисы, добавьте сервис, задайте корневой URL, например api.
  2. Добавьте шаблон URL /item/{code} и в нём метод GET.
  3. Создайте обработчик метода и напишите код.
Функция ItemGET(Запрос)

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

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

    Данные = Новый Структура;
    Данные.Вставить("code", Код);
    Данные.Вставить("name", Ссылка.Наименование);
    Данные.Вставить("guid", Строка(Ссылка.УникальныйИдентификатор()));

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

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

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

Обработчик HTTP-сервиса всегда выполняется на сервере, поэтому директивы компиляции здесь не нужны.

Публикация и проверка

Базу публикуют на веб-сервере (IIS или Apache) из Конфигуратора: Администрирование → Публикация на веб-сервере, флажок публикации HTTP-сервисов должен стоять. После этого сервис доступен по адресу вида:

curl -u "api_user:пароль" "https://server/base/hs/api/item/00-00000015"

Часть /hs/ обязательна — по ней веб-расширение 1С понимает, что запрос идёт к HTTP-сервису.

OData: стандартный REST без единой строки обработчиков

OData — готовый интерфейс платформы. Он отдаёт справочники, документы и регистры в формате JSON или XML без написания обработчиков. Подходит для BI, отчётов в Excel и простых интеграций.

Включение

  1. Укажите, какие объекты открыть. Это делают кодом один раз, с правами администратора:
Состав = Новый Массив;
Состав.Добавить(Метаданные.Справочники.Номенклатура);
Состав.Добавить(Метаданные.Документы.РеализацияТоваровУслуг);
УстановитьСоставСтандартногоИнтерфейсаOData(Состав);
  1. При публикации на веб-сервере отметьте флажок «Публиковать стандартный интерфейс OData».
  2. Заведите отдельного пользователя 1С с правами только на чтение этих объектов.

💡 В типовых конфигурациях на БСП бывает обработка «Настройка автоматического REST-сервиса», которая делает первый шаг через интерфейс. Если её нет — хватит кода выше, выполненного, например, в консоли кода.

Запрос объекта

# Один элемент по GUID
curl -u "odata_user:пароль" \
  "https://server/base/odata/standard.odata/Catalog_Номенклатура(guid'3f2a1c4e-0000-0000-0000-000000000000')?\$format=json"

# Отбор и выбор нужных полей
curl -u "odata_user:пароль" \
  "https://server/base/odata/standard.odata/Catalog_Номенклатура?\$filter=Code%20eq%20'00-00000015'&\$select=Ref_Key,Description&\$format=json"

Имена сущностей строятся по схеме Catalog_, Document_, InformationRegister_ + имя объекта метаданных. Поле ссылки — Ref_Key, наименование — Description, код — Code.

OData отдаёт объект целиком, с табличными частями. Без $select и $top выгрузка большого справочника заметно нагрузит сервер.

Командная строка, консоль кода и отладчик

Консоль кластера (rac, оснастка администрирования серверов) объектами базы не управляет: она видит сеансы, соединения и информационные базы, но не данные. Чтобы получить объект «по-администраторски», используют другие приёмы.

Запуск обработки из командной строки

Пишете внешнюю обработку , которая в серверном модуле находит объект и выполняет действие, и запускаете её без участия пользователя:

"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" ENTERPRISE /S "srv1c\buh" /N "Робот" /P "пароль" /Execute "C:\scripts\obrabotka.epf" /C "00-00000015"

Параметр /C передаёт строку в программу, внутри она доступна через ПараметрЗапуска. Номер платформы в пути подставьте свой.

Консоль кода и консоль запросов

Обработки «Консоль кода» и «Консоль запросов» распространяются как внешние обработки. В консоли кода можно выполнить на сервере тот же Ссылка.ПолучитьОбъект() и посмотреть результат. Запускайте её только под пользователем с полными правами и только в копии, если код что-то записывает.

Отладчик и навигационная ссылка

  • 🧭 В Конфигураторе остановитесь на точке останова и откройте «Вычислить выражение» (Shift+F9): введите Ссылка.ПолучитьОбъект() и разверните реквизиты.
  • 🧭 Чтобы найти конкретную запись, в открытой форме объекта получите навигационную ссылку (Shift+F11). Она имеет вид e1cib/data/Справочник.Номенклатура?ref=…, где после ref= — GUID объекта в шестнадцатеричном виде.

COM-соединение и внешние компоненты

COM-соединение даёт программе на Windows (другой базе 1С, скрипту на VBScript или Python) прямой доступ к объектной модели базы. На стороне подключения работает полноценный серверный контекст: доступны менеджеры, запросы и ПолучитьОбъект().

Коннектор = Новый COMОбъект("V83.COMConnector");
Соединение = Коннектор.Connect("Srvr=""srv1c"";Ref=""buh"";Usr=""Робот"";Pwd=""пароль"";");

Ссылка = Соединение.Справочники.Номенклатура.НайтиПоКоду("00-00000015");
Если Не Ссылка.Пустая() Тогда
    УдаленныйОбъект = Ссылка.ПолучитьОбъект();
    Сообщить(УдаленныйОбъект.Наименование);
КонецЕсли;

Что нужно для работы:

  • 🔧 зарегистрировать comcntr.dll от имени администратора: regsvr32 "C:\Program Files\1cv8\<версия>\bin\comcntr.dll";
  • 🔧 разрядность платформы и вызывающей программы должна совпадать (64-битный скрипт не увидит 32-битный коннектор);
  • 🔧 внешнее соединение занимает клиентскую лицензию, как обычный сеанс.

Объекты из COM-соединения нельзя напрямую подставить в реквизиты своей базы. Ссылка «чужой» базы — это COM-объект, а не ссылка вашей конфигурации. Переносите данные через простые значения: код, GUID, строки.

Внешние компоненты (Native API) сами по себе к данным базы доступа не дают. Это библиотеки на C++, которые расширяют язык: работа с оборудованием, криптография, нестандартные протоколы. Объект 1С всё равно получают кодом на встроенном языке, а компоненте передают уже простые значения.

Быстро и без падений: оптимизация и обработка ошибок

Не читайте объект целиком ради одного поля

Обращение через точку Ссылка.Наименование и вызов ПолучитьОбъект() читают из базы всю запись. В цикле на 5 000 строк это 5 000 отдельных обращений. Один запрос по массиву ссылок делает ту же работу за одно обращение:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|   Номенклатура.Ссылка КАК Ссылка,
|   Номенклатура.Артикул КАК Артикул
|ИЗ
|   Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|   Номенклатура.Ссылка В (&Ссылки)";
Запрос.УстановитьПараметр("Ссылки", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Выборка.Ссылка, Выборка.Артикул
КонецЦикла;

В конфигурациях на БСП то же самое делают функции ОбщегоНазначения.ЗначениеРеквизитаОбъекта() и ОбщегоНазначения.ЗначенияРеквизитовОбъектов() — они внутри строят такой запрос.

ЗадачаЧем делать
Прочитать 1–3 поляЗапрос или ЗначенияРеквизитовОбъекта()
Прочитать поля у многих объектовОдин запрос с В (&Ссылки)
Изменить и записатьПолучитьОбъект() + Записать()
Вызвать метод модуля объектаПолучитьОбъект()

Перехват ошибок

Запись объекта может упасть из-за блокировки, проверки заполнения или прав. Оборачивайте её в Попытка … Исключение и пишите причину в журнал регистрации:

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

Права и безопасность: как не слить данные

Получая объект для внешней системы, вы фактически открываете часть базы наружу. Несколько правил, которые снимают большинство рисков:

  • 🔐 Отдельный пользователь под интеграцию. Только нужные роли, только чтение, если запись не требуется. Не публикуйте сервис под учётной записью администратора.
  • 🔐 HTTPS обязателен. Basic-аутентификация передаёт логин и пароль в каждом запросе; по HTTP их видно в сети открытым текстом.
  • 🔐 Минимальный состав OData. Открывайте только те объекты, которые нужны потребителю. Справочник «Физические лица» или кадровые документы в составе OData — прямая утечка персональных данных.
  • 🔐 Осторожно с привилегированным режимом. УстановитьПривилегированныйРежим(Истина) отключает проверку прав и ограничений на уровне записей. Включайте его на минимальный участок кода, а не на весь обработчик.
  • 🔐 Безопасный режим для чужого кода. Если обработчик выполняет код, пришедший извне (например, текст запроса из параметра), используйте УстановитьБезопасныйРежим(Истина) — а лучше вообще не принимайте код снаружи.
  • 🔐 Пароли не в тексте модуля. Строку подключения COM и учётные данные храните в защищённом хранилище или в константе с ограниченным доступом, а не литералом в коде.

Проверяйте права в коде явно, если сервис отдаёт данные по произвольному идентификатору. Иначе любой, кто знает адрес и пароль интеграционного пользователя, перебором GUID или кодов вытащит весь справочник.

Если Не ПравоДоступа("Чтение", Метаданные.Справочники.Номенклатура) Тогда
    Возврат Новый HTTPСервисОтвет(403);
КонецЕсли;

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

Чем ссылка отличается от объекта в 1С?
Ссылка — указатель на запись, её можно хранить в реквизитах и передавать на клиент. Объект — полная копия записи с табличными частями, его можно изменить и записать, но существует он только на сервере, в толстом клиенте или во внешнем соединении.
Можно ли передать объект с сервера на клиент?
Нет. Между клиентом и сервером передаются ссылки и простые значения. Верните на клиент структуру с нужными полями или используйте реквизит формы «Объект».
Нужно ли получать объект, чтобы пометить его на удаление?
Да. Пометку ставит метод объекта УстановитьПометкуУдаления(Истина), поэтому сначала вызовите ПолучитьОбъект() на сервере.
Работает ли ПолучитьОбъект() в расширении конфигурации?
Да. Код расширения выполняется по тем же правилам контекста, что и код основной конфигурации. Права на объекты при этом проверяются так же.
Что выбрать для интеграции с сайтом — HTTP-сервис или OData?
OData быстрее запустить, если сайту нужны готовые справочники как есть. HTTP-сервис лучше, когда нужен свой формат ответа, расчёт на стороне 1С или строгий контроль того, какие поля уходят наружу.