Google Calendar API v3는 이벤트 생성시 항상 BadRequest를 반환합니다.
공유 캘린더를 만들고 캘린더에 이벤트를 추가하고 싶습니다.
프로젝트를 만들고 서비스 계정을 설정했습니다 [email protected]
.
그런 다음 캘린더를 소유자 로 서비스 계정에 공유했습니다 .
그러다가
서비스 계정은 공유 캘린더를 수동으로 추가해야합니다.
여기에 설명 된대로 https://stackoverflow.com/a/62232361/298430 과 https://issuetracker.google.com/issues/148804709
그래서 코드를 작성했습니다.
@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)
}
완벽하게 작동합니다. 처음 호출했을 때 calList1
비어 있고 calList2
무언가를 포함하고 있음을 알 수 있습니다.
그런 다음 수동으로 하나의 이벤트를 캘린더에 삽입하고 (Google 캘린더 웹 UI 사용) 이벤트를 검색 할 수 있는지 확인하고 싶습니다.
@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)
}
}
그것은 또한 작동합니다.
{
"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"
}
그런 다음 API 예제와 같이 프로그래밍 방식으로 무언가를 삽입하고 싶습니다.
@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)
}
클라이언트가 google'e 엔드 포인트에 실제로 POST를 수행하는 것을 볼 수 있습니다.
![](https://post.nghiatu.com/assets/images/s/sqQHF.png)
몸은 :
{
"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"
}
그러나 Google은 추가 설명없이 400 BadRequest에 응답했습니다.
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"
}
}
동일한 달력 인스턴스를 사용하고 있습니다 . addCalendarToServiceAccount()
( owner
) 및 listEvents()
. 그러나 이벤트를 삽입 할 때 무엇이 잘못됩니까? 내가 놓친 것이 있습니까?
다른 필드는 다음과 같이 초기화됩니다.
@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()
}
환경 :
<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>
답변
대답:
당신은 사용해야 start.dateTime
하고 end.dateTime
보다는 start.date
및end.date
고치다:
당으로 문서 :
end.date
: 종일 이벤트 인 경우 "yyyy-mm-dd"형식의 날짜입니다.
end.dateTime
: 결합 된 날짜-시간 값으로 표시되는 시간 (RFC3339에 따라 형식화 됨). 시간대가 timeZone에 명시 적으로 지정되지 않은 경우 시간대 오프셋이 필요합니다 .
start.date
: 종일 이벤트 인 경우 "yyyy-mm-dd"형식의 날짜입니다.
start.dateTime
: 결합 된 날짜-시간 값으로 표시되는 시간 (RFC3339에 따라 형식화 됨). 시간대가 timeZone에 명시 적으로 지정되지 않은 경우 시간대 오프셋이 필요합니다 .
따라서 날짜 및 시간 설정 방법을 다음에서 변경해야합니다.
EventDateTime().setDate(DateTime(fromDate, TimeZone.getTimeZone(zoneId))))
에:
EventDateTime().setDateTime(DateTime(fromDate, TimeZone.getTimeZone(zoneId))))
요청 본문을 다음과 같이 변경합니다.
{
"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"
}
이 방법에 대한 설명서는 여기에서 볼 수 있습니다 .
도움이 되었기를 바랍니다.
참조 :
- 이벤트 : 삽입 | 캘린더 API | Google 개발자
- RFC 3339-인터넷의 날짜 및 시간 : 타임 스탬프
- EventDateTime (Calendar API v3-rev20200610-1.30.10)