GET и POST-запросы из 1С:Предприятия 8
ПРЕДИСЛОВИЕ
Методы GET и POST HTTP-запросов |
Проходилось ли Вам настраивать интеграцию решения на платформе 1С:Предприятие с веб-сервисами или другими службами/системами используя GET и POST-запросы? Если нет, то ниже для вас будут представлены интересные примеры работы платформы с этими методами HTTP-запросов. Если же да, то далее в статье Вас может заинтересовать информация об ограничениях платформы при работе с ними, а также пути обхода этих ограничений. Плюс, уверен, Вас заинтересуют примеры реализации обработок авторизации в сервисах Yandex из 1С:Предприятия и получения статистики запросов Yandex.Wordstat.
Все примеры реализованы в тестовой конфигурации, загрузить которую Вы можете по ссылке в конце статьи. Конфигурация работает с версиями платформы 8.2 и выше.
И так, начнем с простого примера использования GET-запроса.
GET-ЗАПРОС
HTTP-запрос этого вида является самым распространенным. При помощи этого вида запроса браузеры запрашивают любые файлы веб-сервера. Главное отличие GET-запросов - это отсутствие тела запроса, присутствуют только заголовки. Подробнее о GET-запросах Вы можете прочитать здесь.
Для чего может понадобиться выполнять HTTP-запрос вида GET из 1С:Предприятия? Самым распространенным примером, на мой взгляд, является скачивание файла с веб-сервера. Именно это мы сейчас и продемонстрируем!
В тестовой конфигурации была создана обработка "GETЗапросы", имеющая следующую структуру метаданных:
Структура метаданных обработки для выполнения GET-запросов |
Форма обработки выполнения GET-запроса для скачивания файла из 1С:Предприятия |
В поле "Сервер запроса" вводим адрес сервера, с которого будем загружать файл. В поле "Текст запроса" копируем часть ссылки, идущую после имени сервера. Т.е. если ссылка:
www.site.ru/something/file.jpg
то адресом сервера будет www.site.ru, а оставшаяся часть ссылки идет в текст запроса: /something/file.jpg.
На скриншоте выше поля содержат адрес сервера и ссылку для скачивания тестовой картинки PNG с сайта www.develplatform.com. Что это за картинка Вы можете узнать скачав тестовую конфигурацию и выполнив GET-запрос по кнопке "Выполнить запрос" на форме.
Поле "Расширение выходного файла" позволяет указать программе какой тип файла будет загружен, чтобы уже в диалоге выбора пути к сохраняемому файлу можно было бы установить фильтр по этому расширению. Его заполнять не обязательно.
Далее представлен программный код для выполнения GET-запроса на скачивание файла и последующее сохранение загруженного файла на диске:
Далее представлен программный код для выполнения GET-запроса на скачивание файла и последующее сохранение загруженного файла на диске:
// !!! HTTP-соединение с параметрами по умолчанию Соединение = Новый HTTPСоединение(Объект.СерверЗапроса); // С помощью диалога выбора файла // настраиваем путь для сохранения // скачиваемого файла на диск Режим = РежимДиалогаВыбораФайла.Сохранение; ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим); // Если фильтр по расширению указан, то // используем его Если ЗначениеЗаполнено(Объект.РасширениеВыходногоФайла) Тогда Фильтр = НСтр("ru = 'Файл'") + "(*."+Объект.РасширениеВыходногоФайла+")|*."+ Объект.РасширениеВыходногоФайла; ДиалогОткрытияФайла.Фильтр = Фильтр; КонецЕсли; ДиалогОткрытияФайла.Заголовок = "Выберите путь и имя файла"; ДиалогОткрытияФайла.МножественныйВыбор = Ложь; Если ДиалогОткрытияФайла.Выбрать() Тогда // !!! Выполняем GET-запрос, указав полный путь // к файлу на сервере и путь сохранения загруженного // файла Соединение.Получить(Объект.ТекстЗапроса, ДиалогОткрытияФайла.ПолноеИмяФайла); Предупреждение("GET-запрос успешно выполнен!"); Иначе Текст = "ru = ""Файл не выбран!""; en = ""File not selected!"""; Предупреждение(НСтр(Текст)); КонецЕсли;
Код, непосредственно относящийся к выполнение GET-запроса, пометил в комментариях как "!!!". Общий принцип такой: сначала создаем класс HTTP-соединения с заданным адресом сервера. После этого выполняем метод "Получить()" для указанного адреса на этом сервере в первом параметре. Во втором параметре указываем путь, по которому будет сохранен загруженный файл. Если оставить только непосредственно относящийся к GET-запросу код, то мы увидим следующее:
Соединение = Новый HTTPСоединение("www.site.ru"); Соединение.Получить("/something/file.jpg", "C:\Рисунок.png");
Все достаточно просто. Подробнее о классе HTTP-соединения и его методах Вы можете прочитать в синтаксис-помощнике. Перейдем к более интересным примерам POST-запросов, имеющих намного больше возможностей и способов применения.
POST-ЗАПРОС
Метод POST является одним из самых используемых методов HTTP-запросов. От GET-запросов его отличает наличие тела запроса, что позволяет отправлять на веб-сервер практически любые данные. Очень часто используется для заполнения веб-форм и загрузки файла. Также может применяться для отправки запросов веб-сервисам в различных форматах как, например, было сделано в статье "Веб-сервис на C# для 1С:Предприятие 8.x. Отправка СМС".
Далее рассмотрим общий принцип формирования POST-запросов средствами платформы 1С:Предприятие, а также разные форматы передаваемых запросом данных (SOAP и JSON) на примере взаимодействия с сервисами Yandex.
Отправка средствами платформы
Отправка POST-запросов средствами платформы выполняется следующим образом:
// Создаем объект HTTP-соединения с заданным сервером // Последний параметр указывает будет ли использоваться // защищенное соединение HTTP = Новый HTTPСоединение(Сервер,,,,,Истина); // Создаем временный файл, который будет // передан в теле POST-запроса ФайлЗапроса = ПолучитьИмяВременногоФайла(); // Записываем в файл текстовое содержимое // тела запроса (переменная "ТелоЗапроса") ТекстовыйФайл = Новый ТекстовыйДокумент; ТекстовыйФайл.УстановитьТекст(ТелоЗапроса); ТекстовыйФайл.Записать(ФайлЗапроса, КодировкаТекста.ANSI); // Получаем размер отправляемых данных в теле запроса ФайлОтправки = Новый Файл(ФайлЗапроса); РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер()); // Подготовим временный файл для получения тела // ответа POST-запроса ФайлРезультата = ПолучитьИмяВременногоФайла(); // Для того, чтобы установить заголовки // POST-запроса создадим соответствие ЗаголовокHTTP = Новый Соответствие(); // В этом примере устанавливаем в заголовках запроса // размер передаваемых данных и их тип ЗаголовокHTTP.Вставить("Content-Length", РазмерФайлаОтправки); ЗаголовокHTTP.Вставить("Content-Type", "application/json; charset=utf-8"); // Отправляем POST-запрос для обработки. // Параметры: // 1. Файл запроса - путь к файлу, содержащего // тело запроса // 2. Ресурс - ссылка на страницу веб-сервера, // к которой выполняется POST-запрос // 3. ФайлРезультат - файл, в который будет // помещено тело ответа сервера // 4. ЗаголовокHTTP - соответствие с заголовками // POST-запроса HTTP.ОтправитьДляОбработки(ФайлЗапроса, Ресурс, ФайлРезультата, ЗаголовокHTTP); // Получаем ответ веб-сервера на POST-запрос // в виде текста ТекстовыйФайлОтвет = Новый ТекстовыйДокумент; ТекстовыйФайлОтвет.Прочитать(ФайлРезультата,КодировкаТекста.UTF8); СтрокаОтветСервера = ТекстовыйФайлОтвет.ПолучитьТекст();
Отличие от GET-запроса - это объявление заголовков и тела запроса. Подробно описывать нет смысла, ход действий должен быть понятен по комментариям в коде выше.
Рассмотрим на практике применение POST-запросов для платформы 1С:Предприятие с использованием разных форматов данных, передаваемых в теле запроса.
В разных форматах
Примеры отправки POST-запросов будут демонстрироваться для работы с сервисами Yandex'a: Yandex.Direct и Yandex.Wordstat. В рамках статьи мы не будем подробно рассматривать реализацию аутентификации на этих сервисах, самостоятельно пример Вы сможете посмотреть в тестовой конфигурации к статье. Отмечу лишь некоторые моменты, чтобы Вы смогли использовать собственный аккаунт на Яндексе, чтобы посмотреть примеры из статьи.
Первое, что вам нужно сделать - это включить использование профессионального интерфейса для сервиса Yandex.Direct, чтобы стала доступна работа через API. Какой интерфейс использовать сервис спросит Вас в самом начале. Подробнее написано в справке Директа или на форуме.
После этого необходимо зарегистрировать приложение по адресу.
Регистрация приложения Yandex |
В настройках нового приложения обязательно дайте права на работу с Yandex.Direct и укажите следующий Callback URI: https://oauth.yandex.ru/verification_code?dev=True
Настройки нового зарегистрированного приложения Yandex |
В результате должно быть создано приложение, у которого нас интересует его идентификатор.
Идентификатор приложения Yandex |
Скопируйте этот идентификатор в константу тестовой конфигурации.
Сохраняем идентификатор приложения в тестовой конфигурации |
И последний шаг - это получение токена доступа. Для этого достаточно запустить обработку авторизации и при необходимости войти в аккаунт Яндекса. Токен будет получен автоматически!
Получение токена доступа Яндекса из 1С:Предприятия |
Перейдем непосредственно к примерам!
SOAP
SOAP - это простой протокол доступа к объектам, предназначенный для обмена сообщениями в формате XML. Более подробную информацию о нем Вы можете прочитать здесь.
Согласно руководству разработчика Yandex.Direct поддерживает два способа взаимодействия через API: через SOAP или JSON. Рекомендуется использовать последний, но для примера выполним один из методов Директа с использованием SOAP, отправив тело POST-запросом.
Пусть это будет метод "PingAPI", проверяющий доступность сервиса. Вот так выглядит программный код для вызова метода:
// Создаем HTTP-соединение с сервером API Яндекса HTTP = Новый HTTPСоединение("api.direct.yandex.ru",,,,,Истина); // Формируем файл с содержимым тела POST-запроса ФайлЗапроса = ПолучитьИмяВременногоФайла(); // Содержимое тела запроса, в которое обязательно должен // быть подставлен токен доступа из константы ЗапросТекст = ПолучитьТелоЗапроса(); // Записываем содержимое тела в файл отправки ТекстовыйФайл = Новый ТекстовыйДокумент; ТекстовыйФайл.УстановитьТекст(ЗапросТекст); ТекстовыйФайл.Записать(ФайлЗапроса, КодировкаТекста.ANSI); // Создаем файл, в который будет помещено тело ответа сервера ФайлРезультата = ПолучитьИмяВременногоФайла(); // Формируем заголовки POST-запроса и отправляем // его для обработки ЗаголовокHTTP = Новый Соответствие(); ФайлОтправки = Новый Файл(ФайлЗапроса); РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер()); ЗаголовокHTTP.Вставить("Content-Length", РазмерФайлаОтправки); ЗаголовокHTTP.Вставить("Content-Type", "text/xml; charset=utf-8"); HTTP.ОтправитьДляОбработки(ФайлЗапроса, "/live/v4/soap/1/", ФайлРезультата, ЗаголовокHTTP); // Получаем ответ сервера в виде строки ТекстовыйФайлОтвет = Новый ТекстовыйДокумент; ТекстовыйФайлОтвет.Прочитать(ФайлРезультата,КодировкаТекста.UTF8); СтрокаРезультат = ТекстовыйФайлОтвет.ПолучитьТекст();
Принцип тот же, что и для обычного POST-запроса. Содержимое тела запроса формируется следующей функцией:
В тестовой конфигурации, после выполнения метода, на экране отобразится ответ сервера также в формате SOAP:
Таким путем можно реализовать работу с Яндекс.Директ из 1С:Предприятия, но проще и эффективней работать через формат JSON.
Формирование тела POST-запроса в формате SOAP для выполнения метода "PingAPI" Яндекс.Директ |
Ответ Яндекс.Директ для метода PingAPI в формате SOAP |
JSON
JSON - это текстовый формат обмена данными, основанный наJavaScript и обычно используемый именно с этим языком. Как и многие другие текстовые форматы, JSON легко читается людьми.
В рамках статьи не будем касаться серилизации и десериализации типов данных 1С:Предприятия и JSON. Будем использовать готовую разработку Александра Переверзева, которую можно скачать в его блоге. Созданный им парсер и серилизатор позволяет за короткое время создать алгоритмы по отправке и приему данных в формате JSON.
В примере мы создадим обработку, которая будет получать статистику по запросам сервиса Yandex.Wordstat за последний месяц. Функционал обработки следующий:
Форма обработки для получения статистики Yandex.Wordstat |
В поле "Поиск" вводим фразу, нажимаем "Получить статистику" и через некоторое время в табличных частях появляется статистика по ключевым фразам, где участвует введенная фраза, и статистика по связанным запросам. Вот так выглядит программный код команды по получению статистики запросов Yandex.Wordstat:
// Получаем объект и менеджер обработки для // дальнейшего вызова экспортных процедур ОбработкаОбъект = РеквизитФормыВЗначение("Объект"); МенеджерОбработки = Обработки.POSTЗапрос_JSON; // Очищаем таблицы со статистикой Объект.СтатистикаПоисковыхЗапросов.Очистить(); Объект.СтатистикаСвязанныхЗапросов.Очистить(); // Получаем список отчетов, сформированных или ожидающих // формирования, и удаляем их, чтобы сформировать новые СписокОтчетов = МенеджерОбработки.ВыполнитьМетодСервиса("GetWordstatReportList", , Режим); Для Каждого Отчет Из СписокОтчетов Цикл IDОтчета = Отчет["ReportID"]; МенеджерОбработки.ВыполнитьМетодСервиса("DeleteWordstatReport", IDОтчета, Режим); КонецЦикла; // Создаем отчет по ключевой фразе // Сначала создаем массив со списком фраз, по которым // нужно получить статистику. После массив добавляем в // структуру по ключу "Phrases" и вызываем метод для // создания отчета ПараметрыМетода = Новый Структура; МассивФразДляОбработки = Новый Массив; МассивФразДляОбработки.Добавить(Объект.Поиск); ПараметрыМетода.Вставить("Phrases", МассивФразДляОбработки); ИдентификаторСозданногоОтчета = МенеджерОбработки.ВыполнитьМетодСервиса("CreateNewWordstatReport", ПараметрыМетода, Режим); // Ожидаем пока отчет не будет сформирован ОтчетГотов = Ложь; КоличествоПопытокПолученияОтчета = 0; Пока НЕ ОтчетГотов И КоличествоПопытокПолученияОтчета < 10 Цикл Обработки.POSTЗапрос_JSON.Ожидание(5); // Проверяем сформирован ли наш отчет СписокОтчетов = МенеджерОбработки.ВыполнитьМетодСервиса("GetWordstatReportList",, Режим); Для Каждого Отчет Из СписокОтчетов Цикл IDОтчета = Отчет["ReportID"]; Если IDОтчета = ИдентификаторСозданногоОтчета Тогда СтатусОтчета = Отчет["StatusReport"]; Если СтатусОтчета = "Done" Тогда ОтчетГотов = Истина; Прервать; КонецЕсли; КонецЕсли; КонецЦикла; // Если отчет готов, то получаем данные статистики // и заполняем таб. части обработки Если ОтчетГотов Тогда ДанныеОтчета = МенеджерОбработки.ВыполнитьМетодСервиса("GetWordstatReport", ИдентификаторСозданногоОтчета, Режим); Для Каждого Стат Из ДанныеОтчета Цикл МассивСтатистики = Стат["SearchedWith"]; Для Каждого ЭлСтат Из МассивСтатистики Цикл НовСтр =
Объект.СтатистикаПоисковыхЗапросов.Добавить(); НовСтр.КлючеваяФраза = ЭлСтат["Phrase"]; НовСтр.КоличествоЗапросов = ЭлСтат["Shows"]; КонецЦикла; МассивСтатистики = Стат["SearchedAlso"]; Для Каждого ЭлСтат Из МассивСтатистики Цикл НовСтр =
Объект.СтатистикаСвязанныхЗапросов.Добавить(); НовСтр.КлючеваяФраза = ЭлСтат["Phrase"]; НовСтр.КоличествоЗапросов = ЭлСтат["Shows"]; КонецЦикла; КонецЦикла; Прервать; КонецЕсли; КоличествоПопытокПолученияОтчета = КоличествоПопытокПолученияОтчета + 1; КонецЦикла;
Мы использовали три метода Яндекс.Директ:
Рассматривать каждый из методов мы не будем, подробнее о них Вы можете узнать в официальной документации по ссылкам выше.
Функция "ВыполнитьМетодСервиса()" выполняет следующие действия:
Функция ВыполнитьМетодСервиса(ИмяМетода, ПараметрыМетода = Неопределено, Режим = 1) Экспорт // Формируем структуру параметров метода // Кроме переданных параметров обязательно // заполняется токен и имя метода, а также // язык ПараметрыЗапроса = Новый Структура; ПараметрыЗапроса.Вставить("token",
Константы.ТокенДоступаYandex.Получить()); ПараметрыЗапроса.Вставить("method", ИмяМетода); Если НЕ ПараметрыМетода = Неопределено Тогда ПараметрыЗапроса.Вставить("param", ПараметрыМетода); КонецЕсли; ПараметрыЗапроса.Вставить("locale", "ru"); // Отправляем POST-запрос с телом в формате JSON РезультатЗапроса = ОтправитьЗапросJSON(ПараметрыЗапроса, Режим); // Обрабатываем результат. Структура результата зависит // от метода. В случае ошибки выводим исключение Результат = РезультатЗапроса.Получить("data"); Если НЕ Результат = Неопределено Тогда Возврат РезультатЗапроса["data"]; Иначе КодОшибки = РезультатЗапроса["error_code"]; КраткоеОписание = РезультатЗапроса["error_str"]; ДеталиОшибки = РезультатЗапроса["error_detail"]; СообщениеОбОшибке = "Ошибка обращения к сервисам Yandex!" + Символы.ПС + "Код ошибки: " + КодОшибки + Символы.ПС + "Описание: " + КраткоеОписание + Символы.ПС + ?(ЗначениеЗаполнено(ДеталиОшибки),"Подробно: " + ДеталиОшибки, ""); ВызватьИсключение СообщениеОбОшибке; КонецЕсли; КонецФункции
Преобразование структуры параметров в текст JSON осуществляется в функции "ОтправитьЗапросJSON()". Там же выполняется и обратное преобразование текста JSON в типы данных 1С:Предприятия 8. Вот содержимое этой процедуры:
Функция ОтправитьЗапросJSON(ПараметрыЗапроса, Режим = 1) Экспорт // Адрес для отправки POST-запросов к API Сервер = "api.direct.yandex.ru"; Ресурс = "/live/v4/json/"; HTTP = Новый HTTPСоединение(Сервер,,,,,Истина); ФайлЗапроса = ПолучитьИмяВременногоФайла(); // Преобразуем типы платформы в JSON СтрокаJSON = ЗаписатьJSON(ПараметрыЗапроса); ТекстовыйФайл = Новый ТекстовыйДокумент; ТекстовыйФайл.УстановитьТекст(СтрокаJSON); ТекстовыйФайл.Записать(ФайлЗапроса, КодировкаТекста.ANSI); ФайлРезультата = ПолучитьИмяВременногоФайла(); ЗаголовокHTTP = Новый Соответствие(); ФайлОтправки = Новый Файл(ФайлЗапроса); РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер()); ЗаголовокHTTP.Вставить("Content-Length",РазмерФайлаОтправки); ЗаголовокHTTP.Вставить("Content-Type","application/json; charset=utf-8"); HTTP.ОтправитьДляОбработки(ФайлЗапроса,Ресурс,
ФайлРезультата,ЗаголовокHTTP); ТекстовыйФайлОтвет = Новый ТекстовыйДокумент; ТекстовыйФайлОтвет.Прочитать(ФайлРезультата,КодировкаТекста.UTF8); СтрокаJSONРезультат = ТекстовыйФайлОтвет.ПолучитьТекст(); Попытка УдалитьФайлы(ФайлЗапроса); Исключение КонецПопытки; Попытка УдалитьФайлы(ФайлРезультата); Исключение КонецПопытки; // Преобразуем JSON в типы платформы Возврат ПрочитатьJSON(СтрокаJSONРезультат); КонецФункции
Подробнее посмотреть принцип работы алгоритмов работы с JSON Вы можете в тестовой конфигурации или в блоге Александра Переверзева.
Пример рабочий, статистику получает без проблем! Но столкнулся с проблемой, решение которой не нашел. Если искать статистику, не вводя кириллицу - все работает отлично! Стоит только ввести русские буквы, сразу возникают проблемы с кодировками.
Ошибка кодировки при отправке POST-запросом кириллицы |
Проблему решил отказавшись от использования собственных средств платформы для отправки POST-запросов.
РЕШЕНИЕ ПРОБЛЕМЫ
Написал небольшую утилиту на .NET Framework, которая отправляет POST-запрос с указными данными и возвращает тело ответа. Утилита не имеет графического интерфейса, запуск производится из командной строки через передачу параметров.
- // Параметры: server - сервер для отправки запроса
- // service - ссылка на сервис сервера
- // fileWithJSON - путь к файлу с телом запроса
- // Туда же и поместится ответ сервера
- // timeout - время ожидания ответа от сервера
- public static void SendQuery(string server, string service, string fileWithJSON, int timeout)
- {
- try
- {
- string json = System.IO.File.ReadAllText(fileWithJSON);
- byte[] body = Encoding.UTF8.GetBytes(json);
- HttpWebRequest request =
- (HttpWebRequest)WebRequest.Create("https://" + server + service);
- request.Timeout = timeout;
- request.Method = "POST";
- request.ContentType = "application/json";
- request.ContentLength = body.Length;
- using (Stream stream = request.GetRequestStream())
- {
- stream.Write(body, 0, body.Length);
- stream.Close();
- }
- string answer = "";
- using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
- {
- using (StreamReader stream =
- new StreamReader(response.GetResponseStream(), Encoding.UTF8))
- {
- answer = stream.ReadToEnd();
- }
- response.Close();
- }
- string[] lines = { answer };
- System.IO.File.WriteAllLines(fileWithJSON, lines);
- }
- catch (Exception ex)
- {
- string info = "[ERROR]: " + ex.Message;
- string[] lines = { info };
- System.IO.File.WriteAllLines(fileWithJSON, lines);
- }
- }
Пример использования утилиты Вы можете посмотреть в тестовой конфигурации, подробно рассматривать ее работу не буду, т.к. это выходит за рамки статьи.
В обработке получения статистики Yandex.Wordstat в тестовой конфигурации можно использовать как встроенные средства платформы, так и написанную мной утилиту. Выбор осуществляется на форме обработки:
Выбор режима отправки POST-запроса |
Не забудьте установить .NET Framework 4.5, чтобы утилита заработала!
ЗАКЛЮЧЕНИЕ
Интеграция - вот где может стать незаменимым использование GET и POST-запросов в платформе 1С:Предприятие 8.x.
В статье мы рассмотрели их использование для работы с сервисами Yandex.Direct и Yandex.Wordstat. Разобравшись в теме можно настраивать интеграцию с любыми сервисами, предоставляющими API. Тот же Google использует похожую схему авторизации и работу посредством POST-запросов в формате JSON или SOAP. Пример GET-запроса продемонстрировал как выполнить скачивание файла с веб-сервера.
Проблему, возникшую с кодировкой, не удалось решить в короткий срок, поэтому было принято решение использовать утилиту на .NET. Если кто-нибудь из читателей знает решение проблемы, то прошу помочь поправить алгоритмы в тестовой конфигурации и поделиться измененными алгоритмами.
Тестовой конфы нет.
ОтветитьУдалитьТестовая конфа будет?
ОтветитьУдалитьМеня зовут господин Бенжамин. И твои деньги у меня. Ты их больше не увидишь, а сам я уже в Австралии.
ОтветитьУдалитьСпасибо за сотрудничество. Удачи!