我一直在阅读Google Calendar API和google-api-ruby-client库的文档,但我在理解它们时遇到了很多麻烦。
我有一个Rails应用程序,它有一个前端,允许用户创建名为Events的对象,并将它们保存在我的服务器上的数据库中。我想要的是,在这些事件保存在数据库中之后,我想调用Google Calendar API在Google日历上创建一个事件(服务器创建了该事件,只有服务器才有权修改该日历)。
我有很多问题要弄清楚如何使用ruby库对API进行身份验证。使用OAuth2对我来说没有意义,因为我不需要向用户授权任何东西,因为我对他们的数据不感兴趣。我查看了服务帐户(http://code.google.com/p/google-api-ruby-client/wiki/ServiceAccounts),但服务帐户似乎不支持Google日历。
有人有什么想法吗?这是我正在尝试的代码(使用服务帐户):
@client = Google::APIClient.new(:key => 'my_api_key')
path_to_key_file = '/somepath/aaaaaa-privatekey.p12'
passphrase = 'my_pass_phrase'
key = Google::APIClient::PKCS12.load_key(path_to_key_file, passphrase)
asserter = Google::APIClient::JWTAsserter.new(
'blah_blah@developer.gserviceaccount.com',
'https://www.googleapis.com/auth/calendar',
key)
# To request an access token, call authorize:
@client.authorization = asserter.authorize()
calendar = @client.discovered_api('calendar', 'v3')
event = {
'summary' => 'Appointment',
'location' => 'Somewhere',
'start' => {
'dateTime' => '2012-06-03T10:00:00.000-07:00'
},
'end' => {
'dateTime' => '2012-06-03T10:25:00.000-07:00'
},
'attendees' => [
{
'email' => 'attendeeEmail'
},
#...
]
}
result = @client.execute!(:api_method => calendar.events.insert,
:parameters => {'calendarId' => 'primary'},
:body => JSON.dump(event),
:headers => {'Content-Type' => 'application/json'})
然后我收到此错误消息:Google :: APIClient :: ClientError(用户必须注册Google日历。)因为服务帐户不支持Google日历。
答案 0 :(得分:1)
我认为你仍然需要一个真正的谷歌用户来托管日历实例。但是,一旦您获得了以您的身份创建的日历,您就可以与服务帐户共享。在日历的共享设置中,只需使用服务帐户的电子邮件地址(我的服务帐户以@ developer.gserviceaccount.com结尾)。使用正确的共享权限,您的服务帐户可以创建/更改事件信息,而不会弄乱您的特定身份。从那里,您可以与更多人(或公共)共享日历,以便他们使用镜像事件。
我遇到的另一个问题是,您似乎只能在每个有效期内授权()服务帐户一次。您必须保存您获得的令牌并在接下来的一小时内重复使用它,然后再获取一个新令牌。
答案 1 :(得分:0)
我对Ruby一无所知。但似乎理解底层的REST查询有助于调试您的问题。我在这里记录了它们:http://www.tqis.com/eloquency/googlecalendar.htm
答案 2 :(得分:0)
我也遇到了麻烦,终于搞定了。最重要的是,Google Calendar API v3需要OAuth,您需要通过Google Developer Console设置应用/项目,然后在目标Google帐户上申请OAuth权限。授予授权后,您将要保存刷新令牌并在后续调用中使用它以获取新的访问令牌(过期!)。我在这里写了一篇详细的博客文章:http://www.geekytidbits.com/google-calendar-api-from-ruby/这是我的示例脚本,希望能帮助你理解这个流程:
#gem install 'google-api-client'
require 'google/api_client'
#Setup auth client
client_secrets = Google::APIClient::ClientSecrets.load #client_secrets.json must be present in current directory!
auth_client = client_secrets.to_authorization
auth_client.update!(
:scope => 'https://www.googleapis.com/auth/calendar',
:access_type => "offline", #will make refresh_token available
:approval_prompt =>'force',
:redirect_uri => 'http://www.myauthorizedredirecturl.com'
)
refresh_token_available = File.exist?('refresh_token.txt')
if !refresh_token_available
#OAuth URL - this is the url that will prompt a Google Account owner to give access to this app.
puts "Navigate browser to: '#{auth_client.authorization_uri.to_s}' and copy/paste auth code after redirect."
#Once the authorization_uri (above) is followed and authorization is given, a redirect will be made
#to http://www.myauthorizedredirecturl.com (defined above) and include the auth code in the request url.
print "Auth code: "
auth_client.code = gets
else
#If authorization has already been given and refresh token saved previously, simply set the refresh code here.
auth_client.refresh_token = File.read('refresh_token.txt')
end
#Now, get our access token which is what we will need to work with the API.
auth_client.fetch_access_token!
if !refresh_token_available
#Save refresh_token for next time
#Note: auth_client.refresh_token is only available the first time after OAuth permission is granted.
#If you need it again, the Google Account owner would have deauthorize your app and you would have to request access again.
#Therefore, it is important that the refresh token is saved after authenticating the first time!
File.open('refresh_token.txt', 'w') { |file| file.write(auth_client.refresh_token) }
refresh_token_available = true
end
api_client = Google::APIClient.new
cal = api_client.discovered_api('calendar', 'v3')
#Get Event List
puts "Getting list of events..."
list = api_client.execute(:api_method => cal.events.list,
:authorization => auth_client,
:parameters => {
'maxResults' => 20,
'timeMin' => '2014-06-18T03:12:24-00:00',
'q' => 'Meeting',
'calendarId' => 'primary'})
puts "Fetched #{list.data.items.count} events..."
#Update Event
puts "Updating first event from list..."
update_event = list.data.items[0]
update_event.description = "Updated Description here"
result = api_client.execute(:api_method => cal.events.update,
:authorization => auth_client,
:parameters => { 'calendarId' => 'primary', 'eventId' => update_event.id},
:headers => {'Content-Type' => 'application/json'},
:body_object => update_event)
puts "Done with update."
#Add New Event
puts "Inserting new event..."
new_event = cal.events.insert.request_schema.new
new_event.start = { 'date' => '2015-01-01' } #All day event
new_event.end = { 'date' => '2015-01-01' }
new_event.description = "Description here"
new_event.summary = "Summary here"
result = api_client.execute(:api_method => cal.events.insert,
:authorization => auth_client,
:parameters => { 'calendarId' => 'primary'},
:headers => {'Content-Type' => 'application/json'},
:body_object => new_event)
puts "Done with insert."