Kesalahan saat membuat acara kalender google dengan akun layanan

Dec 19 2020

Saya memiliki persyaratan untuk membuat acara kalender google di kalender dan menambahkan pengguna lain sebagai peserta ke acara itu. Tujuannya adalah untuk mengirim acara kalender ke pengguna aplikasi tanpa mengambil persetujuan mereka (O-Auth).

Setelah membaca dokumentasi Google, saya menemukan bahwa saya memerlukan akun layanan. Jadi saya membuat proyek dan akun layanan dari salah satu alamat email G-Suite kami, [email protected] dan mengaktifkan API kalender untuk hal yang sama.

Saya membuat dan mendownload pasangan kunci (JSON) yang isinya adalah,

{
  "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"
}

Dan sesuai dokumentasi, saya melanjutkan untuk menulis kode alur otentikasi,

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;
    }

The credentialobjek memiliki sebagian besar rincian dari file kunci. Tapi, ladang, serviceAccountUser, accessToken, refreshToken, clientAuthenticationdan requestInitializermemiliki nullnilai. (Saya menebak ada yang salah di sini)

Sekarang, dengan menggunakan credentialObject, saya terus menulis kode sesuai dokumentasi untuk membuat acara tersebut.

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("[email protected]") };
        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());

Tapi, ini mengakibatkan kesalahan,

{
  "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."
}

Setelah menghabiskan waktu Domain-Wide Delegation, saya mengerti bahwa ini diperlukan jika kami harus mengirim acara sebagai pengguna lain dari g-suite kami, yang tidak diperlukan untuk masalah saya. Tapi, untuk men-debug, saya melanjutkan dan menyediakan Domain-Wide Delegationdan menjalankan kembali program. Kesalahan yang sama terjadi lagi.

Jadi, saya menghapus undangan / peserta dari eventobjek dan menjalankan kembali aplikasinya. Kali ini program berjalan tanpa kesalahan apa pun, tetapi tautan acara yang dihasilkan, saat diklik, mengatakan Could not find the requested event,.

Saya tidak melihat contoh penggunaan akun layanan melalui perpustakaan klien java di tautan pengembang google.

Bisakah Anda memberi tahu saya apa yang salah di sini dan dokumentasi resmi / kerja tentang bagaimana tepatnya membuat acara kalender google dari proyek saya menambahkan pengguna lain (non g suite juga) untuk ditambahkan sebagai peserta, jadi saya tidak punya mendapatkan persetujuan dari pengguna lain untuk menambahkan acara ke kalender mereka sendiri?

Terima kasih.

Jawaban

DaImTo Dec 21 2020 at 15:06

Pertama, saya ingin mengatakan bahwa ini adalah sesuatu yang baru, jika Anda melihat banyak pertanyaan, dan tutorial yang tidak menyatakan Anda perlu melakukan ini karena akun layanan dulu dapat mengirim undangan, ini adalah sesuatu yang dikunci oleh Google sekitar satu tahun yang lalu.

Ini seharusnya berfungsi tetapi saya belum mengujinya karena saya tidak lagi memiliki akses ke akun G Suite. Anda harus meminta admin gsuite menyiapkan delegasi seluruh domain untuk pengguna lain. Kemudian akun layanan perlu menyamar sebagai pengguna tersebut sehingga akan muncul karena pengguna tersebut adalah orang yang mengirim undangan.

Satu-satunya contoh yang saya miliki tentang cara menambahkannya adalah di .net

Contoh .net

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

            }.FromCertificate(certificate);

Contoh tebakan jawa

Saya bukan pengembang java tetapi perpustakaan klien .net dan perpustakaan klien Java sangat dekat dalam cara mereka dikembangkan. Saya rasa Anda sedang mencari metode yang disebut 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 untuk Akun Layanan