Задача: Требуется загрузка табличного документа в google таблицу. Также желательно иметь возможность получить google таблицу прямо в 1С.
Условие: без использования сторонних библиотек.
У "google sheet" имеется достаточно развитая API. С ней как бы проблем нет, стандартный REST API.
Почитав русскоязычные источники, выяснилось, что основная проблема это авторизация в google api средствами JWT. До платформы 8.3.21 - это было действительно проблемой, так как в 1С отсутствовала поддержка подписания токена алгоритмом sha256.
С выходом платформы 8.3.21, в 1С появился новый объект ТокенДоступа (AccessToken), его мы и будем использовать в решении данной задачи.
Описывать создание сервисного аккаунта не буду. Есть много видео по этой теме. В результате у вас должен быть в наличии JSON файл сервисного пользователя с правами на "Google Sheets API".
Разберем создание JWT токена:
Функция ПолучитьJWTТокен()
ТокенДоступа = Новый ТокенДоступа;
//Алгоритм шифования
//Google API использует алгоритм "RS256"
ТокенДоступа.Заголовки.Вставить("alg", "RS256");
//Формат токена
//Google API использует формат "JWT"
ТокенДоступа.Заголовки.Вставить("typ", "JWT");
//iss - Адрес электронной почты service account
//Данный параметр находится в JSON файле, в свойстве "client_email"
ТокенДоступа.Эмитент = "test@test-11.iam.gserviceaccount.com";
//scope - Список областей, разделенных пробелами, которые определяют ресурсы,
//к которым ваше приложение может получить доступ от имени пользователя.
//Для работы с google таблицами нам хватит двух:
//"https://www.googleapis.com/auth/spreadsheets"
//"https://www.googleapis.com/auth/drive"
ТокенДоступа.ПолезнаяНагрузка.Вставить("scope", "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive");
//aud - A descriptor of the intended target of the assertion
// или дескриптор предполагаемой цели утверждения.
//Данный параметр находится в JSON файле, в свойстве "token_uri"
//И на текущий момент всегда равен "https://oauth2.googleapis.com/token"
ТокенДоступа.ПолезнаяНагрузка.Вставить("aud", "https://oauth2.googleapis.com/token");
//Дополнительно нам нужно указать 2 параметра
//что бы задать время жизни токена
//Первый iat - Числовое значение времени создания токена доступа в формате UnixTime
ТокенДоступа.ВремяСоздания = ТекущаяУниверсальнаяДата() - Дата(1970,1,1,0,0,0);
//Второй exp - Числовое значение времени истечения срока действия токена
//в формате UnixTime. Максимум 1час после iat.
//Вычисляется как iat + 1час
ТокенДоступа.ВремяЖизни = ТокенДоступа.ВремяСоздания + 60 * 60;
//Тут вроде всё хорошо, но 1С упорно, не верно вычисляет время exp
//По этому мы переопределим данный параметр через полезную нагрузку.
ТокенДоступа.ПолезнаяНагрузка.Вставить("exp", Формат(ТокенДоступа.ВремяЖизни, "ЧГ="));
//JWT - Последняя часть формирования токена - это создание подписи.
//Для подписи нам потребуется ключ в формате PEM
//взять его можно так же из файла JSON, в свойстве "private_key"
ТокенДоступа.Подписать(АлгоритмПодписиТокенаДоступа.RS256, "-----BEGIN PRIVATE KEY-----
|MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7VJTUt9Us8cKj
|................................................................
|dn/RsYEONbwQSjIfMPkvxF+8HQ==
|-----END PRIVATE KEY-----");
//Сам JWT токен, это сроковое представление объекта ТокенДоступа
Возврат Строка(ТокенДоступа);
КонецФункции
Запрос получения токена доступа:
Функция ПолучитьНовыйТокен(Знач Токен)
//Создаем заголовки для запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
//Формируем строку запроса
//основной параметр тут "grant_type"
//на данный момент он имеет статичное значение
//"urn:ietf:params:oauth:grant-type:jwt-bearer"
grant_type = КодироватьСтроку("urn:ietf:params:oauth:grant-type:jwt-bearer", СпособКодированияСтроки.КодировкаURL);
ПараметрыЗапроса = СтрШаблон("grant_type=%1&assertion=%2", grant_type, Токен);
ЗапросТекст = СтрШаблон("/token?%1", ПараметрыЗапроса);
//Отправляем POST запрос с нашим токеном в качестве параметра.
Соединение = Новый HTTPСоединение("oauth2.googleapis.com", 443,,,, 30, Новый ЗащищенноеСоединениеOpenSSL);
HTTPЗапрос = Новый HTTPЗапрос(ЗапросТекст, Заголовки);
Результат = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
//И получаем "access_token"
//используемый для дальнейшей работы с google api
Если Результат.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьПоток(Результат.ПолучитьТелоКакПоток());
Возврат ПрочитатьJSON(ЧтениеJSON, Истина).Получить("access_token");
КонецЕсли;
Возврат Неопределено;
КонецФункции