当前位置: 首页 > 知识库问答 >
问题:

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

郑功
2023-03-14

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

在阅读了谷歌的留档后,我发现我需要一个服务号。所以我从我们的G-Suite的一个电子邮件地址创建了一个项目和一个服务号,noreply@xxxxx.com并为其启用了日历应用编程接口。

我创建并下载了一个密钥对(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;
    }

凭据对象具有密钥文件中的大部分详细信息。但是,字段,serviceAcCountUser访问令牌刷新令牌client验证请求初始化器具有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中的其他用户的身份发送活动,这是必要的,而我的问题不需要这样做。但是,为了调试,我继续提供了域范围的委托,并重新运行了程序。同样的错误再次出现。

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

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

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

非常感谢。


共有1个答案

李烨
2023-03-14

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

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

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

var gsuiteUser = "se@clawskeyboard.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
            {
                User = gsuiteUser,
                Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }

            }.FromCertificate(certificate);

我不是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();
  • 服务帐户的OAuth2
 类似资料:
  • 我试图实现与谷歌服务号的用户模拟,一直有一段时间的问题,这是我在Java使用的代码: 当我尝试从共享日历中读取事件时,我收到以下身份验证错误: com.google.api.client.auth.oauth2.TokenResponseException: 401未经授权的邮政https://oauth2.googleapis.com/token 如果我不使用模拟,我可以读取事件,但不能邀请与会

  • 要在Google日历中添加事件,我创建了一个Google服务号,从中我获得了客户端ID、服务帐户名称和p12密钥。现在从我的代码中,它正在创建一个事件,但它创建了自己的新日历以插入具有服务号名称的事件。我想在我的Google帐户的默认日历中添加事件。下面是服务号事件插入的工作代码。

  • 问题内容: 我想通过服务帐户在Google日历上创建新活动。我可以正确访问并打印我所有日历的列表。但是,当我想创建一个新事件时,响应为403 Forbidden。 我的代码: 和服务器响应: 有任何想法吗?可能是其他作用域,或允许编辑事件(我不知道在哪里可以配置它,并且已经搜索了,保证) 当然,我的日历是公共日历。 任何帮助都将受到欢迎:) 谢谢! 问题答案: 我解决了,问题不是代码,它工作正常。

  • 问题内容: 我正在尝试使用服务帐户在Google日历上创建条目。我真的很接近,但是最后一行是行不通的。我让它运行时得到提示。否则,程序将毫无错误地运行,无论花费多少。 该文件的内容可以发现在这里。在我试图调用方法开始在该文件上的1455线。 问题答案: 我想通了。由于我看不到将服务帐户与API v3一起使用的完整示例,因此我将发布完整的解决方案以供参考。但是,除了实现代码外,还需要做一些事情: 1

  • 因此,我已将服务号设置为域范围的授权,如本文所述执行谷歌办公套件域范围的授权。在谷歌办公套件管理控制台中,我已授权服务号使用OAuth 2.0范围: 每次我试图创建一个事件,最终都会出现这个错误 这建立了google凭据,不使用模拟,日历与服务号共享。

  • 我从快速入门开始(https://developers.google.com/google-apps/calendar/quickstart/python)而且效果很好。然后我尝试用这个指南插入事件(https://developers.google.com/google-apps/calendar/create-events)。我将此代码添加到quickstart的代码中,但出现错误。如何查看我