REST интерфейс и HTTP запросы. Часть 1  Получение данных – метод GET

Печать (Ctrl+P)

Вторая часть  можно посмотреть здесь

Общие сведения

В  версии платформы 8.3.5.1068, опубликованной в  сентябре 2015 появился механизм  интеграции 1С с внешними программами через технологию   REST интерфейс.  В качестве протокола доступа платформа использует протокол OData .  Это открытый веб-протокол для запроса и обновления данных. Он позволяет оперировать данными, используя в качестве запросов HTTP-команды. Получать ответы  в версии 8.3.5.1068 можно было только в формате Atom/XML  Однако, начиная  с релиза 8.3.8.1652 в августе 2017 г. появился второй вариант получения данных в формате JSON(англ. JavaScript Object Notation)  . По сравнению с XML он легко читается людьми  занимает меньше места. Кроме этого все браузеры имеют встроенные средства для работы с JSON.

Работу с протоколом OData на платформе 1С: предприятие  можно посмотреть в книге 1С: Руководства разработчика в главе 17  Механизмы интернет-сервисов , параграф  17.2.1  Cтандартный интерфейс OData.  Можно также посмотреть примеры   расширения поддержки протокола OData ,  реализованного в версии 8.3.8.1652 здесь.

Преимущество использования REST интерфейс. заключает в том , что  для получения доступа к данным системы из внешнего приложения не требуется  модификации кода прикладного решения (например, если прикладное решение стоит на поддержке). Для получения такого доступа необходимо особым образом опубликовать приложение на веб-сервере и указать, какие объекты конфигурации будут использоваться таким образом. После этого сторонние системы могут обращаться к вашему приложению с помощью HTTP запросов.

Публикация стандартного интерфейса OData выполняется с помощью диалога публикации на веб-сервере (Администрирование – Публикация на веб- сервере) и описано в книге 1С:Предприятие 8.3. “Руководство администратора”.
Важно! Для того чтобы объекты конфигурации стали доступны через стандартный интерфейс OData, необходимо разрешить это с помощью метода глобального контекста УстановитьСоставСтандартногоИнтерфейсаOData().
Механизм установки состава объектов, доступных с помощью стандартного интерфейса OData, можно выполнить в виде внешней обработки. Для этого не требуется модифицировать прикладное решение.

Для взаимодействия  с внешним  REST- веб-сервер из 1С:Предприятия  используется  имеющиеся в платформе средства работы с HTTP:  объекты HTTPСоединение,  HTTPЗапрос и HTTPОтвет.

В этой цикле статьей я буду показывать  примеры типовых операций, использующих соответствующий HTTP-метод ;

  •  Получение данных – метод GET;
  •  Создание объекта – метод POST;
  •  Обновление данных : метод PATCH – в этом случае можно указывать только те свойств, которые необходимо обновить;  метод PUT – в этом случае необходимо указывать все свойства сущности;
  •  Удаление данных – метод DELETE.

 1. Примеры получения данных.  HTTP-метод GET

В качестве сервера будет выступать опубликованная на веб-сервере БД с именем WebBuh  (Демо-база “Бухгалтерия Предприятия 3.0”).  В качестве формата обмена данных я буду использовать формат  JSON.  Подробнее о работе с JSON написано в документации, доступной здесь .  Для получения данных  из сервера  HTTP-методом GET требуется создать  объект ЧтениеJSON  для последовательного чтения JSON-данных из файла или строки. Для организации последовательной записи объектов и текстов  на сервере  HTTP-методом POST PATCH PUT  требуется создать объект ЗаписьJSON.  Отметим, для  метода DELETE  не требуется JSON.

В качестве иллюстрации  потокового чтения и записи JSON при обращении к REST интерфейсу я буду вызывать  следующую пользовательскую  функцию  общего назначения ВызватьHTTPМетодНаСервере  :

 &НаСервере
 // <Описание функции>
 //
 // Параметры:
 //  <HTTPМетод>  - Строка, содержащая имя HTTP-метода для запроса ("POST"."PATCH", "PUT" ,"GET","DELETE"
 //  <HTTPСоединение>  - объект HTTPСоединение
 //  <АдресРесурса>  - Строка http-ресурса, к которому будет отправлен HTTP запрос.
 //  <ОтправляемыеДанные>  - Структура или соответствие, содержащие данные, отправляемые на указанный адрес для обработки  
 //                     на сервер с использованием указанного HTTP-метода "POST" или "PATCH" или  "PUT" 
 // Возвращаемое значение:
 //   Структура ответа сервера в зависимости от HTTPМетод
 //
 Функция ВызватьHTTPМетодНаСервере(HTTPМетод,HTTPСоединение,АдресРесурса,ОтправляемыеДанные = Неопределено)
 //  Создание HTTPЗапрос
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/json");
ЗапросHTTP = Новый HTTPЗапрос( АдресРесурса, Заголовки);
 //  ЗаписьJson толка для создания и обновление данных
Если HTTPМетод= "POST" или HTTPМетод="PATCH" или HTTPМетод="PUT" Тогда
	ЗаписьJSON = Новый ЗаписьJSON; 
	ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто,"",Истина);	
	ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
	ЗаписатьJSON(ЗаписьJSON, ОтправляемыеДанные); // ОтправляемыеДанные обязательны в этом случае
	СтрокаДляТела = ЗаписьJSON.Закрыть();
	ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаДляТела,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
КонецЕсли;
 //  Вызов Метода HTTPСоединение
	ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP);
  СтруктураОтвета = Новый Структура;
  СтруктураОтвета.Вставить("КодСостояния", ОтветHTTP.КодСостояния);
  // ЧтениеJSON только для метода GET
Если HTTPМетод= "GET"  Тогда
Попытка
    ЧтениеJSON = Новый ЧтениеJSON;
    ОтветСервера = ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8");
    ЧтениеJSON.УстановитьСтроку(ОтветСервера);
    Соответствие = ПрочитатьJSON(ЧтениеJSON,Истина);
    СтруктураОтвета.Вставить("ОтветСервера", Соответствие);
    СтруктураОтвета.Вставить("ОтветСервераНеРасшифрованный", ОтветСервера);
  Исключение
    Сообщить(ОписаниеОшибки());
    Возврат Неопределено;
КонецПопытки;
Конецесли;
Возврат СтруктураОтвета;
   КонецФункции // ВызватьHTTPМетодНаСервере()

Для получения  от сервера в формате JSON при обращении к REST интерфейсу прикладного решения нужно  в адресе ресурса указать $format=json. Либо указать MIME тип “application/json” в заголовке :

Заголовки = Новый Соответствие(); 
Заголовки.Вставить("Content-Type", "application/json");
АдресРесурса ="WebBuh/odata/standard.odata/?$format=json"
ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);

Особенность глобального  контекста  ПрочитатьJSON(ЧтениеJSON, Истина)

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

  •  Если  значение второго  параметра установлено Истина, чтение объекта JSON будет выполнено в Соответствие.Если установлено Ложь, объекты будут считываться в объект типа Структура.
  • При десериализации объектов JSON в структуру необходимо помнить о требованиях к ключам структуры. Если при десериализации объекта будет найдено имя свойства, недопустимое для ключа структуры, то будет вызвано исключение.

1. 1 Настройка параметров HTTP  соединения

Для организации клиентской части взаимодействия с внешним  REST- веб-сервер, я создал “с нуля” конфигурацию клиента на базе БСП. На этой конфигурации я создал   справочник настройки параметров подключения (см Рис 1)

Рис 1 Справочник настройки параметров HTTP  соединения  к внешней ИБ через rest интерфейс

После нажатия кнопки Проверить ответ сервера,  вызывается процедура, по которой клиент  попытается получать ответ сервера.  Программный код процедуры написан ниже :

&НаКлиенте
 Процедура ПроверитьПодключение(Команда)
 Адрес = Объект.АдресСервера;
 Пользователь = Объект.Пользователь;
 Пароль= Объект.Пароль;
 ИмяБазы = Объект.Наименование;
 Порт = ?(Объект.Порт <> 0,Объект.Порт,80);
 HTTPСоединение = Новый HTTPСоединение(Адрес,Порт,Пользователь, Пароль);
 АдресРесурса = ИмяБазы+ "/odata/standard.odata/$metadata";
//Вызов пользовательской функции
 СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса); 
Если СтруктураОтвета <> Неопределено Тогда
  ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Код состояния "+СтруктураОтвета.КодСостояния);
Конецесли;
КонецПроцедуры

Цель этой процедуры – Это  проверка работы сервиса  и правильно ли пользователь ввел параметры соединения.  Для этого достаточно  выполнить GET-запрос:
HTTPСоединение.ВызватьHTTPМетод(“GET”, ЗапросHTTP) ;
с использованием адреса ресурса:
АдресРесурса = ИмяБазы+ /odata/standard.odata/“;
Проверить  работы сервиса можно также  в браузере с использованием
URL   
http://host/WebBuh/odata/standard.odata.  В результате такого запроса получается только список сущностей .  Для получения полного описания стандартного интерфейса OData (список доступных сущностей, их атрибутов и функций в виде XML-
документа.)  необходимо выполнить GET-запрос с использованием параметра $metadata.   URL  http://host/WebBuh/odata/standard.odata/$metadata.   Подробное описание документа можно получить по адресу http://www.odata.org/documentation/   (на английском языке).
Получать ответы можно в формате Atom/XML или JSON.    Коды статусов ответа по протоколу HTTP  можно посмотреть здесь. Ответы в диапазонах:

  • 100-199  – информационные ответы, показывающие, что запрос клиента принят и обрабатывается.
  • 200-299 – означают, что запрос клиента обработан успешно.
  • 300-399  означает, что запрос не выполнен и клиенту нужно предпринять некоторые действия для удовлетворения запроса.
  • 400-499   – информирует об ошибках на стороне клиентского приложения. Эти коды могут также означать, что от клиента требуется дополнительная информация.
  •  500-599  – информирует об ошибке на стороне сервера, показывают, что сервер столкнулся с ошибкой и, вероятно, не сможет выполнить запрос клиента.

1.2  Поиск объекта   по идентификатору

Следующая функция предназначена для поиска справочника или документа по уникальному идентификатора  на сервере . Если объект найден, то функция возвращает  строковое значение идентификатора (Ref_Key ) ,  иначе возвращает  неопределено.    В функцию передаются следующие параметры:

  • HTTPСоединение – Объект  типа  HTTPСоединение
  • ИмяПубликации – Имя опубликованной базы базы данных сервера 
  • Элемент – идентификатор сущности объекта , например, Catalog_Организации  или Document_- справочник Организации.
  • Идентификатор –  Идентификатор объекта, который нужно искать на сервере, например, Организация.УникальныйИдентификатор() 
&НаСервере
Функция ПоискОбъектПоGUID (HTTPСоединение,ИмяПубликации,Элемент,УникальныйИдентификатор)
GUID = Строка(УникальныйИдентификатор); // преобразуем в строку 
АдресРесурса = ИмяПубликации+ "/odata/standard.odata/" + Элемент+ "(guid'"+ GUID+ "')?$format=json";
//Вызов моей пользовательской функции
  СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса)Если  СтруктураОтвета.КодСостояния >= 400 Тогда
//ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния+
//ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный);
Возврат неопределено;
КонецЕсли;
Соответствие = СтруктураОтвета.ОтветСервера;
Массив= Соответствие["value"];
Если Массив = Неопределено Тогда
 Возврат Соответствие["Ref_Key"]
Иначе
 Возврат Массив[0]["Ref_Key"];
 КонецЕсли;
КонецФункции

Параметр АдресРесурса   используется для обращения к REST-сервису.  Для проверки работы сервиса можно указать ресурс в браузере таким образом

http://{АдресВебСервера}/{ИмяПубликации}/odata/standard.odata/{Элемент}?{Параметры},где

  • АдресВебСервера –  Адрес  веб-сервера, на котором опубликован сервис, например Localhost
  • ИмяПубликации – имя информационной базы  указанное при публикации решения
  • /odata/standard.odata/ – Признак обращения к стандартному интерфейсу OData
  • Элемент – идентификатор ресурса или предопределенные ресурсы. Например, Catalog_Контрагент(guid’value’).
  • Параметры – параметры ресурса. Используются, например, для отбора, в принятом для HTTP-запросов: ?ключ=значение&ключ2=значение2

 1.3  Поиск объекта по полям поиска

Следующая пользовательская функция предназначена для поиска объекта по полям поиска в том случае, когда  объект по идентификационному номеру. Функция возражает строку  Ref_Key –  идентификационный номер.

&НаСервере
 Функция ПоискОбъектПоПолямПоиска(HTTPСоединение,ИмяПубликации, Элемент,ПоляПоиска )
Условие = "";
Для Каждого КлючЗначение из ПоляПоиска Цикл
Условие = Условие + КлючЗначение.Ключ + " eq '" + КлючЗначение.Значение + "' and ";
КонецЦикла;
ТекстЗапроса = Лев(Условие, СтрДлина(Условие)-5); // удаляем последние 5 символов 
АдресРесурса= ИмяПубликации+ "/odata/standard.odata/" +Элемент+ "?$filter=" + ТекстЗапроса + "&$format=json&$select=Ref_Key";
//Вызов моей пользовательской функции
 СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса);

Если СтруктураОтвета.КодСостояния >= 400 Тогда
//ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния);
//ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный);
Возврат неопределено;
КонецЕсли;
Соответствие = СтруктураОтвета.ОтветСервера; 
Массив= Соответствие["value"]; 
Если Массив = Неопределено Тогда 
 Возврат Соответствие["Ref_Key"]
 Иначе Возврат Массив[0]["Ref_Key"]; 
 КонецЕсли; 
КонецФункции

Как видно из тела процедуры ПоискОбъектПоПолямПоиска , отбор начинается с ключевого слова $filter в адресе ресурса. Формальный параметр ПоляПоиска – это соответствие, которое содержит наименования и значения реквизитов.

Отметим, что наименование реквизитов порой не очевидно.  Необходимо запомнить, что для справочников:

  • Code – код,
  • Description – Наименование
  • DeletionMark – пометка удаления,
  • IsFolder – признак группы,
  • Parent_Key – родитель.
  • Если реквизит ссылочного типа, к его имени следует добавить суффикс _Key, например Контрагент_Key.

Для документов:

  • Number – номер документа,
  • Date – дата документа.

Логические операции отбора

  • eq — Равно; /Catalog_Города?$filter=Наименование eq ‘Главный’;
  • ne — Не равно; /Catalog_Города?$filter=Наименование ne ‘Пермь’;
  • gt — Больше; /Catalog_Товары?$filter=Цена gt 10;
  • ge — Больше или равно; /Catalog_Товары?$filter=Цена ge 10;
  • lt — Меньше; /Catalog_Товары?$filter=Цена lt 10;
  • le — Меньше или равно; /Catalog_Товары?$filter=Цена le 10;
  • or — Логическое ИЛИ; /Catalog_Товары?$filter=Цена lt 10 or Цена gt 100;
  • and — Логическое И; /Catalog_Товары?$filter=Цена gt 10 and Цена lt 100;
  • not — Отрицание; /Catalog_Товары?$filter=not (Цена eq 10);

Отметим, также, что  значение  фактического параметра   Элемент ( или сущность)) , который я передаю  на функцию   формируется по следующему правилу:

ПрефиксИмени_ИмяОбъектаКонфигурации_СуффиксИмени.

С помощью стандартного  интерфейса OData можно получить доступ к следующим объектам (ПрефиксИмени):

  • Справочник — Catalog;
  • Документ — Document;
  • Журнал документов — DocumentJournal;
  • Константа — Constant;
  • План обмена — ExchangePlan;
  • План счетов — ChartOfAccounts
  • План видов расчета — ChartOfCalculationTypes;
  • План видов характеристик — ChartOfCharacteristicTypes;
  • Регистр сведений — InformationRegister;
  • Регистр накопления — AccumulationRegister;
  • Регистр расчета — CalculationRegister;
  • Регистр бухгалтерии — AccountingRegister;
  • Бизнес-процесс — BusinessProcess;
  • Задача — Task.

ИмяОбъектаКонфигурации — свойство «Имя» объекта конфигурации так, как оно задано в конфигураторе.

СуффиксИмени — нужен для уточнения имени ресурса, необязателен, может принимать следующие значения:

  • Имя табличной части объекта;
  • Имя виртуальной таблицы объекта;
  • RowType — строка табличной части объекта;
  • RecordType — отдельная запись регистра.

Параметры обращения к ресурсам

После формирования имени ресурса нужно определить параметры обращения к ресурсу, например, ?$filter=Значение&$format=json&$select=Ref_Key ,

  • $filter — отбор при получении данных
  • $format — указывает формат возвращаемых данных,
  • $select — перечисление свойств сущности, которые попадут в результат запроса;
  • $metadata — возвращает описание стандартного интерфейса OData (используется без указания суффикса имени, пример на одном из изображений выше);
  • $top — ограничение количества возвращаемых записей ;
  • $skip — убирает из результата запроса указанное количество записей ;
  • $count — возвращает количество записей в выборке запроса;
  • $inlinecount=allpage(=none) — добавляет в результат запроса информацию о количестве записей
  • $orderby=<Реквизит1> asc, <Реквизит2> desc — сортировка результата запроса
  • alloweOnly — только разрешенные (используется без знака «$»).

 1.4   Получить массив записей регистра сведений

Посмотрим пример получения массив записей регистра сведения ФИОФизическихЛиц, например историю изменения ФИО физического лица

ИмяПубликации ="WebBuh";  
Элемент = "InformationRegister_ФИОФизическихЛиц";
Период = Неопределено;
 ДанныеСсылочногоТипа = Новый Структура();
ДанныеСсылочногоТипа.Вставить("ФизическоеЛицо",ФизическоеЛицо_Key);
ДанныеНЕСылочногоТипа= Новый Структура();
ДанныеНЕСылочногоТипа.Вставить("ФизическоеЛицо_Type", "StandardODATA.Catalog_ФизическиеЛица")
Массив = ПолучитьНаборЗаписиРегистраСведений(HTTPСоединение,ИмяПубликации,Элемент,  Период ,ИзмеренияСсылочногоТипа, ИзмеренияНЕСылочногоТипа )

Тело функции ПолучитьНаборЗаписиРегистраСведений, которая вызывается в этом примере показано ниже  

&НаСервере
 Функция ПолучитьНаборЗаписиРегистраСведений(HTTPСоединение,ИмяПубликации,Элемент,
                                             Период =Неопределено ,ИзмеренияСсылочногоТипа= Неопределено, 
                                             ИзмеренияНЕСылочногоТипа = Неопределено) 
ТекстЗапроса ="";
Если Период <> Неопределено Тогда
ФорматированныйПериод = Формат(Период,"ДФ=yyyy-MM-ddTHH:mm:ss");
ТекстЗапроса = "Period = datetime'"+ ФорматированныйПериод + "'" ;
КонецЕсли;
Если ИзмеренияСсылочногоТипа <> Неопределено Тогда
Для Каждого КлючЗначение из ИзмеренияСсылочногоТипа Цикл
Запитая = ?(ЗначениеЗаполнено(ТекстЗапроса), "," ,"");
ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=guid('"+ КлючЗначение.Значение + "')";
КонецЦикла;
КонецЕсли;
Если ИзмеренияНЕСылочногоТипа<> Неопределено Тогда
Для Каждого КлючЗначение из ИзмеренияНЕСылочногоТипа Цикл
Запитая = ?(ЗначениеЗаполнено(ТекстЗапроса), "," ,"");
ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=" + КлючЗначение.Значение;
КонецЦикла;
КонецЕсли;
АдресРесурса= ИмяПубликации+ "/odata/standard.odata/" + Элемент + "("+ ТекстЗапроса+  + ")?$format=json";
//Вызов моей пользовательской функции
СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса);
Если СтруктураОтвета.КодСостояния >= 400 Тогда 
//ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния);
 //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный);
 Возврат неопределено; КонецЕсли;
Соответствие = СтруктураОтвета.ОтветСервера; 
Массив= Соответствие["value"]; 
Если Массив = Неопределено Тогда 
 Возврат Соответствие;
 Иначе 
Возврат Массив;
 КонецЕсли; 
КонецФункции

REST интерфейс и HTTP запросы. Часть 2  Создание и изменение объекта

Previous Article
Next Article

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.