2016-12-28 5 views
1

Я пытаюсь сгенерировать Google Презентации из Google Таблиц; использовали сценарий Sheets без проблем, но когда я пытаюсь включить Google Slides, после проверки подлинности и получения запроса разрешения Oauth, я получаю эту ошибку, с которой я не могу найти ссылку; Я убедился, что API Google Презентаций и Drive API включены в Консоли разработчиков.403 ошибка с сообщением «API Google слайдов не использовался в проекте ... раньше или он отключен»

Запрос не удался для https://slides.googleapis.com/v1/presentations/ ... Обратный код: 403. Усеченный ответ сервера: {"error": {"code": 403, "message": "Google Slides API не был использован в проекте project-id- ... до или это disab ... (используйте параметр muteHttpExceptions для проверки полного ответа) (строка 93, файл «Код») «

Ошибка кода в следующем порядке: функция, которая сбой, была скопирована с How to download Google Slides as images? . ID клиента и секрет определены, пропущены только для безопасности

// from https://mashe.hawksey.info/2015/10/setting-up-oauth2-access-with-google-apps-script-blogger-api-example/ 

function getService() { 
    // Create a new service with the given name. The name will be used when 
    // persisting the authorized token, so ensure it is unique within the 
    // scope of the property store. 
    return OAuth2.createService('slidesOauth') 

     // Set the endpoint URLs, which are the same for all Google services. 
     .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth') 
     .setTokenUrl('https://accounts.google.com/o/oauth2/token') 


     // Set the client ID and secret, from the Google Developers Console. 
     .setClientId(CLIENT_ID) 
     .setClientSecret(CLIENT_SECRET) 

     // Set the name of the callback function in the script referenced 
     // above that should be invoked to complete the OAuth flow. 
     .setCallbackFunction('authCallback') 

     // Set the property store where authorized tokens should be persisted. 
     .setPropertyStore(PropertiesService.getUserProperties()) 

     // Set the scopes to request (space-separated for Google services). 
     // this is blogger read only scope for write access is: 
     // https://www.googleapis.com/auth/blogger 
     .setScope('https://www.googleapis.com/auth/blogger.readonly') 

     // Below are Google-specific OAuth2 parameters. 

     // Sets the login hint, which will prevent the account chooser screen 
     // from being shown to users logged in with multiple accounts. 
     .setParam('login_hint', Session.getActiveUser().getEmail()) 

     // Requests offline access. 
     .setParam('access_type', 'offline') 

     // Forces the approval prompt every time. This is useful for testing, 
     // but not desirable in a production application. 
     .setParam('approval_prompt', 'force'); 
} 

function authCallback(request) { 
    var oauthService = getService(); 
    var isAuthorized = oauthService.handleCallback(request); 
    if (isAuthorized) { 
    return HtmlService.createHtmlOutput('Success! You can close this tab.'); 
    } else { 
    return HtmlService.createHtmlOutput('Denied. You can close this tab'); 
    } 
} 

// from https://stackoverflow.com/questions/31662455/how-to-download-google-slides-as-images/40678925#40678925 

function downloadPresentation(id) { 
    var slideIds = getSlideIds(id); 

    for (var i = 0, slideId; slideId = slideIds[i]; i++) { 
    downloadSlide('Slide ' + (i + 1), id, slideId); 
    } 
} 
function downloadSlide(name, presentationId, slideId) { 
    var url = 'https://docs.google.com/presentation/d/' + presentationId + 
    '/export/png?id=' + presentationId + '&pageid=' + slideId; 
    var options = { 
    headers: { 
     Authorization: 'Bearer ' + getService().getAccessToken() 
    } 
    }; 
    var response = UrlFetchApp.fetch(url, options); // This is the failing line 93 
    var image = response.getAs(MimeType.PNG); 
    image.setName(name); 
    DriveApp.createFile(image); 
} 
+0

Включены ли API для правильного идентификатора проекта? Выберите из раскрывающегося списка проекта в консоли разработчика? (Я упоминаю об этом, так как раньше у меня была эта ошибка, чтобы включить API в неправильный проект) – Bardy

+0

Да, это единственный проект в этой учетной записи и потребовалось некоторое время, чтобы выяснить, как включить API для проекта. Но спасибо за предложение –

ответ

1

EDIT: я получил эту работу с этим кодом Snipp et:

var CLIENT_ID = '...'; 
var CLIENT_SECRET = '...'; 
var PRESENTATION_ID = '...'; 

// from https://mashe.hawksey.info/2015/10/setting-up-oauth2-access-with-google-apps-script-blogger-api-example/ 

function getService() { 
    // Create a new service with the given name. The name will be used when 
    // persisting the authorized token, so ensure it is unique within the 
    // scope of the property store. 
    return OAuth2.createService('slidesOauth') 

     // Set the endpoint URLs, which are the same for all Google services. 
     .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth') 
     .setTokenUrl('https://accounts.google.com/o/oauth2/token') 


     // Set the client ID and secret, from the Google Developers Console. 
     .setClientId(CLIENT_ID) 
     .setClientSecret(CLIENT_SECRET) 

     // Set the name of the callback function in the script referenced 
     // above that should be invoked to complete the OAuth flow. 
     .setCallbackFunction('authCallback') 

     // Set the property store where authorized tokens should be persisted. 
     .setPropertyStore(PropertiesService.getUserProperties()) 

     // Set the scopes to request (space-separated for Google services). 
     .setScope('https://www.googleapis.com/auth/drive') 

     // Below are Google-specific OAuth2 parameters. 

     // Sets the login hint, which will prevent the account chooser screen 
     // from being shown to users logged in with multiple accounts. 
     .setParam('login_hint', Session.getActiveUser().getEmail()) 

     // Requests offline access. 
     .setParam('access_type', 'offline') 

     // Forces the approval prompt every time. This is useful for testing, 
     // but not desirable in a production application. 
     .setParam('approval_prompt', 'force'); 
} 

function authCallback(request) { 
    var oauthService = getService(); 
    var isAuthorized = oauthService.handleCallback(request); 
    if (isAuthorized) { 
    return HtmlService.createHtmlOutput('Success! You can close this tab.'); 
    } else { 
    return HtmlService.createHtmlOutput('Denied. You can close this tab'); 
    } 
} 

function getSlideIds(presentationId) { 
    var url = 'https://slides.googleapis.com/v1/presentations/' + presentationId; 
    var options = { 
    headers: { 
     Authorization: 'Bearer ' + getService().getAccessToken() 
    } 
    }; 
    var response = UrlFetchApp.fetch(url, options); 

    var slideData = JSON.parse(response); 
    return slideData.slides.map(function(slide) { 
    return slide.objectId; 
    }); 
} 


// from http://stackoverflow.com/questions/31662455/how-to-download-google-slides-as-images/40678925#40678925 

function downloadPresentation(id) { 
    var slideIds = getSlideIds(id); 

    for (var i = 0, slideId; slideId = slideIds[i]; i++) { 
    downloadSlide('Slide ' + (i + 1), id, slideId); 
    } 
} 

function downloadSlide(name, presentationId, slideId) { 
    var url = 'https://docs.google.com/presentation/d/' + presentationId + 
    '/export/png?id=' + presentationId + '&pageid=' + slideId; 
    var options = { 
    headers: { 
     Authorization: 'Bearer ' + getService().getAccessToken() 
    } 
    }; 
    var response = UrlFetchApp.fetch(url, options); // This is the failing line 93 
    var image = response.getAs(MimeType.PNG); 
    image.setName(name); 
    DriveApp.createFile(image); 
} 

function start() { 
    var service = getService(); 
    var authorizationUrl = service.getAuthorizationUrl(); 
    Logger.log('Open the following URL and re-run the script: %s', 
     authorizationUrl); 

    if (service.hasAccess()) { 
    downloadPresentation(PRESENTATION_ID); 
    } 
} 

Я бы предположил, что идентификатор клиента и секрет не связаны с проектом, с которого, по вашему мнению, они исходят. Вы можете проверить это, посетив your project's credentials page и посмотреть, есть ли соответствующий идентификатор клиента, указанный в разделе «Идентификаторы клиента OAuth 2.0». Проект, содержащий этот идентификатор клиента, должен иметь API слайдов.

Также примечание: конечная точка/export/png, которую вы используете, не является документированным/поддерживаемым API Google, поэтому его можно переименовать или разбить в будущем. Если вы заинтересованы в официальном API для получения предоставленных PNG слайдов через API слайдов, следуйте вместе с этим issue on the tracker.


Предыдущее содержание:

Ваш код также немного отличается от фрагмента кода вы копируете с. Для получения значения заголовка авторизации используется ScriptApp.getOAuthToken(), но вы вызываете другую функцию getService().getAccessToken(). Похоже, вы используете библиотеку apps-script-oauth2 для создания вашего токена OAuth. Если это так, подтвердите, что API-интерфейс слайдов включен в проекте консоли разработчика, который сгенерировал клиентский идентификатор и секрет клиента, который вы передаете, до OAuth2.createService, так как это не обязательно тот же проект, который прилагается к вашему скрипту. Если вы можете переключиться на ScriptApp.getOAuthToken(), это может сработать.

Если это не исправить вашу проблему, не задумываясь о предоставлении большего количества кода? Этот фрагмент, который вы вставили, похоже, не соответствует сообщению об ошибке, поскольку ваш код, как представляется, делает запрос на docs.google.com, а не slides.googleapis.com, как указано в ошибке.

+0

Добавлен больше кода; как вы говорите, я заменил вызов ScriptApp функцией, которая позволила мне контролировать клиентский и клиентский секрет. Фрагмент правильный, я запрашиваю с docs.google.com, поскольку слайды, которые я хочу использовать в качестве шаблона, находятся на странице https: //docs.google.com/presentation/d/1V7k5UTj ... но похоже, что это вызывает перенаправления. –

+0

@Bruno, добавив часть, которая на самом деле вызывает 'downloadSlide'? Я могу попытаться воспроизвести весь ваш сценарий. Я все еще подозреваю, что идентификатор/секрет клиента принадлежит проекту, который вы не ожидаете, что API-интерфейс не включен. –

+0

Вы правы, пропустили функцию, которая вызывает downloadSlide, в то время как это не совсем относится к проблеме. Основная функция просто вызывает downloadSlides с действительным идентификатором (дважды проверяется, последний раз только что добавлен ID на https://docs.google.com/presentation/d/ и он работает правильно). Я также дважды проверил проект, это единственный проект, связанный с учетной записью, и он сообщает, что API Google Диска и Google Презентации включены. Я все еще думаю, что ключом к проблеме является сообщение об ошибке на стороне «впервые использовавшегося», а не отключено. –

0

Краткая версия решения: Благодаря усилиям Мориса Кодика я получил и его код, и мою работу.

Проблема была с Уполномоченным переориентировать установки URIS в учетных данных OAuth, который должен был быть установлен в

https://script.google.com/macros/d/[ScriptID]/usercallback

-1

Это не является прямым ответом на О.П. вопрос но напрямую обратиться к 1-й части из их 1-го предложения, которое: «Я пытаюсь создать Google Презентации из Google Таблиц ....» Это точный вариант использования, который я создал для video (and accompanying blog post [s]).ПРИМЕЧАНИЕ: полезная нагрузка в сообщении - JSON, но полный пример из видео находится в Python, поэтому разработчики не-Python могут просто использовать его как псевдокод.)

+0

Я видел, что до внедрения моего кода ... хорошая ссылка, но не ответ на вопрос, как вы говорите –

 Смежные вопросы

  • Нет связанных вопросов^_^