gifts2017

Получение доступа к скачиванию гугл-таблицы

Опубликовал Тарас Курдельчук (softgarant) в раздел Обмен - Интеграция с WEB

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

В общем, когда начинал гуглить, ничего толком не находил. Статьи в основном старые, а так как недавно гугл изменил способ авторизации, то грош теперь таким статьям цена. Решил копать глубже. Наткнулся на несколько интересных ссылок и разобрался.

Немного теории:

Все приложения, получающие доступ к GoogleAPI, должны быть зарегистрированы разработчиком через API-консоль. Для этого необходимо авторизоваться под учетной записью. Для авторизации нужно использовать протокол OAuth 2.0. Другие протоколы авторизации не поддерживаются гуглом.
Все запросы к Google Analytics API должны быть разрешены пользователем, прошедшим аутентификацию.

В общих чертах процедура аутентификации выглядит так:

  1. Создавая приложение, вы регистрируете его в Google Developers Console. (https://console.developers.google.com)
  2. Вы включаете Drive API в Google Developers Console
  3. Когда приложению потребуются пользовательские данные, оно запрашивает у Google определенную область доступа.
  4. Google показывает пользователю диалоговое окно с предложением авторизовать приложение для запроса этих данных.
  5. Если пользователь соглашается, Google предоставляет приложению токен доступа с коротким сроком действия.
  6. Приложение запрашивает пользовательские данные, указывая токен доступа.
  7. Получив действительный запрос и токен, Google возвращает необходимые данные.

Перейдем к практике.

Скачивать будем эту тестовую гугл таблицу:

https://docs.google.com/spreadsheets/d/1QvjMLjBK3HJrJbcuY16Ihwve2B-AgHdEMpiu9SKrkMQ/edit#gid=0&vpid=A1

Сначала включим  Drive API в Google Developers Console

Переходим по ссылке https://console.developers.google.com, и создаем новый проект

После этого выбираем в списке сервис Drive API (к нему необходимо получить доступ приложению)

Далее переходим по ссылке Credentials, чтобы создать идентификаторы приложения

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

Затем создаем ID пользователя, еще раз нажав на поле Credentials. 

 

После завершения получаем

Подготовительные действия завершены. Все дальнейшие действия будут выполняться в среде 1С:Предприятие.

Создаем обработку и добавляем на форму элемент ПолеHTMLДокумента. 

 

В процедуре-обработчике события для кнопки “Авторизация” надо написать код, формирующий адрес страницы авторизации и в последней строке открывающий эту страницу на экране для пользователя.

Процедура КнопкаВыполнитьНажатие(Кнопка)
	ПолучитьОсновыеЗначениеПеремменных();
	ПройтиАвторизацию();	
КонецПроцедуры
Процедура ПолучитьОсновыеЗначениеПеремменных()
	redirect_uri = "http://localhost";
	client_id = "158908578317-u84j5fap070ib8o5jtuvgei0m6d6gsv8.apps.googleusercontent.com";
	client_secret = "w-x-FHvuwtjd7yDygCYi4vqB";
	ID_Файл	= "1QvjMLjBK3HJrJbcuY16Ihwve2B-AgHdEMpiu9SKrkMQ";		
КонецПроцедуры
Процедура ПройтиАвторизацию()
	Параметры = "response_type=code"+"&";
	Параметры = Параметры + "client_id="+ client_id + "&";
	Параметры = Параметры + "redirect_uri=" + redirect_uri + "&";
	Параметры = Параметры + "scope=https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds";
	АдресАвторизации = "https://accounts.google.com/o/oauth2/auth" + "?";
	ПолныйАдресАвторизации = АдресАвторизации + Параметры;
	ЭлементыФормы.Браузер.Перейти(ПолныйАдресАвторизации);
КонецПроцедуры

Таким образом, при нажатии кнопки «Авторизация» пользователю будет выведена страница для выполнения авторизации и выдачи разрешения для доступа к данным таблицы.

Разрешаем доступ приложению. 

Итак, перейдем к скачиванию таблицы. В обработчике действия кнопки "Скачать таблицу" пишем:

Процедура ОсновныеДействияФормыСкачатьТаблицу(Кнопка)
	
	//код доступа берем с заголовка браузера
	//код доступа нужен чтоб получить маркер
	//пишут что код доступа доступен 8 часов. не проверял
	ПолучитьКодДоступа();	
	
	//маркер доступен 1час
	Маркер = ПолучаемМаркер();
	
	Если Найти(Маркер, "Code was already redeemed") = 0 Тогда
		ПолучитьМетаданные();	
	Иначе	
	
	КонецЕсли;
	
	ВременнаяТаблица = ПолучитьИмяВременногоФайла(".xlsx");
	КопироватьФайл(СсылкаДляСкачивания, ВременнаяТаблица);
	
	#Если Клиент Тогда
		Сообщить("Таблица сохранена во временный файл: " + ВременнаяТаблица);
	#КонецЕсли	
	
КонецПроцедуры

Разберем эту процедуру. Сначала нам нужно получить код доступа из заголовка браузера.

Процедура ПолучитьКодДоступа()
	СтрокаСКодом = ЭлементыФормы.Браузер.документ.URLUnencoded;
	Если СтрокаСКодом = "about:blank" Тогда
		#Если Клиент Тогда
			Сообщить("Пройдите авторизацию для получения кода доступа!");	
		#КонецЕсли
		КодДоступа = Неопределено;
	Иначе
		НачалоКода = Найти(ЭлементыФормы.Браузер.документ.URLUnencoded, "=")+1;	
		КодДоступа = Сред(СтрокаСКодом,НачалоКода,СтрДлина(СтрокаСКодом)-1);
	КонецЕсли;
КонецПроцедуры

Далее получаем маркер доступа:

Функция ПолучаемМаркер()
	
	XTTPЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
	Скрипт = Новый COMОбъект("MSScriptControl.ScriptControl");
	Скрипт.language = "javascript";
	Скрипт.AddObject("XTTPЗапрос", XTTPЗапрос);
	Скрипт.Eval("XTTPЗапрос.Option(4)=13056");
	
	XTTPЗапрос.Open("Post", "https://accounts.google.com/o/oauth2/token", 0);
	XTTPЗапрос.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	
	ПараметрыPOST = "grant_type=authorization_code" + "&";
	ПараметрыPOST = ПараметрыPOST + "code=" + КодДоступа + "&";
	
	ПараметрыPOST = ПараметрыPOST + "client_id=" + client_id + "&";
	ПараметрыPOST = ПараметрыPOST + "client_secret=" + client_secret + "&";
	ПараметрыPOST = ПараметрыPOST + "redirect_uri=" + redirect_uri;
	
	XTTPЗапрос.send(ПараметрыPOST);
		
	ТекстОтвета = XTTPЗапрос.responsetext();
	
	//парсим строку. вытаскиваем значение маркера
	НачалоТокена = Найти(ТекстОтвета, "access_token")+17;
	КонецТокена  = Найти(ТекстОтвета, "token_type")-6;
	пМаркер = Сред(ТекстОтвета,НачалоТокена, КонецТокена-НачалоТокена);
	
Возврат пМаркер;
КонецФункции

Получив маркер, можем получить доступ к метаданным нашей таблицы. В метаданных есть много чего интересного, в том числе и ссылка на скачивание (в форматах csv, pdf, xlsx). Итак, получим метаданные нашей таблицы.

Процедура ПолучитьМетаданные()
	ФайлМетаданных = ПолучитьИмяВременногоФайла(".txt");
		XTTPЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
	Скрипт = Новый COMОбъект("MSScriptControl.ScriptControl");
	Скрипт.language = "javascript";
	Скрипт.AddObject("XTTPЗапрос", XTTPЗапрос);
	Скрипт.Eval("XTTPЗапрос.Option(4)=13056");
	
	XTTPЗапрос.Open("GET", "https://www.googleapis.com/drive/v2/files/"+ID_Файл);
	XTTPЗапрос.setRequestHeader("Authorization", "Bearer " + Маркер);
	XTTPЗапрос.send();
		ТекстОтвета = XTTPЗапрос.responsetext();
		СсылкаДляСкачивания = ПолучитьСсылкуДляСкачивания(ТекстОтвета);
КонецПроцедуры

Далее дело за малым. Нужно обработать полученный ответ. Вытягиваем от туда ссылку на скачивание. (В нашем примере в формате .xlsx).

Функция ПолучитьСсылкуДляСкачивания(ТекстОтвета)
	
	СтрокаПоиска = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"": """;
	НачалоСсылки = Найти(ТекстОтвета, СтрокаПоиска)+СтрДлина(СтрокаПоиска);	
	КонецСсылки  = Найти(ТекстОтвета, "userPermission")-8;
	Результат = Сред(ТекстОтвета, НачалоСсылки, КонецСсылки-НачалоСсылки);
	
	Возврат Результат;
	
КонецФункции // ()

И финалочка. Скачиваем таблицу во временный файл
Пример кода:       

ВременнаяТаблица = ПолучитьИмяВременногоФайла(".xlsx");
КопироватьФайл(СсылкаДляСкачивания, ВременнаяТаблица);
#Если Клиент Тогда
Сообщить("Таблица сохранена во временный файл: " + ВременнаяТаблица);
#КонецЕсли	

В результате получим временную .xlsx таблицу

Скачать файлы

Наименование Файл Версия Размер
Обработка гугл-таблицы.epf 6
.epf 11,48Kb
07.12.15
6
.epf 11,48Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Александр Красильников (kao_andi) 01.12.15 07:18
Вопрос, а почему HTTP-запросы реализованы через COM-объект, чем не устроили типовые?
2. Тарас Курдельчук (softgarant) 06.12.15 21:10
(1) kao_andi, чесно говоря не пробовал использовать типовые http-запросы. нашел пример реализации через COM, по этому выбор чисто субъективный
3. Роберт Рождественский (kashafeev) 17.03.16 11:34
А как добавлять данные, в уже имеющуюся Гугл-таблицу (Например для обновления цен). И как сделать это в авто режиме, чтобы не проходить каждый раз авторизацию?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа