PHP复制带AppScript的Google Docs时脚本无法运行的问题求助
问题:服务账号复制Google Docs后,附带的AppScript无法运行且菜单不显示
场景复现
通过PHP代码使用服务账号复制Google Docs,代码如下:
$documentId = 'ID'; $googleAccountKeyFilePath = __DIR__ . '/service_key.json'; putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $googleAccountKeyFilePath); $client = new \Google_Client(); $client->setApplicationName('Some name'); $client->setScopes([\Google_Service_Docs::DOCUMENTS, \Google_Service_Drive::DRIVE]); $client->setAccessType('offline'); $client->setAuthConfig($googleAccountKeyFilePath); $driveService = new \Google_Service_Drive($client); $originalDocument = $driveService->files->get($documentId); $copyDocument = new \Google_Service_Drive_DriveFile(array('name' => $_GET['domain'].' Title: ' . $_GET['date_start'].' - '.$_GET['date_end'])); $newDocument = $driveService->files->copy($documentId, $copyDocument); //copying document $newDocumentId = $newDocument->getId(); $driveService->permissions->create($newDocumentId, new \Google_Service_Drive_Permission(array('type' => 'anyone', 'role' => 'writer')));
复制后的文档成功创建,且包含原文档的AppScript代码:
function onOpen() { const ui = DocumentApp.getUi(); ui.createMenu('Addition') .addItem('findSynonyms', 'findSynonyms') .addToUi(); }
出现的问题
- 文档打开后,自定义菜单
Addition未显示 - 手动运行脚本时,报错:
Error
The script cannot be run because it is owned by a service account. Please copy or transfer the project to a valid account before running.
附appsscript.json配置
{ "timeZone": "Europe/Kiev", "dependencies": { "enabledAdvancedServices": [{ "userSymbol": "Docs", "serviceId": "docs", "version": "v1" }, { "userSymbol": "Drive", "serviceId": "drive", "version": "v3" }] }, "webapp": { "access": "DOMAIN", "executeAs": "USER_ACCESSING" }, "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8" }
解决方法及原因说明
核心原因
服务账号是无界面的机器账号,不属于普通消费者或Google Workspace用户账号范畴,无法拥有或运行AppScript项目。用服务账号复制带脚本的文档时,脚本项目的所有权会被转移给服务账号,导致普通用户无法访问、触发或运行该脚本。
具体解决方案
有三种可行路径:
方案1:复制文档后转移脚本项目所有权
- 复制文档完成后,先找到复制后文档关联的脚本项目ID(可通过Docs API查询,或直接在文档的脚本编辑器地址栏获取)。
- 调用Drive API的
permissions.create方法,将脚本项目的所有权转移到一个有效的用户账号(个人Google账号或Workspace账号),需设置参数transferOwnership: true。 - 转移完成后,普通用户打开文档时,
onOpen触发器会正常执行,自定义菜单也会显示。
方案2:改用用户OAuth授权模式复制文档
放弃服务账号,改用OAuth 2.0授权码模式,让真实用户授权应用访问其Drive资源。用授权后的用户身份复制文档,复制后的脚本项目所有权会属于该授权用户,脚本可正常运行,菜单也能正常显示。
方案3:将脚本部署为独立Web应用
- 将原文档中的脚本单独部署为Web应用,设置访问权限为符合需求的范围(比如“任何人,甚至匿名”),执行身份选择“以我自己的身份运行”。
- 在复制后的文档中,插入自定义菜单,通过菜单调用该Web应用的接口实现功能,不再依赖文档绑定的脚本。
额外注意事项
- 服务账号无法触发AppScript的简单触发器(如
onOpen、onEdit),这类触发器必须由真实用户操作触发。 - 即使将服务账号加入Google Workspace域并赋予权限,也无法解决脚本所有权的核心问题,仍需转移所有权才能让普通用户正常使用脚本。
内容的提问来源于stack exchange,提问作者theblackpost
相关产品推荐
相关产品推荐

