Google apps script 公共谷歌脚本不';不要从chrome扩展运行

Google apps script 公共谷歌脚本不';不要从chrome扩展运行,google-apps-script,google-chrome-extension,Google Apps Script,Google Chrome Extension,我有一个修改谷歌电子表格内容的谷歌脚本(当然不是最终的脚本),但是我在从谷歌浏览器扩展运行这个简单脚本时遇到了一个问题。 以下是附加到我的电子表格的脚本: function insertData(parameters) { var spreadsheet = SpreadsheetApp.openByUrl(THE_URL_OF_THE_SPREADSHEET) spreadsheet.getRange('A5').activate(); spreadsheet.getCurrent

我有一个修改谷歌电子表格内容的谷歌脚本(当然不是最终的脚本),但是我在从谷歌浏览器扩展运行这个简单脚本时遇到了一个问题。 以下是附加到我的电子表格的脚本:

function insertData(parameters) {
  var spreadsheet = SpreadsheetApp.openByUrl(THE_URL_OF_THE_SPREADSHEET)
  spreadsheet.getRange('A5').activate();
  spreadsheet.getCurrentCell().setValue(parameters.data1);
  spreadsheet.getRange('B5').activate();
  spreadsheet.getCurrentCell().setValue(parameters.data2);
}
我将此脚本部署为web应用程序(以我的身份执行+访问所有人,甚至匿名)和可执行API(访问任何人)

然后我尝试了这个JS脚本来运行我的google脚本,来自google chrome扩展,使用了我从google chrome扩展示例中获得的代码:

sendDataToExecutionAPICallback: function() {
    post({  'url': 'https://script.googleapis.com/v1/scripts/' + SCRIPT_ID + ':run',
            'callback': obj.executionAPIResponse,
            'token': 'MY_GENERATED_TOKEN'
            'request': {
                'function': 'insertData',
                'parameters': {                 
                    'data1': 'ok1 from script',
                    'data2': 'ok2 from script'
                },
                'devMode': true
            }
        });
}, 

executionAPIResponse: function(response){
    var obj = this;
    var info;
    if (response.response.result.status == 'ok'){
        info = 'Data has been entered';
    } else {
        info = 'Error...';
    }
    obj.displayMessage(info);
}
我有一个post功能:

function post(options) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            // JSON response assumed. Other APIs may have different responses.
            options.callback(JSON.parse(xhr.responseText));
        } else if(xhr.readyState === 4 && xhr.status !== 200) {
            console.log('post', xhr.readyState, xhr.status, xhr.responseText);
        }
    };
    xhr.open('POST', options.url, true);
    // Set standard Google APIs authentication header.
    xhr.setRequestHeader('Authorization', 'Bearer ' + options.token);
    xhr.send(JSON.stringify(options.request));
}
当我调用
sendDataToExecutionAPICallback
函数时,我得到了以下身份验证错误:

"error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
}
EDIT1: 生成令牌并将其添加到代码后,出现以下错误:

 "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }

我想提出两种方法。请选择其中一个

方法1: 为了使用执行API运行函数,请执行以下流程

  • 创建项目(独立或绑定脚本)
  • 将GAS脚本复制并粘贴到项目中。在本例中,您的GAS脚本未被修改
  • 作为示例,选择“只有我自己”作为“谁有权访问脚本”
  • 在API控制台启用应用程序脚本API
  • 使用“保存”按钮,在脚本编辑器上保存项目。这是很重要的一点。这样,脚本就会反映到部署的执行API中
  • 从该项目的客户端ID和客户端机密中检索访问令牌。
    • 请包括
      https://www.googleapis.com/auth/drive
      https://www.googleapis.com/auth/drive.scripts
      https://www.googleapis.com/auth/spreadsheets
      在作用域中<代码>https://www.googleapis.com/auth/drive可能不用于这种情况
  • 请将检索到的访问令牌用于以下修改的脚本

    Javascript: 注:
    • 在我的环境中,这个修改过的脚本可以工作。但是如果在您的环境中,这不起作用,请尝试方法2好吗
    方法2:网络应用 根据您的问题和评论,我担心访问令牌可能无法使用。因此,我还想提出使用Web应用程序的方法。在这种情况下,您可以在不使用访问令牌的情况下运行函数。但是要运行的密码密钥用于有效负载

    使用此应用程序时,请将Web应用程序部署为
    ”,将应用程序执行为:“:Me
    ”谁有权访问该应用程序:“:任何人,即使是匿名的
    ”。如果您想了解Web应用的详细信息,请查看

    在这个示例脚本中,它不使用
    xhr.setRequestHeader('Authorization'、'Bearer'+options.token)
    post()

    修改后的脚本如下所示。请向部署Web应用程序的脚本编辑器添加GAS

    气体: Javascript: 注:
    • 如果使用Web应用程序,请在将GAS脚本复制并粘贴到脚本编辑器后,将Web应用程序重新部署为新版本。由此,最新的脚本得到了反映

    在我的环境中,我可以确认这两种方法都有效。

    From:此方法需要使用OAuth 2.0令牌进行授权,该令牌至少包括授权部分中列出的一个作用域;不需要授权的脚本项目无法通过此API执行。谢谢!我生成了一个令牌并修改了代码(我在上面对其进行了编辑),但现在出现了另一个错误(错误403:调用方没有权限)。请确保您已使用脚本文件中使用的所有作用域生成了令牌(您可以在“文件”>“项目属性”的“作用域”选项卡中查看所有作用域)如果您打算将设置保留为:
    访问所有人,即使是匿名的
    ,那么使用OAuth是没有意义的,它不是必需的。我可以理解您想要在GAS中运行
    insertData()
    。但您正在部署Web应用程序和可执行API。您当前的脚本似乎使用了可执行API。我能问一下你想用什么方法吗?通过这个,我认为您的脚本可以修改。谢谢Tanaike,第二种方法确实有效,但是有一个GET请求(我在帖子中有一个跨域错误,但是因为它与GET一起工作,所以我没有进一步检查)。谢谢你@朱利安·勒卡尔维兹感谢您提供的更多信息。我很高兴你的问题解决了。我还将在将来测试其他方法。当我得到它的时候,我想在这里求婚
    sendDataToExecutionAPICallback: function() {
      post({
        'url': 'https://script.googleapis.com/v1/scripts/' + SCRIPT_ID + ':run',
        'callback': obj.executionAPIResponse,
        'token': 'MY_GENERATED_TOKEN',
        'request': {
          'function': 'insertData',
          'parameters': [{
            'data1': 'ok1 from script',
            'data2': 'ok2 from script',
          }],
          'devMode': true,
        }
      });
    },
    
    executionAPIResponse: function(response) {
      var info;
      if (!response.error) {
        info = 'Data has been entered';
      } else {
        info = 'Error...';
      }
      obj.displayMessage(info);
    },
    
    function post(options) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          // JSON response assumed. Other APIs may have different responses.
          options.callback(JSON.parse(xhr.responseText));
        } else if(xhr.readyState === 4 && xhr.status !== 200) {
          console.log('post', xhr.readyState, xhr.status, xhr.responseText);
        }
      };
      xhr.open('POST', options.url, true);
      // Set standard Google APIs authentication header.
      xhr.setRequestHeader('Authorization', 'Bearer ' + options.token);
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.send(JSON.stringify(options.request));
    }
    
    function doPost(e) {
      var p = JSON.parse(e.postData.contents);
      if (p.password == 'samplePassword') {
        insertData(p.parameters);
        return ContentService.createTextOutput("ok");
      } else {
        return ContentService.createTextOutput("error");
      }
    }
    
    function insertData(parameters) {
      var spreadsheet = SpreadsheetApp.openByUrl(THE_URL_OF_THE_SPREADSHEET);
      spreadsheet.getRange('A5').activate();
      spreadsheet.getCurrentCell().setValue(parameters.data1);
      spreadsheet.getRange('B5').activate();
      spreadsheet.getCurrentCell().setValue(parameters.data2);
    }
    
    sendDataToExecutionAPICallback: function() {
      post({
        'url': 'https://script.google.com/macros/s/#####/exec', // URL of Web Apps
        'callback': obj.executionAPIResponse,
        'request': {
          'parameters': {
            'data1': 'ok1 from script',
            'data2': 'ok2 from script'
          },
          'password': 'samplePassword',
        }
      });
    }, 
    executionAPIResponse: function(response) {
      var info;
      if (response == 'ok') {
        info = 'Data has been entered';
      } else {
        info = 'Error...';
      }
      obj.displayMessage(info);
    },
    
    function post(options) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          // JSON response assumed. Other APIs may have different responses.
          options.callback(xhr.responseText);
        } else if(xhr.readyState === 4 && xhr.status !== 200) {
          console.log('post', xhr.readyState, xhr.status, xhr.responseText);
        }
      };
      xhr.open('POST', options.url, true);
      // Set standard Google APIs authentication header.
      xhr.send(JSON.stringify(options.request));
    }