使用apps-script-oauth2库时handleCallback函数报code未定义错误
问题描述
调用authCallback函数时遇到以下错误:
TypeError: Cannot read properties of undefined (reading 'code')
at Service_.handleCallback(Service:440:40)
at authCallback(Auth:69:39)
日志显示请求中存在code参数,但报错提示无法读取该参数。相关代码如下(错误发生在handleCallback调用处):
function doGet(e) { return initiateAuthorization(); // Or any other function you want to run when the web app is accessed directly } function getAdobeSignService_() { // 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('adobeSign') // Set the endpoint URLs .setAuthorizationBaseUrl('https://secure.na4.adobesign.com/public/oauth/v2') .setTokenUrl('https://secure.na4.adobesign.com/public/oauth/v2/token') // Set the client ID and secret .setClientId('..') .setClientSecret('..') // 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 .setScope('agreement_send') // Requests offline access. .setParam('access_type', 'offline') // Consent prompt is required to ensure a refresh token is always // returned when requesting offline access. .setParam('prompt', 'consent'); } function initiateAuthorization() { var adobeSignService = getAdobeSignService_(); console.log("done getting adobe sign service"); var userProperties = PropertiesService.getUserProperties(); if (!adobeSignService.hasAccess()) { var authorizationUrl = adobeSignService.getAuthorizationUrl(); var template = HtmlService.createTemplate( '<a href="<?= authorizationUrl?>" target="_blank">Authorize</a>. ' + 'Reopen the sidebar when the authorization is complete.'); template.authorizationUrl = authorizationUrl; var page = template.evaluate(); return page; // Return the HTML output directly. No SpreadsheetApp.getUi() here. } else { var justAuthorized = userProperties.getProperty('adobeSignAuthorized'); if (justAuthorized === 'true') { userProperties.deleteProperty('adobeSignAuthorized'); } getAgreements(function(agreements){ updateSheetWithAgreements(agreements); }); return HtmlService.createHtmlOutput("Authorization Complete. Data will be updated."); } } function authCallback(request) { var adobeSignService = getAdobeSignService_(); var jsonRequest = JSON.stringify(request) var isAuthorized = adobeSignService.handleCallback(jsonRequest); if (isAuthorized) { return HtmlService.createHtmlOutput('Success! You can close this tab.'); } else { return HtmlService.createHtmlOutput('Denied. You can close this tab'); } } function getAgreements() { // Example: Function to get agreements var adobeSignService = getAdobeSignService(); var accessToken = adobeSignService.getAccessToken(); // Construct the Adobe Sign API request URL (Example) var apiUrl = 'https://api.na1.echosign.com/api/rest/v6/agreements'; try { var response = UrlFetchApp.fetch(apiUrl, { method: 'get', // Or post, put, delete as needed headers: { 'Authorization': 'Bearer ' + accessToken, 'Accept': 'application/json' // Important: specify JSON }, muteHttpExceptions: true // Handle potential errors gracefully }); var data = JSON.parse(response.getContentText()); Logger.log(data); // Log the response data (for debugging) // Process the data as needed (e.g., display in spreadsheet) // Example: Loop through the agreements and log their IDs if (data && data.hasOwnProperty("agreementList")) { data.agreementList.forEach(function(agreement) { Logger.log("Agreement ID: " + agreement.agreementId); }); } else { Logger.log("No agreements found or unexpected response format."); Logger.log(response); // Log the full response for debugging } } catch (error) { Logger.log("Error making API request: " + error); Logger.log(response); // Log the full response for debugging // Handle the error (e.g., display an error message in the sidebar) } }
打印的jsonRequest值如下:
{parameter={redir=, code=**value**, state=**value**, serviceName=adobeSign, authuser=0}, contextPath=, parameters={authuser=[0], serviceName=adobeSign, code=[**value**], state=[**value**], redir=[]}, contentLength=-1.0, queryString=code=**value**&state=**value**&authuser=0&redir}
请问jsonRequest的值是否存在问题?
解决方案
问题出在authCallback函数的参数传递上:你把request对象转成了JSON字符串传给handleCallback,但OAuth2库的handleCallback方法需要接收原始的request对象,而非字符串化后的JSON。
当传入字符串时,库内部尝试读取jsonRequest.code,但字符串本身没有code属性,因此抛出"Cannot read properties of undefined (reading 'code')"的错误。你的jsonRequest内容本身是正常的,包含了code参数,只是传递方式错误导致库无法正确解析。
修改后的authCallback函数如下:
function authCallback(request) { var adobeSignService = getAdobeSignService_(); // 移除JSON.stringify,直接传递原始request对象 var isAuthorized = adobeSignService.handleCallback(request); if (isAuthorized) { return HtmlService.createHtmlOutput('Success! You can close this tab.'); } else { return HtmlService.createHtmlOutput('Denied. You can close this tab'); } }
内容的提问来源于stack exchange,提问作者Katrina Trial
相关产品推荐
相关产品推荐

