【问题标题】:OAuth2 with Google Cloud PrintOAuth2 与 Google 云打印
【发布时间】:2015-08-14 10:38:53
【问题描述】:

我编写了一个连接到 Google 云打印的 Google Apps 脚本来自动执行一些打印。该脚本将按时间间隔自动运行,搜索相关文件,如果找到它会将它们发送到我的打印机。我的代码使用了 OAuthConfig 并且工作正常,但现在该类已被弃用,经过一个周末的反复试验和搜索互联网,我 无法让它与 OAuth2 一起使用强>。

这是运行良好的 OAuthConfig 代码

function printDoc(docId, docTitle, myPrinterId) {

  var scope = 'https://www.googleapis.com/auth/cloudprint';
  var url = 'https://www.google.com/cloudprint/submit'; 
  var payloadOfSubmit = {
    "printerid" : myPrinterId, 
    "title" : docTitle,
    "content"  : docId, 
    "contentType" : "google.kix"  
  };

  var fetchArgs = googleOAuth_('google', scope, payloadOfSubmit); 
  fetchArgs.method = 'POST';
  var responseOfSubmit = UrlFetchApp.fetch(url, fetchArgs);
  var jsonOfSubmit = JSON.parse(responseOfSubmit.getContentText()); 

  return jsonOfSubmit;
}

function googleOAuth_(name, scope, payloadData) {
  var oAuthConfig = UrlFetchApp.addOAuthService(name);
  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oAuthConfig.setConsumerKey("anonymous");
  oAuthConfig.setConsumerSecret("anonymous");
  return {
    oAuthServiceName:name, 
    oAuthUseToken:"always", 
    muteHttpExceptions:true, 
    payload:payloadData
  }; 
}  

我已经成功连接了githublibrary for OAuth2。但是,那里提供的说明以及许多其他站点上提供的说明的不同之处在于,它们假定代码将部署为 Web 服务,提示用户手动单击以授权请求。在我的情况下,代码将保存在 Google Apps 脚本文件中,并且云打印机在同一个 Google 帐户上,所以我不需要这种手动干预或来回使用我的原始 OAuthconfig。

我第一次尝试修改说明是:

function printDoc2(docId, docTitle, myPrinterId) {

  var url = 'https://www.google.com/cloudprint/submit';
  var scope = 'https://www.googleapis.com/auth/cloudprint'; 
  var payloadOfSubmit = {
    "printerid" : myPrinterId, 
    "title" : docTitle,
    "content"  : docId, 
    "contentType" : "google.kix",
  };

  var accessToken = googleOAuth_('google', scope).getAccessToken();

  var params = {
    method:"POST",
    headers: {"Authorization": "Bearer " + accessToken},
    muteHttpExceptions:true,
    payload:payloadOfSubmit
  };

  var responseOfSubmit = UrlFetchApp.fetch(url, params);
  //Logger.log(responseOfSubmit);
  var jsonOfSubmit = JSON.parse(responseOfSubmit.getContentText()); 

  return jsonOfSubmit;
}

function googleOAuth2_(name, scope) {

  return OAuth2.createService(name)
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setClientId("anonymous")
    .setClientSecret("anonymous")
    .setProjectKey(ScriptApp.getProjectKey())
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope(scope)
    .setCallbackFunction('authCallback');
}

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

但是当它尝试运行该行时,这会给我一个错误“访问未授予或过期”:

var accessToken = googleOAuth_('google', scope).getAccessToken();

所以我找到了一个apps ScriptApp Method getOAuthToken,它似乎可以给我我需要的令牌。我将上面的行替换为:

var accessToken = ScriptApp.getOAuthToken();

并且代码执行,但我从服务器得到的响应是“需要错误 403 用户凭据”。

根据@Mogsdad 的建议,这是我的第三次尝试:

function sendPrintJob(docId,myPrinterId,docTitle) {

  var payloadOfSubmit = {
            "printerid" : myPrinterId, 
            "title" : docTitle,
            "content"  : docId, 
            "contentType" : "google.kix" ,
  };

  var request = {
    "method": "POST",
    "headers":{"Authorization": "Bearer "+ScriptApp.getOAuthToken()},    
    "muteHttpExceptions": true
  };

  var responseOfSubmit = UrlFetchApp.fetch("https://www.google.com/cloudprint/submit", request);
  Logger.log(responseOfSubmit);
}

我尝试了多种变体,包括创建开发者控制台项目并使用那里提供的客户端 ID,但我一直卡在这两个问题上(未授予访问权限或需要凭据)。如果有人能提供任何帮助,我将不胜感激。

【问题讨论】:

  • 建议:改用ScriptApp.getOAuthToken()this answer 中的说明。
  • 感谢您的回复@Mogsdad。我尝试了您的建议,但仍然收到错误 403:需要用户凭据。我查看了您引用的链接中的 cmets,有人指出“因为您使用的是 DriveApp,您的脚本已经有权从包括 UrlFetchApp 在内的任何来源访问您的文件”。是否有可能该脚本未获得访问 Google 云打印的授权(如果是,我不确定如何解决此问题)?

标签: google-apps-script oauth-2.0 google-cloud-print google-oauth


【解决方案1】:

以下是允许我将 Google Apps 脚本连接到 Google Cloud Print 的步骤,这样我就可以提交 GCP 作业(这些步骤都是从 Google Apps 脚本中开始的):

  1. 添加 OAuth2 库 (https://github.com/googlesamples/apps-script-oauth2) 到你的谷歌 Apps 脚本通过转到:资源 > 库 > 查找库 MswhXl8fVhTFUH_Q3UOJbXvxhMjh3Sh48 > 选择
  2. 在 Developer Console Resources > Developer Console Project > 单击项目链接 > APIs & Auth > 创建新的 Web 应用程序 凭据 > 添加凭据 > OAuth2.0 客户端 ID > Web 应用程序 > 将授权重定向 URI 设置为格式
    https://script.google.com/macros/d/{PROJECT KEY}/usercallback 其中项目密钥位于文件>项目属性下并复制 您的客户端 ID 和客户端密码
  3. 将 ID 和 Secret 添加到下面的“getCloudPrintService()”代码中(替换 client_idclient_secret
  4. 转到运行 > ShowURL 并授权脚本。
  5. 打开 Logger(Cmd + Enter),复制 URL 并将其粘贴到新的浏览器选项卡中以完成授权。
  6. 转到https://www.google.com/cloudprint/#printers,选择您的打印机,点击详细信息,展开高级详细信息,然后复制您的Printer ID(格式为555aa555-5a55-5555-5555-55555a55a555
  7. 在下面的“printGoogleDocument()”代码中添加打印机ID(替换myPrinterId

此资源有助于找出步骤:http://ctrlq.org/code/20061-google-cloud-print-with-apps-script,您也可能会发现这些链接很有帮助:

function showURL() {
  var cpService = getCloudPrintService();
  if (!cpService.hasAccess()) {
    Logger.log(cpService.getAuthorizationUrl());
  } else {
    Logger.log("You already have access to this service.");
  }
}
 
function getCloudPrintService() {
  return OAuth2.createService('print')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setClientId(client_id)
    .setClientSecret(client_secret)
    .setCallbackFunction('authCallback')
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope('https://www.googleapis.com/auth/cloudprint')
    .setParam('login_hint', Session.getActiveUser().getEmail())
    .setParam('access_type', 'offline')
    .setParam('approval_prompt', 'force');
}
 
function authCallback(request) {
  var isAuthorized = getCloudPrintService().handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('You can now use Google Cloud Print from Apps Script.');
  } else {
    return HtmlService.createHtmlOutput('Cloud Print Error: Access Denied');
  }
}

function getPrinterList() {
  var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/search', {
    headers: {
      Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
    },
    muteHttpExceptions: true
  }).getContentText();
 
  var printers = JSON.parse(response).printers;
 
  for (var p in printers) {
    Logger.log("%s %s %s", printers[p].id, printers[p].name, printers[p].description);
  }
}

function printGoogleDocument(docId, docTitle) {  
  // For notes on ticket options see https://developers.google.com/cloud-print/docs/cdd?hl=en
  var ticket = {
    version: "1.0",
    print: {
      color: {
        type: "STANDARD_COLOR"
      },
      duplex: {
        type: "NO_DUPLEX"
      },
    }
  };
   
  var payload = {
    "printerid" : myPrinterId,
    "content"   : docId,
    "title"  : docTitle,
    "contentType" : "google.kix", // allows you to print google docs
    "ticket"    : JSON.stringify(ticket),
  };
 
  var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/submit', {
    method: "POST",
    payload: payload,
    headers: {
      Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
    },
    "muteHttpExceptions": true
  });
 
  // If successful, should show a job here: https://www.google.com/cloudprint/#jobs

  response = JSON.parse(response);
  if (response.success) {
    Logger.log("%s", response.message);
  } else {
    Logger.log("Error Code: %s %s", response.errorCode, response.message);
  }
  return response;
}

【讨论】:

    【解决方案2】:

    范围“https://www.googleapis.com/auth/cloudprint”必须是included explicitly manifest file

    appscript.json(查看 > 显示清单文件)

    {
      "timeZone": "Europe/Paris",
      "dependencies": {
      },
      "oauthScopes": [
        "https://www.googleapis.com/auth/documents",
        "https://www.googleapis.com/auth/drive",
        "https://www.googleapis.com/auth/script.container.ui",
        "https://www.googleapis.com/auth/script.external_request",
        "https://www.googleapis.com/auth/spreadsheets",
        "https://www.googleapis.com/auth/cloudprint"
      ],
      "exceptionLogging": "STACKDRIVER"
    }
    

    代码.gs

    function listPrinters() {
      var options = {
        headers: {
          authorization: 'OAuth ' + ScriptApp.getOAuthToken()
        }
      }
      var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/search', options);
      Logger.log(response);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 2012-04-12
      • 2012-01-26
      • 2011-12-14
      • 2011-12-12
      • 2015-01-30
      • 1970-01-01
      • 2013-09-02
      • 2013-06-27
      相关资源
      最近更新 更多