OAuth2与Google云打印

时间:2015-06-01 04:15:32

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

我编写了一个与Google Cloud Print相关联的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
  }; 
}  

我已成功连接github library 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();

所以我发现了一个应用程序ScriptApp方法getOAuthToken,它似乎可能会给我我需要的令牌。我用以下内容替换了上面一行:

var accessToken = ScriptApp.getOAuthToken();

代码执行但我的服务器响应是“Error 403 User credentials required”。

这是我根据@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,但我一直陷入这两个问题(未授予访问权限或需要凭据)。如果有人能提供任何帮助,我会非常感激。

2 个答案:

答案 0 :(得分:1)

以下是允许我将Google Apps脚本连接到Google云打印的步骤,因此我可以提交GCP作业(这些步骤都是从Google Apps脚本中启动的):

  1. 添加OAuth2库 (https://github.com/googlesamples/apps-script-oauth2)到您的Google 应用脚本转到:资源>图书馆>查找图书馆 MswhXl8fVhTFUH_Q3UOJbXvxhMjh3Sh48>选择
  2. 在开发者控制台资源中创建新的Web应用程序>开发者控制台项目>点击项目链接> API& Auth> 证书>添加凭据> OAuth2.0客户端ID>卷筒纸 申请>将授权重定向URI设置为格式
    https://script.google.com/macros/d/{PROJECT KEY}/usercallback 其中项目密钥位于文件>项目属性和副本 您的客户ID和客户端密码
  3. 将ID和密码添加到下面的“getCloudPrintService()”代码中(替换client_idclient_secret
  4. 转到“运行”> ShowURL并授权脚本。
  5. 打开记录器(Cmd + Enter),复制URL并将其粘贴到新的浏览器选项卡中以完成授权。
  6. 转到https://www.google.com/cloudprint/#printers,选择您的打印机,点击详细信息,展开高级详细信息,然后复制Printer ID(格式为555aa555-5a55-5555-5555-55555a55a555
  7. 将打印机ID添加到下面的“printGoogleDocument()”代码中(替换myPrinterId
  8. 此资源有助于确定步骤: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;
    }

答案 1 :(得分:0)

范围“ 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"
}

Code.gs

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