При интеграции сторонних систем (например, интернет-магазинов, CRM-систем или мобильных приложений) с 1С через стандартный интерфейс OData разработчики часто сталкиваются с серьезным препятствием. Платформа 1С жестко завязана на использование уникальных идентификаторов (GUID/UUID). В JSON-пакетах OData они представлены как Ref_Key для самих объектов и ИмяРеквизита_Key для ссылочных полей (например, Номенклатура_Key или Контрагент_Key).
Возникает закономерный вопрос: неужели во внешней системе обязательно создавать дополнительные поля, запускать полную синхронизацию баз и хранить эти «чужие» GUID у себя? Ответ — нет, это делать необязательно. Существует несколько проверенных архитектурных подходов, которые позволяют связать системы по естественным бизнес-ключам (артикулу, ИНН, штрихкоду или коду) без изменения структуры внешней базы данных. Разберем эти варианты подробно.
Если мы не хотим хранить GUID в сторонней базе данных, мы можем получать их из 1С «на лету» непосредственно перед отправкой транзакций (например, перед созданием документа заказа). Для этого используется стандартный механизм запросов OData с фильтрацией.
Проанализируем этот процесс по шагам:
$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"
Схема простая: при первом обращении к товару с артикулом SL-9938 мы запрашиваем его GUID из 1С и записываем связку «Артикул -> GUID» в локальный кэш со средним временем жизни (TTL) в несколько часов или дней. При последующих операциях мы мгновенно берем GUID из памяти своего сервера.
_Key.
Рассмотрим обратную ситуацию: внешней системе нужно прочитать документы из 1С (например, забрать новые заказы покупателей) и сопоставить товары со своим каталогом. По умолчанию OData возвращает только «голые» GUID ссылочных полей:
"Номенклатура_Key": "6a8c095a-6005-11e8-a2ed-000c290bd191"
Чтобы не делать по каждому товару отдельные запросы в 1С за артикулами, мы можем использовать мощный параметр $expand. Он заставляет платформу 1С «развернуть» связанные справочники прямо внутри итогового JSON-файла.
Пример запроса на получение документов с раскрытием данных о товарах:
/odata/standard.odata/Document_ЗаказПокупателя?$expand=Товары/Номенклатура,Контрагент
В результате в полученном JSON-ответе вместо плоских полей _Key мы увидим вложенные объекты, которые будут содержать все реквизиты номенклатуры (включая артикул и наименование) и контрагента (включая ИНН и КПП). Внешняя система сможет легко сопоставить данные со своей базой без единого дополнительного запроса к 1С.
Иногда при поиске GUID по бизнес-ключу выясняется, что объекта (например, нового клиента или нового товара) в базе 1С еще не существует. В этом случае внешняя система может создать его «на лету»:
Catalog_Контрагенты), передавая в теле запроса только известные нам бизнес-данные (Наименование, ИНН, Адрес).Ref_Key и сразу же подставляем его в создаваемый документ.Стандартный 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С и максимальную простоту поддержки программного кода интеграции.