Java 使用服务帐户创建google日历事件时出错

Java 使用服务帐户创建google日历事件时出错,java,google-api,google-calendar-api,google-api-java-client,service-accounts,Java,Google Api,Google Calendar Api,Google Api Java Client,Service Accounts,我需要在日历上创建google日历事件,并将其他用户添加为该事件的参与者。目标是向应用程序用户发送日历事件,而无需征得其同意(O-Auth) 在阅读了谷歌的文档后,我发现我需要一个服务帐户。所以我从我们G-Suite的一个电子邮件地址创建了一个项目和一个服务帐户,noreply@xxxxx.com并启用了相同的日历API 我创建并下载了一个密钥对(JSON),其内容是 { "type": "service_account", "proje

我需要在日历上创建google日历事件,并将其他用户添加为该事件的参与者。目标是向应用程序用户发送日历事件,而无需征得其同意(O-Auth)

在阅读了谷歌的文档后,我发现我需要一个服务帐户。所以我从我们G-Suite的一个电子邮件地址创建了一个项目和一个服务帐户,noreply@xxxxx.com并启用了相同的日历API

我创建并下载了一个密钥对(JSON),其内容是

{
  "type": "service_account",
  "project_id": "*****",
  "private_key_id": "bdbbcd**************49f77d599f2",
  "private_key": "**"
  "client_email": "******@*****.iam.gserviceaccount.com",
  "client_id": "11083******576856",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/****dev%40*****kdev.iam.gserviceaccount.com"
}
根据文档,我开始编写身份验证流代码

public static GoogleCredential doOauth( String credsPath ) throws IOException
    {
        GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(credsPath))
                .createScoped(Collections.singleton(CalendarScopes.CALENDAR));
        System.out.println(credential);
        return credential;
    }
credential
对象包含密钥文件中的大部分详细信息。但是,
serviceAccountUser
accessToken
refreshToken
clientAuthentication
requestInitializer
字段具有
null
值。(我猜这里有点不对劲)

现在,使用
credentialObject
,我继续按照文档编写代码来创建事件

GoogleCredential credential = doOauth(CREDENTIALS_FILE_PATH);
        Event event = new Event().setSummary("Google I/O 2015").setLocation("800 Howard St., San Francisco, CA 94103")
                .setDescription("A chance to hear more about Google's developer products.");
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

        DateTime startDateTime = new DateTime("2020-12-28T09:00:00-07:00");
        EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/Los_Angeles");
        event.setStart(start);

        DateTime endDateTime = new DateTime("2020-12-28T17:00:00-07:00");
        EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone("America/Los_Angeles");
        event.setEnd(end);

        String[] recurrence = new String[] { "RRULE:FREQ=DAILY;COUNT=2" };
        event.setRecurrence(Arrays.asList(recurrence));

        EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail("myemailaddress@gmail.com.com") };
        event.setAttendees(Arrays.asList(attendees));

        EventReminder[] reminderOverrides = new EventReminder[] {
                new EventReminder().setMethod("email").setMinutes(24 * 60),
                new EventReminder().setMethod("popup").setMinutes(10), };
        Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
                .setOverrides(Arrays.asList(reminderOverrides));
        event.setReminders(reminders);
        String calendarId = "primary";
        Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName("testapp").build();
        event = service.events().insert(calendarId, event).execute();
        System.out.printf("Event created: %s\n", event.getHtmlLink());
但是这就导致了这个错误,

{
  "code" : 403,
  "errors" : [ {
    "domain" : "calendar",
    "message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.",
    "reason" : "forbiddenForServiceAccounts"
  } ],
  "message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority."
}
在花时间进行了
域范围的委派之后
,我了解到,如果我们必须以g-suite中的其他用户的身份发送事件,则需要这样做,而我的问题不需要这样做。但是,为了调试,我继续提供了
域范围的委托
,并重新运行了程序。同样的错误再次出现

因此,我从
事件
对象中删除了被邀请者/与会者,并重新运行了应用程序。这次程序运行时没有出现任何错误,但在单击时生成的事件链接显示,
找不到请求的事件

在googledeveloper链接上,我没有看到任何通过java客户端库使用服务帐户的例子

您能告诉我这里出了什么问题,以及如何从我的项目中创建google日历事件的官方/工作文档吗?添加其他(非g套件)用户以添加为与会者,这样我就不必征得其他用户的同意才能将事件添加到他们自己的日历中


谢谢。

首先我想说的是,如果你看到很多问题和教程没有说明你需要这样做,这是新的东西,因为服务帐户过去可以发送邀请,这是谷歌大约一年前锁定的东西

这应该可以工作,但我没有测试它,因为我不再有权访问Gsuite帐户。您需要将gsuite管理员设置为另一个用户。然后,服务帐户需要模拟该用户,以便显示该用户是发送邀请的用户

关于如何添加的唯一示例是在.net中

.net示例 Java示例猜测 我不是java开发人员,但.net客户机库和java客户机库的开发方式非常接近。我猜您正在寻找一个名为setServiceAccountUser的方法

GoogleCredential credential = new  GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(CalendarScopes.CALENDAR)
                .setServiceAccountPrivateKeyFromP12File(credsPath))
                .setServiceAccountUser(gsuiteUser)
                .build();
GoogleCredential credential = new  GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(CalendarScopes.CALENDAR)
                .setServiceAccountPrivateKeyFromP12File(credsPath))
                .setServiceAccountUser(gsuiteUser)
                .build();