我正在尝试编写一个程序,用于在多个Google帐户的CRM和Google日历之间同步事件。
这是一个Windows控制台应用程序。
对于每个Google帐户,我在API控制台中启用了Calendar API,创建了一个名为“UpdateSync”的应用程序(类型:native),然后下载了JSON文件。
我使用帐户邮件地址(即email1@gmail.com.json)重命名了这些文件
接下来,我写了下面的代码:
/// <summary>
/// Loads updated event from Google Calender after last synchonization date
/// </summary>
/// <param name="user">The user we want to get appointments</param>
public List<Appointment> LoadAppointments(User user)
{
Console.WriteLine("LoadAppointments({0})", user.Email);
List<Appointment> Appointments = new List<Appointment>();
UserCredential credential;
using (var stream = new FileStream(string.Format("credentials\\{0}.json", user.Email), FileMode.Open, FileAccess.Read))
{
try
{
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, new[] { CalendarService.Scope.Calendar }, "user", CancellationToken.None, new FileDataStore("UpdayeSync.Credentials")).Result;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
BaseClientService.Initializer initializer = new BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "UpdateSync";
service = new CalendarService(initializer);
EventsResource.ListRequest req = service.Events.List("primary");
req.TimeMin = DateTime.Now.AddMonths(-2).ToString("o");
req.ShowDeleted = true;
req.UpdatedMin = XmlConvert.ToString(LastSync, XmlDateTimeSerializationMode.Utc);
req.SingleEvents = true;
Events events;
try
{
events = req.Execute();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
// [...]
}
为每个JSON文件调用此代码。
第一次通话时,要同步的帐户是“email1@gmail.com”。 Google Chrome自动启用,并使用我自己的帐户(email2@gmail.com)自动登录,并要求我允许我的程序访问Calendar API。
我接受了。
此弹出窗口再也没有显示过。
任何帐户的更改都是在我自己的日历上完成的,而不是JSON文件所引用的。
怎么了?如何使用独特的程序访问多个Google帐户?
这个程序将作为计划任务在服务器上运行,我不能打开任何窗口,因为没有人会看到服务器的屏幕。我不能要求用户认证自己,因为没有用户。
但我可以对任何用户的Google帐户执行任何操作(启用API,创建密钥,授予应用程序等)。
答案 0 :(得分:2)
您应该为每个用户创建一个新的CalendarService(轻量级组件)。 CalendarService和所有其他Google服务都实现为不可变(为简单起见并支持线程安全操作)。
为每个用户创建一项新服务,并使用不同的userId(“user1”,“user2”等)作为GoogleWebAuthorizationBroker.AuthorizeAsync的参数。
更新:
您还应该创建自己的流程类:
class ForceUIGoogleAuthorizationCodeFlow : AuthorizationCodeFlow { public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri) { return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl)) { ClientId = ClientSecrets.ClientId, Scope = string.Join(" ", Scopes), RedirectUri = redirectUri, ApprovalPrompt = "force", }; } }
然后,
使用以下代码替换您对GoogleWebAuthorizationBroker的调用:
var initializer = new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = clientSecrets, Scopes = [SCOPED_HERE]; initializer.DataStore = new FileDataStore("Credentials"); }; var flow = new ForceUIGoogleAuthorizationCodeFlow(initializer);
// Create authorization code installed app instance and authorize the user.
crdentials = await new AuthorizationCodeInstalledApp(flow,
new LocalServerCodeReceiver()).AuthorizeAsync
("USER_ID_HERE", taskCancellationToken).ConfigureAwait(false);