API suddently started throwing Error: Access not granted or expired. Service_.getAccessToken Service.gs:466 error

API suddently started throwing Error: Access not granted or expired. Service_.getAccessToken Service.gs:466 error

我目前正在 运行 Google 脚本上的一些脚本来调用 Salesforce REST API 并将数据下载到 Google 表格中。

我正在使用 Google 表格库 ID 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF,这是可以在 github here.

上找到的 OAuth2 库

然后,我按照指示使用以下调用通过以下代码实际验证 Salesforce API:

var CLIENT_ID = {I get this from the connected SalesForce app};
var CLIENT_SECRET = {I get this from the connected SalesForce app};

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('salesforce')
      // Set the endpoint URLs
      .setAuthorizationBaseUrl('https://flolive.my.salesforce.com/services/oauth2/authorize')
      .setTokenUrl('https://flolive.my.salesforce.com/services/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.getDocumentProperties())
       // .setCache(CacheService.getDocumentCache())
      // Set the scopes to request (space-separated for Google services).
    
     // .setScope('r_organization_social,r_basicprofile,r_liteprofile,rw_organization_admin,r_ads_reporting,r_ads')

      // Below are salesforce-specific OAuth2 parameters.

        .setParam('response_type', 'code')
      
      // 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 salesforceService = getService();
  var isAuthorized = salesforceService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');
  }
}

function logOut() {
  PropertiesService.getDocumentProperties().deleteAllProperties();
  PropertiesService.getUserProperties().deleteAllProperties();
  var service=getService();
    service.reset();

}
function salesforceAPI() {
  var service = getService();
  if (service.hasAccess()) {
    //exchange authorisation code for access token
    
    // sheet.getSheetByName('Settings').getRange(3,2).setValue(getService().getAccessToken());

    var tokenURL = 'https://flolive.my.salesforce.com/services/oauth2/token';

    var parameters = 'grant_type=authorization_code&code='+getService().getAccessToken()+'&redirect_uri='+getService().redirect_uri+'&client_id='+CLIENT_ID+'&client_secret='+CLIENT_SECRET;

 var options = {
   'method': 'POST',
   'contentType': 'application/x-www-form-urlencoded',
  'muteHttpExceptions': true,    
   'payload': parameters
  }

  var response = UrlFetchApp.fetch(tokenURL,options);
  var json = JSON.parse(response.getContentText());

  console.log(json);

    //sheet.getSheetByName('Settings').getRange(3,3).setValue(json.items);
  return json;

    
  } else {
    var authorizationUrl = service.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();
    SpreadsheetApp.getUi().showModalDialog(page,'Authorise salesforce');

    Logger.log(getService().getAccessToken());
  }
}

现在我对此没有问题。我打的所有电话都有效。我在连接的应用程序中检查了回调url,一切正常。

当我尝试将一些数据输出到不同的工作表时,一切都停止了。

所以现在我有 2 个工作表。

SF API 后端 - 这是我放置 API 所有设置和参考的地方 记录的会议 - 这是我输出我试图提取的数据的地方,这些数据是活动。

起初一切正常,我可以正常输出。但是,当我添加 API 后端工作表时,起初它不起作用。我没有收到任何错误,也没有收到任何数据。

我以为是因为它需要一个不同的回调url,所以我添加了它。然后,出于某种原因,我使用了上面提到的 logOut() 函数来尝试重置连接。 那是我开始收到此错误的时候 错误:访问未被授予或已过期。 Service_.getAccessToken@Service.gs:466.

我上网查了下,觉得跟PropertyService有关系。所以我删除了所有 PropertyService 键。我什至将 getService() 函数从 .setPropertyStore(PropertiesService.getDocumentProperties()) 切换到 .setCache(CacheService.getDocumentCache())(现在已被注释掉)。

还是一样的错误。

然后我进入 Salesforce 并获得一个设置的访问令牌并用它替换 +getService().getAccessToken()

我收到此错误 TypeError: 无法读取未定义的 属性 'setClientId' 在 getService(SalesForceAuthentication:15:7) 在 salesforceAPI(SalesForceAuthentication:56:17)

我不确定为什么会出现该错误,因为我更改的代码甚至不在该函数中。

这就是我目前所在的位置。

我没有看到任何被列入黑名单的内容或任何会混淆或阻止它的设置。

我什至尝试重建整个东西,然后将代码(仅代码)复制到不同的脚本。我得到了同样的错误 错误:访问未被授予或已过期。 Service_.getAccessToken@Service.gs:466.

这让我认为客户端 Secret/Client Id 以某种方式被阻止。

问题:

当您使用getDocumentProperties()存储授权数据时:

Gets a property store (for this script only) that all users can access within the open document, spreadsheet, or form

如果您使用与存储数据的电子表格不同的电子表格,则数据不可用。

解决方案:

如果您希望它适用于多个电子表格,请改用 getScriptProperties() or getUserProperties(),它可以保留在多个文档上(仅当您使用相同的脚本时)。

.setPropertyStore(PropertiesService.getScriptProperties())