Webman需通过Google Sheets API实现导出,必须由服务端用OAuth2或服务账号完成授权,前端JS直连因安全限制不可行;服务账号方式最适配,需下载JSON密钥、共享邮箱为编辑者、用Google_Client写入数据。

Webman 本身不提供直接导出到 Google Sheets 的能力,必须通过 Google Sheets API 实现。这不是“装个包就能调用”的事,而是涉及 OAuth2 授权、服务端凭据管理、HTTP 请求构造和错误重试——稍有疏忽就会卡在 401 Unauthorized 或 403 Permission denied。
为什么不能用前端 JS 直连 Google Sheets API
Google Sheets API 要求 bearer token,而该 token 必须由服务端用私钥或 OAuth2 refresh token 换取。前端无法安全持有私钥,也无法完成 OAuth2 授权码流程(缺少后端回调 endpoint)。若强行让前端发起请求,会暴露 client_secret 或私钥,属于严重安全漏洞。
常见错误现象:Failed to fetch、net::ERR_BLOCKED_BY_CLIENT、浏览器控制台报 Invalid Credentials ——本质是跨域 + 凭据缺失双重拦截。
- 必须由 Webman 控制器发起 HTTP 请求,用
guzzlehttp/guzzle或curl调用 Google API - OAuth2 流程只能走服务端授权码模式(
authorization_code),不能用前端隐式流(implicit) - 若用服务账号(Service Account),需提前在 Google Cloud Console 开启 Google Sheets API,并将服务账号邮箱以“编辑者”身份共享给目标表格
如何用服务账号(Service Account)实现静默写入
这是最适配 Webman 常驻进程模型的方式:无需用户交互、无 token 过期烦恼、可预授权、适合后台任务。
关键步骤:
- 在 Google Cloud Console 创建服务账号,下载 JSON 私钥文件(如
service-account-key.json),存到 Webman 项目config/目录下 - 打开目标 Google Sheet,点击右上角「共享」→ 输入服务账号邮箱(形如
xxx@your-project.iam.gserviceaccount.com)→ 设为“编辑者” - 安装依赖:
composer require google/apiclient - 在控制器中加载凭证并写入:
$client = new \Google_Client();
$client->setAuthConfig(__DIR__ . '/../config/service-account-key.json');
$client->addScope([\Google_Service_Sheets::SPREADSHEETS]);
$service = new \Google_Service_Sheets($client);
$values = [
['姓名', '年龄', '城市'],
['张三', 25, '北京'],
['李四', 30, '上海']
];
$body = new \Google_Service_Sheets_ValueRange(['values' => $values]);
$params = [
'valueInputOption' => 'RAW'
];
$service->spreadsheets_values->update(
'YOUR_SPREADSHEET_ID',
'Sheet1!A1',
$body,
$params
);
注意:YOUR_SPREADSHEET_ID 是 URL 中 /d/{id}/edit 那段,不是文件名;Sheet1!A1 是目标范围,支持 A1:C10 或 数据!B2:E100 等写法。
如何避免 Webman 协程阻塞导致写入失败
Google API 请求默认是同步阻塞的,若用 go(function () { ... }) 包裹但没处理好连接池或超时,容易触发 Swoole 的协程调度异常,表现为请求发出去但无响应、或 curl_exec 卡死。
实操建议:
- 禁用 Guzzle 的异步 Promise(它和 Swoole 协程不兼容),改用同步 client + 显式 timeout
- 设置合理超时:
$client->setHttpClient(new \GuzzleHttp\Client(['timeout' => 30])) - 不要在单次 HTTP 请求里写入超过 1 万行;拆成多批次,每批最多 5000 行,用
append模式替代update可避免覆盖风险 - 若写入量极大(如日志归档),应扔进 Worker 进程异步执行,避免阻塞 HTTP worker
真正上线时最容易被忽略的点:服务账号权限只对明确共享的表格生效,新建表格不会自动继承;每次换表都得手动共享一次邮箱。别指望“整个 Google Drive 文件夹授权”——Google Sheets API 不认这个。


















