如何在Ruby中为Google Calendar API授权服务账号?代码报错
解决Ruby中Google Calendar API服务账号授权的
Expected top level property 'installed' or 'web'错误 你遇到的问题根源很明确:官方的quickstart.rb是为OAuth2用户授权流程设计的,它期望的是带有installed或web字段的OAuth客户端凭证,但你用的是服务账号的JSON凭证,这两者的结构完全不同,所以才会抛出这个RuntimeError。
接下来直接给你服务账号的Ruby实现方案:
服务账号授权的完整Ruby代码
替换原来的quickstart.rb,使用以下代码:
require 'google/apis/calendar_v3' require 'googleauth' # 配置参数 SERVICE_ACCOUNT_KEY_PATH = 'service_account_key.json' # 你的服务账号JSON文件路径 SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY APPLICATION_NAME = 'Google Calendar API Service Account Quickstart' def authorize # 从服务账号JSON文件加载凭证 credentials = Google::Auth::ServiceAccountCredentials.make_creds( json_key_io: File.open(SERVICE_ACCOUNT_KEY_PATH), scope: SCOPE ) # 可选:如果是G Suite/Workspace账户,可模拟域内用户访问其日历 # credentials.sub = 'target-user@your-domain.com' credentials end # 初始化API服务 service = Google::Apis::CalendarV3::CalendarService.new service.client_options.application_name = APPLICATION_NAME service.authorization = authorize # 获取日历事件(替换为你要访问的日历ID,比如共享给服务账号的日历ID) calendar_id = 'primary' # 若模拟G Suite用户,primary对应该用户的主日历;否则用共享日历ID response = service.list_events( calendar_id, max_results: 10, single_events: true, order_by: 'startTime', time_min: Time.now.iso8601 ) puts "Upcoming events:" if response.items.empty? puts "No upcoming events found" else response.items.each do |event| start = event.start.date || event.start.date_time puts "- #{event.summary} (#{start})" end end
关键注意事项
- 凭证文件:确保使用的是服务账号的JSON文件(下载时为
*.json,包含type: "service_account"字段),而非OAuth客户端的client_secrets.json。 - API启用:在Google Cloud控制台中确认已启用Google Calendar API。
- 日历共享:若要访问非服务账号自身的日历(比如个人Gmail日历),必须将该日历共享给服务账号的邮箱(可在服务账号JSON的
client_email字段找到),并赋予对应权限(如查看权限)。 - G Suite域范围授权(可选):如果使用G Suite/Workspace账户,可通过设置
credentials.sub模拟域内用户,这需要在Google Admin控制台中为服务账号启用域范围授权权限。
原代码失效的原因
原代码中的Google::Auth::ClientId.from_file方法专门处理OAuth2用户授权的凭证(installed/web类型),而服务账号的凭证需要用Google::Auth::ServiceAccountCredentials.make_creds加载——这是两种完全不同的授权流程:
- OAuth2用户授权:需要用户手动授权,适合访问用户个人日历
- 服务账号授权:无需用户交互,适合服务器端自动化任务,需提前配置共享或域范围授权
内容的提问来源于stack exchange,提问作者Chloe
相关产品推荐
相关产品推荐

