API Google Kalender v3 selalu mengembalikan BadRequest saat membuat acara

Aug 18 2020

Saya membuat kalender bersama dan ingin menambahkan acara ke kalender.

Saya membuat proyek dan menyiapkan Akun Layanan [email protected].

Kemudian saya membagikan kalender ke Akun Layanan sebagai pemilik .

Kemudian saya perhatikan

Akun Layanan harus menambahkan kalender bersama secara manual

seperti yang dijelaskan di sini https://stackoverflow.com/a/62232361/298430 dan https://issuetracker.google.com/issues/148804709

Jadi saya menulis kode:

 @Test
  fun addCalendarToServiceAccount() {

    val calList1: CalendarList = calendar.calendarList().list().execute()
    logger.info("calList1 = {}", calList1)

    val inserted = calendar.calendarList().insert(CalendarListEntry().setId(calendarId)).execute()
    logger.info("inserted = {}", inserted)

    val calList2: CalendarList = calendar.calendarList().list().execute()
    logger.info("calList2 = {}", calList2)
  }

Ini bekerja dengan sempurna. Ketika pertama kali dipanggil, saya bisa melihat calList1kosong, dan calList2berisi sesuatu.

Kemudian saya secara manual memasukkan satu acara ke kalender (dengan Google Calendar UI WEB), saya ingin memeriksa apakah saya dapat mengambil acara tersebut:

@Test
  fun listEvents() {
    val events: Events = calendar.events().list(calendarId).execute()
    logger.info("events = {}", events)
    events.items.forEachIndexed { index, e ->
      logger.info("Event [index = {}] , event = {}", index, e)
    }
  }

Ini juga berhasil.

{
   "accessRole":"owner",
   "defaultReminders":[

   ],
   "etag":"\"xxx\"",
   "items":[
      {
         "created":"2020-08-17T17:51:21.000Z",
         "creator":{
            "email":"[email protected]"
         },
         "end":{
            "date":"2020-08-20"
         },
         "etag":"\"xxx\"",
         "htmlLink":"https://www.google.com/calendar/event?eid=xxx",
         "iCalUID":"[email protected]",
         "id":"xxx",
         "kind":"calendar#event",
         "organizer":{
            "displayName":"xxx",
            "email":"[email protected]",
            "self":true
         },
         "reminders":{
            "useDefault":false
         },
         "sequence":0,
         "start":{
            "date":"2020-08-19"
         },
         "status":"confirmed",
         "summary":"xxx  test1",
         "transparency":"transparent",
         "updated":"2020-08-18T01:07:54.441Z"
      }
   ],
   "kind":"calendar#events",
   "nextSyncToken":"xxx",
   "summary":"xxx",
   "timeZone":"Asia/Taipei",
   "updated":"2020-08-18T01:07:54.688Z"
}

Lalu saya ingin memasukkan sesuatu secara terprogram, seperti contoh API yang ditunjukkan:

@Test
  fun testInsertEvent() {
    val now = LocalDateTime.now().withSecond(0).withNano(0)
    val zoneId = ZoneId.of("Asia/Taipei")
    val fromDate = Date.from(now.atZone(zoneId).toInstant())
    val endDate = Date.from(now.plusMinutes(60).atZone(zoneId).toInstant())

    val event = 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.")
      .setStart(EventDateTime().setDate(DateTime(fromDate, TimeZone.getTimeZone(zoneId))))
      .setEnd(EventDateTime().setDate(DateTime(endDate, TimeZone.getTimeZone(zoneId))))

    logger.info("before insert event : {}", event)

    val eventResult: Event = calendar.events().insert(calendarId, event).execute()
    logger.info("eventResult = {}", eventResult)
  }

Saya dapat melihat klien benar-benar POST ke titik akhir google'e:

Tubuhnya adalah:

{
   "description":"A chance to hear more about Google's developer products.",
   "end":{
      "date":"2020-08-18T11:32:00.000+08:00"
   },
   "location":"800 Howard St., San Francisco, CA 94103",
   "start":{
      "date":"2020-08-18T10:32:00.000+08:00"
   },
   "summary":"Google I/O 2015"
}

Tapi google baru saja menjawab 400 BadRequest, tanpa penjelasan lebih lanjut:

2020-08-18 10:32:15.974 [main] INFO  c.g.a.c.h.HttpResponse - -------------- RESPONSE --------------
HTTP/1.1 400 Bad Request
Transfer-Encoding: chunked
Alt-Svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Server: ESF
X-Content-Type-Options: nosniff
Pragma: no-cache
Date: Tue, 18 Aug 2020 02:32:15 GMT
X-Frame-Options: SAMEORIGIN
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Vary: Referer
Vary: X-Origin
Vary: Origin
Expires: Mon, 01 Jan 1990 00:00:00 GMT
X-XSS-Protection: 0
Content-Type: application/json; charset=UTF-8

2020-08-18 10:32:15.980 [main] INFO  c.g.a.c.u.LoggingByteArrayOutputStream - Total: 171 bytes
2020-08-18 10:32:15.980 [main] INFO  c.g.a.c.u.LoggingByteArrayOutputStream - {
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "badRequest",
    "message": "Bad Request"
   }
  ],
  "code": 400,
  "message": "Bad Request"
 }
}

Saya menggunakan contoh kalender yang sama , berhasil addCalendarToServiceAccount()(sebagai owner) dan listEvents(). Tapi apa yang salah saat menyisipkan acara? Apakah saya melewatkan sesuatu?

Bidang lain diinisialisasi sebagai berikut:

  @Value("\${google.calendar.id}") private lateinit var calendarId: String @Value("\${google.calendar.apiKey}")
  private lateinit var apiKey : String

  private val httpTransport: HttpTransport by lazy {
    GoogleNetHttpTransport.newTrustedTransport()
  }

  private val jacksonFactory: JsonFactory by lazy {
    JacksonFactory.getDefaultInstance()
  }

  private val saCredentials: GoogleCredentials by lazy {
    javaClass.getResourceAsStream("/chancer-d1de03c4c25a.json").use { iStream ->
      ServiceAccountCredentials.fromStream(iStream)
        .createScoped(listOf(
          "https://www.googleapis.com/auth/cloud-platform",
          *CalendarScopes.all().toTypedArray()
        ))
    }.apply {
      refreshIfExpired()
    }
  }


  private val requestInitializer: HttpRequestInitializer by lazy {
    HttpCredentialsAdapter(saCredentials)
  }

  private val calendar: Calendar by lazy {
    Calendar.Builder(httpTransport, jacksonFactory, requestInitializer)
      .build()
  }

Lingkungan:

    <java.version>1.8</java.version>
    <kotlin.version>1.4.0</kotlin.version>


    <dependency>
      <groupId>com.google.api-client</groupId>
      <artifactId>google-api-client</artifactId>
      <version>1.30.10</version>
    </dependency>
    <dependency>
      <groupId>com.google.apis</groupId>
      <artifactId>google-api-services-calendar</artifactId>
      <version>v3-rev20200610-1.30.10</version>
    </dependency>
    <dependency>
      <groupId>com.google.auth</groupId>
      <artifactId>google-auth-library-oauth2-http</artifactId>
      <version>0.21.1</version>
    </dependency>

Jawaban

2 RafaGuillermo Aug 18 2020 at 17:14

Menjawab:

Anda perlu menggunakan start.dateTimedan end.dateTimedaripada start.datedanend.date

Memperbaiki:

Sesuai dokumentasi :

end.date: Tanggal, dalam format "yyyy-mm-dd", jika ini adalah acara sepanjang hari.

end.dateTime: Waktu, sebagai nilai tanggal-waktu gabungan (diformat menurut RFC3339). Pengimbangan zona waktu diperlukan kecuali zona waktu ditentukan secara eksplisit di zona waktu .

start.date: Tanggal, dalam format "yyyy-mm-dd", jika ini adalah acara sepanjang hari.

start.dateTime: Waktu, sebagai nilai tanggal-waktu gabungan (diformat menurut RFC3339). Pengimbangan zona waktu diperlukan kecuali zona waktu ditentukan secara eksplisit di zona waktu .

Oleh karena itu, Anda perlu mengubah metode pengaturan tanggal & waktu Anda dari:

EventDateTime().setDate(DateTime(fromDate, TimeZone.getTimeZone(zoneId))))

untuk:

EventDateTime().setDateTime(DateTime(fromDate, TimeZone.getTimeZone(zoneId))))

Yang akan mengubah isi permintaan menjadi:

{
  "description": "A chance to hear more about Google's developer products.",
  "end": {
      "dateTime": "2020-08-18T11:32:00.000+08:00" // modified
  },
  "location": "800 Howard St., San Francisco, CA 94103",
  "start": {
    "dateTime": "2020-08-18T10:32:00.000+08:00" // modified
  },
  "summary": "Google I/O 2015"
}

Anda dapat melihat dokumentasi untuk metode ini di sini .

Saya harap ini dapat membantu anda!

Referensi:

  • Acara: masukkan | API Kalender | Pengembang Google
  • RFC 3339 - Tanggal dan Waktu di Internet: Stempel waktu
  • EventDateTime (API Kalender v3-rev20200610-1.30.10)