1С, oauth2, Google API и Google Merchant. Сбор данных и парсинг

14.09.17

Интеграция - WEB-интеграция

Всем привет. Стала задача, собрать данные с Google Merchants и внести их в 1С, для более детального анализа того, что сейчас показывается, что нет и какие проблемы при этом есть. Если кому это интересно, прошу под кат.

Опыт програмирования на платформе 1С у меня крайне маленький, порядка года, поэтому за какие-то банальные вещи, прощу прощения сразу. Статья будет основана на данной статье, но там не описан процесс парсинга + не описан процесс на HTTPСоединение, что является более универсальным и более удобным. 

Все процедуры производились на клиент-серверном режиме, в конфигурации УТ 10.3 (10.3.13.2) на платформе 1С 8.3 (8.3.8.2322).

Использованные механизмы описаны в ключевых словах.

Еще перед тем, как пойдет код, я хотел бы ответить на вопрос, зачем я это вообще пишу? Во первых, для тех, кто ищет информацию по данным технологиям, во вторых, для того, чтобы получить обратную связь от вас, услышать какие-то советы и как итог - сделать себя лучше =) 

Пара ссылок на основне определения:

  1. oauth2
  2. HTTP
  3. POST/GET запросы
  4. JSON
  5. API

 

Погнали, итак, стоит цель, получить данные с Google Merchant и занести их в 1С.

Сделаем декомпозицию задачи.

  1. Получить данные для авторизации в Google
    1. Сделать уч. запись в Google Cloud Console 
      1. Добавить в разделе API , работу с  Content API for Shopping
      2. Сделать учетную запись с типом "Други типы" - http://jmp.sh/9ikhvbp
      3. Получить ClientId и Secret
  2. Добавить свою учетную запись (которая для Google Cloud Console) в Merchant с обычными правами.
  3. Получить Токен для запросов
  4. Сделать регламент Запроса данных/Обновления токена
  5. При запросе данных парсить JSON и вносить их в свою УС

1 и 2 пункт, делаются очень быстро и заострять свое внимание здесь не будем. 

Веселуха начинается с пункта 3. 

Для получения первого токена, пришлос использовать внешнюю обработку с HTML полем  и кнопкой (Если кто знает, как сделать проще, напишите в комментариях)

При нажатии кнопки, появится окно ввода логин/Пароля для учетки Google, вводим :


    client_id = ВАШ_CLIEN_ID_ПОЛУЧЕННЫЙ_В_GOOGLE_CLOUD
	
	ЧастьЗапроса = "response_type=code"+"&";
    ЧастьЗапроса = ЧастьЗапроса + "client_id="+ client_id + "&";
    ЧастьЗапроса = ЧастьЗапроса + "redirect_uri=http://localhost" + "&";
    ЧастьЗапроса = ЧастьЗапроса + "access_type=offline"+"&";
    ЧастьЗапроса = Параметры + "scope=https://www.googleapis.com/auth/content";
    АдресАвторизации = "https://accounts.google.com/o/oauth2/auth" + "?";
    ПолныйАдресАвторизации = АдресАвторизации + ЧастьЗапроса;
    
    ЭлементыФормы.ВАШ_HTTML_ПОЛЕ.Перейти(ПолныйАдресАвторизации);

Для HTML поля, в обработчике "ДокументСформирован", вставим код для отлова Code (Строка, необходимая для обмена на токен)

     Если Сред(ЭлементыФормы.Гугл.Документ.URLUnencoded,1,23) = "http://localhost/?code=" Тогда
		
		Code	=	Сред(ЭлементыФормы.Гугл.Документ.URLUnencoded,24);
		
	 КонецЕсли;

Теперь у нас есть данные, для получения Token и RefreshToken

Делаем процедуру Получения Токена 

    Сервер =  "accounts.google.com";
	Ресурс = "/o/oauth2/token";
	КодДоступа 		= 	Code;
	client_id		=	ВАШ_CLIENT_ID
	client_secret 	=	ВАШ_SECRET

	СтрокаЗапроса = "client_id=" + client_id + "&";
	СтрокаЗапроса = СтрокаЗапроса + "client_secret=" + client_secret + "&";
	СтрокаЗапроса = СтрокаЗапроса + "grant_type=authorization_code" + "&";
	СтрокаЗапроса = СтрокаЗапроса + "code=" + КодДоступа + "&";
	СтрокаЗапроса = СтрокаЗапроса + "redirect_uri=http://localhost";

	Соединение = Новый HTTPСоединение(Сервер,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);

	Заголовки  = Новый Соответствие;
	Заголовки.Вставить("Content-Type","application/x-www-form-urlencoded");
	
	ЗапросХТТП = Новый HTTPЗапрос(Ресурс,Заголовки);
	ЗапросХТТП.УстановитьТелоИзСтроки(СтрокаЗапроса);

	Ответ = Соединение.ВызватьHTTPМетод("POST",ЗапросХТТП);
	
    Если Ответ.КодСостояния <> 200 Тогда Возврат КонецЕсли;

	Строка = Ответ.ПолучитьТелоКакСтроку();
	
    Чтение = Новый ЧтениеJSON();
	Чтение.УстановитьСтроку(Строка);

	Фабрика = ФабрикаXDTO.ПрочитатьJSON(Чтение);
	
    Чтение.Закрыть();
	
    Токен           = Фабрика.access_token;
	ТокенОбновления = Фабрика.refresh_token;

Тут конечно стоило бы написать кучу инфы про ФабрикуXDTO , но ее на просторах Инфостарта столько, что уже просто стыдно, что-то писать далее. Но если не читали, то очень советую прочитать цикл статей  , очень подробно и интересно расписали.

Но если вкратце, то фабрика преобразует наш XML/JSON в объект, с которым можно работать, через точку, что крайне удобно и не надо парсить документ старыми методами, перебором узлов, с проверкой на закрытие-открытие.

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

 

    Сервер =  "accounts.google.com";
	Ресурс = "/o/oauth2/token";
	КодДоступа 		= 	Code;
	client_id		=	ВАШ_CLIEN_ID
	client_secret 	=	ВАШ_SECRET

	СтрокаЗапроса = "client_id="  + client_id + "&";
	СтрокаЗапроса = СтрокаЗапроса + "client_secret=" + client_secret + "&";
	СтрокаЗапроса = СтрокаЗапроса + "grant_type=refresh_token" + "&";
	СтрокаЗапроса = СтрокаЗапроса + "refresh_token=" + ТокенОбновления;	

	Соединение = Новый HTTPСоединение(Сервер,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);

	Заголовки  = Новый Соответствие;
	Заголовки.Вставить("Content-Type","application/x-www-form-urlencoded");
	
	ЗапросХТТП = Новый HTTPЗапрос(Ресурс,Заголовки);
	ЗапросХТТП.УстановитьТелоИзСтроки(СтрокаЗапроса);

	Ответ = Соединение.ВызватьHTTPМетод("POST",ЗапросХТТП);
	Если Ответ.КодСостояния <> 200 Тогда Возврат КонецЕсли;

	Строка = Ответ.ПолучитьТелоКакСтроку();
	Чтение = Новый ЧтениеJSON();
	Чтение.УстановитьСтроку(Строка);

	Фабрика = ФабрикаXDTO.ПрочитатьJSON(Чтение);
	Чтение.Закрыть();
	Токен = Фабрика.access_token;

 

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

Google сделал, конечно, хороший  инструмент, но в нем просто не написана правильная локига создания запроса, поэтому в дело идут инструменты разработчика. 

 

Для примера, получение списка товарных позиций, из документации выглядит вот так

GET https://www.googleapis.com/content/v2/ИДЕНТИФИКАТОР_МАГАЗИНА_В_MERCHANT/products

Но если вы его сделаете, получите просто ошибку ... 

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

https://www.googleapis.com/content/v2/ID_МАГАЗИНА_В_МЕРЧАНТ/productstatuses?maxResults=250&key=ВАШ_CLIENT_ID

 + Заголовок с токен

Теперь код процедуры, с рекурсией =) 

Почему так, потому что гугл, отдаем всего 250 позиций, за один запрос. Так как у нас 10 000 тороговых предложений, то мне надо примерно 41 раз сделать вызов метода ...

Поэтому, рекурсия =) 

Сам вызов процедуры

ПолучениеФайлаСМерчанта(АдресРесурса,ТокенСтраницы)

АдресРесурса = Это тот же адрес, только с доп параметром pageToken=, с этим параметром, гугл отдаст следующую страницу, с новыми позициями.

    Путь   = Я_ФАЙЛЫ_СОХРАНИЛ_НА_ДИСК
	Сервер = "www.googleapis.com";
	Запрос =  АдресРесурса;
	Соединение = Новый HTTPСоединение(Сервер,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
	Заголовки  = Новый Соответствие;
	Заголовки.Вставить("Authorization","Bearer " + Токен);
	ЗапросХТТП = Новый HTTPЗапрос;
	ЗапросХТТП.АдресРесурса	=	Запрос;
	ЗапросХТТП.Заголовки = Заголовки;
	
	Соединение.ВызватьHTTPМетод("GET",ЗапросХТТП);
	Ответ = Соединение.ВызватьHTTPМетод("GET",ЗапросХТТП);
	Файл = Ответ.ПолучитьТелоКакДвоичныеДанные();
	Файл.Записать(Путь + "json_" + ТокенСтраницы + ".json");
	
	Чтение = Новый ЧтениеJSON;
	Чтение.ОткрытьФайл(Путь + "json_" + ТокенСтраницы + ".json");
	
	Фабрика = ФабрикаXDTO.ПрочитатьJSON(Чтение);
	Чтение.Закрыть();
	Если ОбъектXDTOСодержитСвойство(Фабрика,"nextPageToken") Тогда
		Если Фабрика.nextPageToken <> "" Тогда
			ПолучениеФайлаСМерчанта("/content/v2/ID_МАГАЗИНА/productstatuses?maxResults=250&pageToken="+Фабрика.nextPageToken+"&key=897236016313-ceggltgsseaoke0bfb48sivrr3dj766k.apps.googleusercontent.com",Фабрика.nextPageToken);
		КонецЕсли;
	КонецЕсли;

 

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

МассивФайлов = НайтиФайлы(Путь,"*.json");
	
	Если МассивФайлов.Количество() = 0 Тогда
		Сообщить("Файлов не найдено");
		Возврат;
	КонецЕсли;
	
	ТабличноеПоле8.Очистить();
	Для Каждого Файл из МассивФайлов Цикл
		Чтение = Новый ЧтениеJSON;
		Чтение.ОткрытьФайл(Файл.ПолноеИмя);
		Фабрика = ФабрикаXDTO.ПрочитатьJSON(Чтение);
		Чтение.Закрыть();
		
		Для каждого Товар из КоллекцияXDTO(Фабрика.resources.resources) Цикл
			
			стр = ТабличноеПоле8.Добавить();
			Стр.Номенклатура 	= 	Справочники.Номенклатура.НайтиПоРеквизиту("Артикул",Сред(Товар.ProductID,14));
			Стр.Артикул 		=	Стр.Номенклатура.Артикул;
			Стр.ЦеноваяГруппа	=	Стр.Номенклатура.ЦеноваяГруппа;
			Стр.Категория		=	Стр.Номенклатура.МЮС_КаталогНоменклатуры;
			Стр.Ответственный	=	Стр.Номенклатура.МЮС_КаталогНоменклатуры.Ответственный;
			Стр.Ссылка 			=	Товар.Link;
			Стр.ProductID		=	Товар.ProductID;
			Стр.Displayed       =   Товар.destinationStatuses.destinationStatuses[0].approvalStatus;
			Стр.Shoping		    =   Товар.destinationStatuses.destinationStatuses[1].approvalStatus;
			
			
			Если ОбъектXDTOСодержитСвойство(Товар,"dataQualityIssues") тогда
				Для каждого Строка из КоллекцияXDTO(Товар.dataQualityIssues.dataQualityIssues) Цикл
				 					
					Стр.IDerror 	= 	?(ОбъектXDTOСодержитСвойство(Строка,"id")			,Строка.id		,"");
					Стр.severity 	= 	?(ОбъектXDTOСодержитСвойство(Строка,"severity")		,Строка.severity	,"");
					Стр.timestamp 	= 	?(ОбъектXDTOСодержитСвойство(Строка,"timestamp")	,Строка.timestamp	,"");
					Стр.Location	=	?(ОбъектXDTOСодержитСвойство(Строка,"Location")		,Строка.Location	,"");
					
				КонецЦикла;
			КонецЕсли;
			
		
		  КонецЦикла;
		УдалитьФайлы(Файл.ПолноеИмя);
		
	КонецЦикла;
	
	ЭлементыФормы.ТабличноеПоле8.СоздатьКолонки();

 

Тут используется 2 функции, одна проверяет на наличие свойства, вторая проверяет тип объекта XDTO, список он, или единичный

 

Код обеих, авторство не укажу, найдены на просторах Инфостарта.

Функция   ОбъектXDTOСодержитСвойство(ОбъектXDTO, Свойство)
	
	ЕстьСвойство = ОбъектXDTO.Свойства().Получить(Свойство) <> Неопределено
		И ОбъектXDTO[Свойство] <> Неопределено;
		
	Возврат ЕстьСвойство;
	
КонецФункции
Функция   КоллекцияXDTO(Элемент)
    Если ТипЗнч(Элемент)=Тип("ОбъектXDTO") Тогда
        МассивXDTO=Новый Массив;
        МассивXDTO.Добавить(Элемент);
        Возврат МассивXDTO;
    КонецЕсли;
    Возврат Элемент;
КонецФункции

 

В целом все ...

Если вы дочитали это, то уже спасибо =)

Если дадите какой-то хороший совет, буду прям очень рад.

ФабрикаXDTO ЧтениеJSON HTTPСоединение HTTPЗапрос

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    15748    10    17    

11

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    17551    6    15    

13

Интеграция с сервисом vetmanager

WEB-интеграция Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия 3.0 Бытовые услуги, сервис Платные (руб)

Внешняя обработка разрабатывалась для загрузки документов из Ветменеджер в 1С: Бухгалтерия 3.0

12000 руб.

02.02.2021    16360    42    49    

23

[Расширение] БОР-Навигатор.Культура

Зарплата Бюджетный учет WEB-интеграция Обмен с ГосИС Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бюджетный учет Платные (руб)

Расширение конфигурации, включающее в себя объекты, необходимые для подготовки и сдачи отчета "Штатная численность" системы "БОР-Навигатор.Культура" в программе "1С:Зарплата и кадры государственного учреждения", редакция 3.1.

8400 руб.

01.02.2019    25741    9    0    

7

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    88582    160    215    

318
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. shmellevich 134 20.09.17 12:17 Сейчас в теме
Статья хороша +!

А чем не угодил "ПрочитатьJSON(ЧтениеJSON, Истина)" - на выходе будет Соответствие. и безопасность получения свойств проще, и не нужны доп. функции ))

и как себя поведет фабрика если ключом окажется не строка, а например число?

{
   "key1":"value1",
   100:{"part1":50, 
            "part2":30, 
            "part3":20}
}


я когда на подобный джисон попал, долго мучался, было тяжело отойти от уже отлаженного механизма работы с XDTO объектами, все сломать и построить заново )).
user604633_slevin64celevra; +1 Ответить
2. Mi11er 96 20.09.17 17:37 Сейчас в теме
(1) 0_о комментарий к статье... надо будет выпить сегодня.

Чем не угодил, не знаю, привык читать уже через фабрику, можно конечно и через чтение сделать, просто формат который выходил, был протестирован именно на фабрике.

+ у меня не так много опыта в этой теме и когда делаю такие парсеры, делаю не как то универсально, а именно заточенный под этот сервис.
8. uno-c 234 12.12.18 17:35 Сейчас в теме
Если кто знает, как сделать проще, напишите в комментариях
Можно получать access token через 2LO авторизацию https://developers.google.com/identity/protocols/OAuth2ServiceAccount. Это сервер-сервер, без использования учетки пользователя. Проще или нет - субъективно, но 2LO объективно лаконичнее.
4. pbazeliuk 1955 03.10.17 00:46 Сейчас в теме
(1) ПрочитатьJSON, ЗаписатьJSON очень медленныe. Здесь упоминается про это https://infostart.ru/public/640996/, опытным путем удалось подтвердить слова автора.
5. shmellevich 134 03.10.17 15:54 Сейчас в теме
(4) Согласно скрина из статьи видно, что фабрика пишет медленнее, чем даже обычная ЗаписатьJSON в 2 раза.
Или я не правильно понимаю?
6. pbazeliuk 1955 03.10.17 16:07 Сейчас в теме
(5) Про фабрику не знаю, там описано только:
3. ПрочитатьJSON, ЗаписатьJSON - самые медленные
2. Запись в поток - сейчас использую вот этот метод, он почти в 2 раза быстрее, чем предыдущий
1. Запись без контроля - этот пока нет времени реализовать.

По поводу фабрики не знаю, необходимо тестировать.
7. Inkasor 28 09.10.17 01:31 Сейчас в теме
(6)Привет :)

ПрочитатьJSON, ЗаписатьJSON - самые медленные

Дело в том, что 1С как раз по умолчанию инициализирует одну фабрику для быстрой обработки в рамках глобального контекста. Это быстро и удобно для, наверное, 99% задач, стоящих обычно перед коллегами :) Это и есть ПрочитатьJSON, ЗаписатьJSON как они есть.
Мы работаем только на потоке, причем с заранее подготовленными данными, поэтому пишем без контроля, что ещё очень сильно ускоряет обработку.
3. huse 22.09.17 21:17 Сейчас в теме
"Добавить свою учетную запись (которая для Google Cloud Console) в Merchant с обычными правами."

Подскажите как сделать эту операцию для Firebase?

PS content на firebase заменил, но проект запрашивает разрешение и не редиректит. А при нажатии Разрешить пытается открыть страницу с адресом res://ieframe.dll/dnserrordiagoff_webOC.htm#https://accounts.google.com/o/oauth2/approval?as=.......... после чего говорит что не может ее отобразить
9. buzzzard 51 23.07.20 19:50 Сейчас в теме
(3) Вы не разобрались с Firebase случайно?
11. huse 17.12.20 03:41 Сейчас в теме
(9) разобрался но в отношении данной ошибки уже не помню лекарство
10. AxiLLes89 21 26.09.20 05:02 Сейчас в теме
Привет) Статья супер) сообщения в hanhouts не отправлял?
Оставьте свое сообщение