带有 Google 云打印的 OAuth2
OAuth2 with Google Cloud Print
我写了一个 Google Apps 脚本连接到 Google Cloud Print 来自动化一些打印。该脚本会按时间间隔自动 运行,搜索相关文件,如果找到,它会将它们发送到我的打印机。我的代码使用 OAuthConfig 并且运行良好,但现在 class 已被弃用,经过一个周末的反复试验和搜索互联网后,我 不能'它无法与 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');
}
}
但这给了我一个错误 "Access not granted or expired" 当它试图 运行 行:
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,但我一直被这两个问题所困(未授予访问权限,或需要凭据)。如果有人能提供任何帮助,我将不胜感激。
以下是允许我将 Google Apps 脚本连接到 Google Cloud Print 的步骤,这样我就可以提交 GCP 作业(这些步骤都是从 Google 中开始的应用程序脚本):
- 添加 OAuth2 库
(https://github.com/googlesamples/apps-script-oauth2) 给你的 Google
Apps 脚本,方法是转到:资源 > 库 > 查找库
MswhXl8fVhTFUH_Q3UOJbXvxhMjh3Sh48
> Select
- 在 Developer Console Resources > Developer Console Project > 单击项目 link > APIs & Auth > 创建新的 Web 应用程序
凭据 > 添加凭据 > OAuth2.0 客户端 ID > Web
Application > Set Authorized redirect URIs to the format
https://script.google.com/macros/d/{PROJECT KEY}/usercallback
项目密钥位于文件 > 项目属性下并复制
您的客户端 ID 和客户端密码
- 将 ID 和 Secret 添加到下面的 "getCloudPrintService()" 代码中(替换
client_id
和 client_secret
)
- 转到 运行 > 显示URL 并授权脚本。
- 打开记录器(Cmd + Enter),复制URL并粘贴到新的浏览器选项卡中以完成授权。
- 转到 https://www.google.com/cloudprint/#printers,select 您的打印机,单击详细信息,展开高级详细信息,然后复制您的
Printer ID
(格式为 555aa555-5a55-5555-5555-55555a55a555
)
- 将打印机 ID 添加到下面的 "printGoogleDocument()" 代码中(替换
myPrinterId
)
此资源有助于确定步骤:http://ctrlq.org/code/20061-google-cloud-print-with-apps-script,您可能还会发现这些 link 有帮助:
- https://developers.google.com/cloud-print/docs/appInterfaces
- https://mashe.hawksey.info/2015/10/setting-up-oauth2-access-with-google-apps-script-blogger-api-example/
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;
}
范围“https://www.googleapis.com/auth/cloudprint" has to be 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);
}
我写了一个 Google Apps 脚本连接到 Google Cloud Print 来自动化一些打印。该脚本会按时间间隔自动 运行,搜索相关文件,如果找到,它会将它们发送到我的打印机。我的代码使用 OAuthConfig 并且运行良好,但现在 class 已被弃用,经过一个周末的反复试验和搜索互联网后,我 不能'它无法与 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');
}
}
但这给了我一个错误 "Access not granted or expired" 当它试图 运行 行:
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,但我一直被这两个问题所困(未授予访问权限,或需要凭据)。如果有人能提供任何帮助,我将不胜感激。
以下是允许我将 Google Apps 脚本连接到 Google Cloud Print 的步骤,这样我就可以提交 GCP 作业(这些步骤都是从 Google 中开始的应用程序脚本):
- 添加 OAuth2 库
(https://github.com/googlesamples/apps-script-oauth2) 给你的 Google
Apps 脚本,方法是转到:资源 > 库 > 查找库
MswhXl8fVhTFUH_Q3UOJbXvxhMjh3Sh48
> Select - 在 Developer Console Resources > Developer Console Project > 单击项目 link > APIs & Auth > 创建新的 Web 应用程序
凭据 > 添加凭据 > OAuth2.0 客户端 ID > Web
Application > Set Authorized redirect URIs to the format
https://script.google.com/macros/d/{PROJECT KEY}/usercallback
项目密钥位于文件 > 项目属性下并复制 您的客户端 ID 和客户端密码 - 将 ID 和 Secret 添加到下面的 "getCloudPrintService()" 代码中(替换
client_id
和client_secret
) - 转到 运行 > 显示URL 并授权脚本。
- 打开记录器(Cmd + Enter),复制URL并粘贴到新的浏览器选项卡中以完成授权。
- 转到 https://www.google.com/cloudprint/#printers,select 您的打印机,单击详细信息,展开高级详细信息,然后复制您的
Printer ID
(格式为555aa555-5a55-5555-5555-55555a55a555
) - 将打印机 ID 添加到下面的 "printGoogleDocument()" 代码中(替换
myPrinterId
)
此资源有助于确定步骤:http://ctrlq.org/code/20061-google-cloud-print-with-apps-script,您可能还会发现这些 link 有帮助:
- https://developers.google.com/cloud-print/docs/appInterfaces
- https://mashe.hawksey.info/2015/10/setting-up-oauth2-access-with-google-apps-script-blogger-api-example/
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;
}
范围“https://www.googleapis.com/auth/cloudprint" has to be 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);
}