Как работать с OData в 1С без хранения GUID во внешней системе?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции сторонних систем (например, интернет-магазинов, CRM-систем или мобильных приложений) с 1С через стандартный интерфейс OData разработчики часто сталкиваются с серьезным препятствием. Платформа 1С жестко завязана на использование уникальных идентификаторов (GUID/UUID). В JSON-пакетах OData они представлены как Ref_Key для самих объектов и ИмяРеквизита_Key для ссылочных полей (например, Номенклатура_Key или Контрагент_Key).

Возникает закономерный вопрос: неужели во внешней системе обязательно создавать дополнительные поля, запускать полную синхронизацию баз и хранить эти «чужие» GUID у себя? Ответ — нет, это делать необязательно. Существует несколько проверенных архитектурных подходов, которые позволяют связать системы по естественным бизнес-ключам (артикулу, ИНН, штрихкоду или коду) без изменения структуры внешней базы данных. Разберем эти варианты подробно.

Вариант 1. Двухэтапный запрос с фильтрацией и кэшированием (Стандартный OData)

Если мы не хотим хранить GUID в сторонней базе данных, мы можем получать их из 1С «на лету» непосредственно перед отправкой транзакций (например, перед созданием документа заказа). Для этого используется стандартный механизм запросов OData с фильтрацией.

Проанализируем этот процесс по шагам:

  1. Поиск GUID по бизнес-ключу. Перед тем как отправить новый документ в 1С, внешняя система выполняет быстрый точечный GET-запрос к нужному справочнику. С помощью параметра $filter мы указываем наш уникальный бизнес-ключ (например, артикул товара), а с помощью параметра $select просим 1С вернуть только уникальный идентификатор Ref_Key. Это минимизирует объем передаваемых данных и ускоряет работу СУБД.

    Пример GET-запроса для поиска номенклатуры по артикулу:

    /odata/standard.odata/Catalog_Номенклатура?$filter=Артикул eq 'SL-9938'&$select=Ref_Key

    В ответ 1С пришлет компактный JSON-пакет, из которого мы извлекаем GUID:

    "Ref_Key": "6a8c095a-6005-11e8-a2ed-000c290bd191"

  2. Кэширование на стороне интегратора. Выполнять GET-запрос к 1С при добавлении каждой позиции в документ непроизводительно — это создаст колоссальную нагрузку на сеть и сервер. Чтобы избежать этого, на стороне внешней системы организуется кэш (например, в оперативной памяти приложения или в быстром хранилище типа Redis).

    Схема простая: при первом обращении к товару с артикулом SL-9938 мы запрашиваем его GUID из 1С и записываем связку «Артикул -> GUID» в локальный кэш со средним временем жизни (TTL) в несколько часов или дней. При последующих операциях мы мгновенно берем GUID из памяти своего сервера.

  3. Отправка итогового документа. Собрав все необходимые GUID (контрагента по ИНН, товаров по артикулам), внешняя система формирует один POST-запрос на создание документа и передает полученные идентификаторы в соответствующие поля _Key.

Вариант 2. Использование параметра $expand при чтении данных

Рассмотрим обратную ситуацию: внешней системе нужно прочитать документы из 1С (например, забрать новые заказы покупателей) и сопоставить товары со своим каталогом. По умолчанию OData возвращает только «голые» GUID ссылочных полей:

"Номенклатура_Key": "6a8c095a-6005-11e8-a2ed-000c290bd191"

Чтобы не делать по каждому товару отдельные запросы в 1С за артикулами, мы можем использовать мощный параметр $expand. Он заставляет платформу 1С «развернуть» связанные справочники прямо внутри итогового JSON-файла.

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

/odata/standard.odata/Document_ЗаказПокупателя?$expand=Товары/Номенклатура,Контрагент

В результате в полученном JSON-ответе вместо плоских полей _Key мы увидим вложенные объекты, которые будут содержать все реквизиты номенклатуры (включая артикул и наименование) и контрагента (включая ИНН и КПП). Внешняя система сможет легко сопоставить данные со своей базой без единого дополнительного запроса к 1С.

Вариант 3. Динамическое создание объектов (метод Upsert)

Иногда при поиске GUID по бизнес-ключу выясняется, что объекта (например, нового клиента или нового товара) в базе 1С еще не существует. В этом случае внешняя система может создать его «на лету»:

  1. Отправляем POST-запрос в соответствующий справочник (например, Catalog_Контрагенты), передавая в теле запроса только известные нам бизнес-данные (Наименование, ИНН, Адрес).
  2. Платформа 1С самостоятельно создает элемент справочника, генерирует для него новый GUID и возвращает всю созданную структуру обратно во внешнюю систему.
  3. Из тела ответа мы забираем сгенерированный Ref_Key и сразу же подставляем его в создаваемый документ.

Вариант 4. Лучшая альтернатива: Собственные HTTP-сервисы в 1С

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

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

Выясним, почему собственные HTTP-сервисы удобнее стандартного OData:

Посмотрим на пример реализации логики поиска объектов по бизнес-ключам внутри HTTP-сервиса 1С. Ниже представлен пример кода, обрабатывающего входящий JSON-пакет заказа:


// Функция обрабатывает POST-запрос создания заказа от внешней системы
Функция СоздатьЗаказПокупателя(Запрос)
    
    // Читаем входящий JSON-пакет
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
    ДанныеЗапроса = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    // Создаем новый документ заказ покупателя
    НовыйЗаказ = Документы.ЗаказПокупателя.СоздатьДокумент();
    НовыйЗаказ.Дата = ТекущаяДата();
    
    // Ищем контрагента по ИНН, переданному во входящем JSON
    КонтрагентСсылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ДанныеЗапроса.ИНН_Контрагента);
    Если КонтрагентСсылка.Пустая() Тогда
        // Если не нашли, возвращаем ошибку внешней системе
        Ответ = Новый HTTPСервисОтвет(404);
        Ответ.УстановитьТелоИзСтроки("Контрагент с ИНН " + ДанныеЗапроса.ИНН_Контрагента + " не найден в 1С.");
        Возврат Ответ;
    КонецЕсли;
    НовыйЗаказ.Контрагент = КонтрагентСсылка;
    
    // Заполняем табличную часть Товары
    Для Каждого СтрокаТовара Из ДанныеЗапроса.Товары Цикл
        
        // Находим товар по Артикулу, который для нас является уникальным бизнес-ключом
        НоменклатураСсылка = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", СтрокаТовара.Артикул);
        Если НоменклатураСсылка.Пустая() Тогда
            // Пропускаем или создаем товар динамически
            Продолжить;
        КонецЕсли;
        
        НоваяСтрока = НовыйЗаказ.Товары.Добавить();
        НоваяСтрока.Номенклатура = НоменклатураСсылка;
        НоваяСтрока.Количество = СтрокаТовара.Количество;
        НоваяСтрока.Цена = СтрокаТовара.Цена;
        НоваяСтрока.Сумма = СтрокаТовара.Количество * СтрокаТовара.Цена;
        
    КонецЦикла;
    
    Попытка
        НовыйЗаказ.Записать(РежимЗаписиДокумента.Проведение);
        
        // Формируем успешный ответ и возвращаем номер созданного заказа
        Ответ = Новый HTTPСервисОтвет(201);
        СтруктураОтвета = Новый Структура("Успешно, НомерДокумента", Истина, НовыйЗаказ.Номер);
        
        ЗаписьJSON = Новый ЗаписьJSON;
        ЗаписьJSON.УстановитьСтроку();
        ЗаписатьJSON(ЗаписьJSON, СтруктураОтвета);
        Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
        
        Возврат Ответ;
    Исключение
        Ответ = Новый HTTPСервисОтвет(500);
        Ответ.УстановитьТелоИзСтроки("Ошибка проведения документа: " + ОписаниеОшибки());
        Возврат Ответ;
    КонецПопытки;
    
КонецФункции

Подведем итоги

Мы проанализировали различные варианты работы с протоколом OData и интеграции внешних баз данных со встроенными механизмами 1С. Выбор конкретного архитектурного решения зависит от требований к гибкости вашей системы:

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

Используйте собственные HTTP-сервисы в 1С во всех остальных случаях. Этот подход гарантирует высокую скорость выполнения запросов, безопасность транзакций, независимость внешней базы данных от внутренних GUID-идентификаторов 1С и максимальную простоту поддержки программного кода интеграции.

← На главную