github.com/456vv/valexa@v1.0.2-0.20200706152242-1fb922d71ce5/EchoRequest.go (about) 1 package valexa 2 3 import ( 4 "time" 5 "fmt" 6 7 ) 8 9 /* 10 https://developer.amazon.com/zh/docs/custom-skills/request-and-response-json-reference.html 11 12 POST / HTTP/1.1 13 Content-Type : application/json;charset=UTF-8 14 Host : your.application.endpoint 15 Content-Length : 16 Accept : application/json 17 Accept-Charset : utf-8 18 Signature: 19 SignatureCertChainUrl: https://s3.amazonaws.com/echo.api/echo-api-cert.pem 20 Request Body Syntax 21 22 { 23 "version": "1.0", 24 "session": { 25 "new": true, 26 "sessionId": "amzn1.echo-api.session.[unique-value-here]", 27 "application": { 28 "applicationId": "amzn1.ask.skill.[unique-value-here]" 29 }, 30 "attributes": { 31 "key": "string value" 32 }, 33 "user": { 34 "userId": "amzn1.ask.account.[unique-value-here]", 35 "accessToken": "Atza|AAAAAAAA...", 36 "permissions": { 37 "consentToken": "ZZZZZZZ..." 38 } 39 } 40 }, 41 "context": { 42 "System": { 43 "device": { 44 "deviceId": "string", 45 "supportedInterfaces": { 46 "AudioPlayer": {} 47 } 48 }, 49 "application": { 50 "applicationId": "amzn1.ask.skill.[unique-value-here]" 51 }, 52 "user": { 53 "userId": "amzn1.ask.account.[unique-value-here]", 54 "accessToken": "Atza|AAAAAAAA...", 55 "permissions": { 56 "consentToken": "ZZZZZZZ..." 57 } 58 }, 59 "apiEndpoint": "https://api.amazonalexa.com", 60 "apiAccessToken": "AxThk..." 61 }, 62 "AudioPlayer": { 63 "playerActivity": "PLAYING", 64 "token": "audioplayer-token", 65 "offsetInMilliseconds": 0 66 } 67 }, 68 "request": { 69 "type": "IntentRequest", 70 "requestId": "string", 71 "timestamp": "string", 72 "dialogState": "string", 73 "locale": "string", 74 "intent": { 75 "name": "string", 76 "confirmationStatus": "string", 77 "slots": { 78 "SlotName": { 79 "name": "string", 80 "value": "string", 81 "confirmationStatus": "string", 82 "resolutions": { 83 "resolutionsPerAuthority": [ 84 { 85 "authority": "string", 86 "status": { 87 "code": "string" 88 }, 89 "values": [ 90 { 91 "value": { 92 "name": "string", 93 "id": "string" 94 } 95 } 96 ] 97 } 98 ] 99 } 100 } 101 } 102 } 103 } 104 } 105 106 //IntentRequest Example 107 { 108 "version": "1.0", 109 "session": { 110 "new": false, 111 "sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000", 112 "application": { 113 "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe" 114 }, 115 "attributes": { 116 "supportedHoroscopePeriods": { 117 "daily": true, 118 "weekly": false, 119 "monthly": false 120 } 121 }, 122 "user": { 123 "userId": "amzn1.account.AM3B00000000000000000000000" 124 } 125 }, 126 "context": { 127 "System": { 128 "application": { 129 "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe" 130 }, 131 "user": { 132 "userId": "amzn1.account.AM3B00000000000000000000000" 133 }, 134 "device": { 135 "supportedInterfaces": { 136 "AudioPlayer": {} 137 } 138 } 139 }, 140 "AudioPlayer": { 141 "offsetInMilliseconds": 0, 142 "playerActivity": "IDLE" 143 } 144 }, 145 "request": { 146 "type": "IntentRequest", 147 "requestId": " amzn1.echo-api.request.0000000-0000-0000-0000-00000000000", 148 "timestamp": "2015-05-13T12:34:56Z", 149 "dialogState": "COMPLETED", 150 "locale": "string", 151 "intent": { 152 "name": "GetZodiacHoroscopeIntent", 153 "confirmationStatus": "NONE" 154 "slots": { 155 "ZodiacSign": { 156 "name": "ZodiacSign", 157 "value": "virgo", 158 "confirmationStatus": "NONE" 159 } 160 } 161 } 162 } 163 } 164 165 SessionEndedRequest: 166 { 167 "version": "1.0", 168 "session": { 169 "new": false, 170 "sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000", 171 "application": { 172 "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe" 173 }, 174 "attributes": { 175 "supportedHoroscopePeriods": { 176 "daily": true, 177 "weekly": false, 178 "monthly": false 179 } 180 }, 181 "user": { 182 "userId": "amzn1.account.AM3B00000000000000000000000" 183 } 184 }, 185 "context": { 186 "System": { 187 "application": { 188 "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe" 189 }, 190 "user": { 191 "userId": "amzn1.account.AM3B00000000000000000000000" 192 }, 193 "device": { 194 "supportedInterfaces": { 195 "AudioPlayer": {} 196 } 197 } 198 }, 199 "AudioPlayer": { 200 "offsetInMilliseconds": 0, 201 "playerActivity": "IDLE" 202 } 203 }, 204 "request": { 205 "type": "SessionEndedRequest", 206 "requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000", 207 "timestamp": "2015-05-13T12:34:56Z", 208 "reason": "USER_INITIATED", 209 "locale": "string" 210 } 211 } 212 */ 213 214 215 216 217 //提供AudioPlayer接口当前状态的对象 218 //https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#audioplayer-object 219 type EchoRequestContextAudioPlayer struct { 220 //发送请求时的轨道偏移量(以毫秒为单位)。 221 //如果曲目在开头,这是0。AudioPlayer当您的技能是最近在设备上播放音频的技能时,这只会包含在对象中。 222 OffsetInMilliseconds int `json:"offsetInMilliseconds"` 223 224 //音频播放的最后已知状态。 225 //IDLE:没有什么,没有入队的项目。 226 //PAUSED:流已暂停。 227 //PLAYING:流正在播放。 228 //BUFFER_UNDERRUN:缓冲区不足 229 //FINISHED:流完了。STOPPED:流被中断。 230 PlayerActivity string `json:"playerActivity"` 231 232 //音频流的不透明标记。发送Play指令时提供此标记。 233 //AudioPlayer当您的技能是最近在设备上播放音频的技能时,这只会包含在对象中。 234 Token string `json:"token"` 235 } 236 237 type EchoRequestContextSystemApplication struct { 238 ApplicationID string `json:"applicationId"` 239 } 240 241 type EchoRequestContextSystemDeviceSupportedInterfaces struct { 242 AudioPlayer struct{} `json:"AudioPlayer"` 243 } 244 245 type EchoRequestContextSystemDevice struct { 246 DeviceID string `json:"deviceId"` 247 SupportedInterfaces EchoRequestContextSystemDeviceSupportedInterfaces `json:"supportedInterfaces"` 248 } 249 250 type EchoRequestContextSystemUserPermissions struct { 251 ConsentToken string `json:"consentToken"` 252 } 253 254 type EchoRequestContextSystemUser struct { 255 AccessToken string `json:"accessToken"` 256 Permissions EchoRequestContextSystemUserPermissions `json:"permissions"` 257 UserID string `json:"userId"` 258 } 259 260 type EchoRequestContextSystem struct { 261 APIAccessToken string `json:"apiAccessToken"` 262 APIEndpoint string `json:"apiEndpoint"` 263 Application EchoRequestContextSystemApplication `json:"application"` 264 Device EchoRequestContextSystemDevice `json:"device"` 265 User EchoRequestContextSystemUser `json:"user"` 266 } 267 268 //Alexa服务和设备的当前状态的信息。用于在会话(的上下文中发送的请求LaunchRequest和IntentRequest)时, 269 //context对象将复制user和application其也可在信息session对象。 270 //https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#context-object 271 type EchoRequestContext struct { 272 AudioPlayer EchoRequestContextAudioPlayer `json:"AudioPlayer"` 273 System EchoRequestContextSystem `json:"System"` 274 275 } 276 277 type EchoRequestRequestError struct { 278 Message string `json:"message"` 279 Type string `json:"type"` 280 } 281 282 type EchoRequestRequestIntentSlot struct { 283 ConfirmationStatus string `json:"confirmationStatus"` 284 Resolutions struct{} `json:"resolutions"` 285 Name string `json:"name"` 286 Value string `json:"value"` 287 } 288 289 type EchoRequestRequestIntent struct { 290 ConfirmationStatus string `json:"confirmationStatus"` 291 Name string `json:"name"` 292 Slots map[string]*EchoRequestRequestIntentSlot `json:"slots"` 293 } 294 295 type EchoRequestRequest struct { 296 DialogState string `json:"dialogState"` 297 Error EchoRequestRequestError `json:"error"` 298 Intent EchoRequestRequestIntent `json:"intent"` 299 Locale string `json:"locale"` 300 Reason string `json:"reason"` 301 RequestID string `json:"requestId"` 302 Timestamp string `json:"timestamp"` 303 Type string `json:"type"` 304 } 305 306 type EchoRequestSessionApplication struct { 307 ApplicationID string `json:"applicationId"` 308 } 309 310 type EchoRequestSessionUserPermissions struct { 311 ConsentToken string `json:"consentToken"` 312 } 313 type EchoRequestSessionUser struct { 314 AccessToken string `json:"accessToken"` 315 Permissions EchoRequestSessionUserPermissions `json:"permissions"` 316 UserID string `json:"userId"` 317 } 318 type EchoRequestSession struct { 319 Application EchoRequestSessionApplication `json:"application"` 320 Attributes struct{} `json:"attributes"` 321 New bool `json:"new"` 322 SessionID string `json:"sessionId"` 323 User EchoRequestSessionUser `json:"user"` 324 } 325 type EchoRequest struct { 326 Context EchoRequestContext `json:"context"` 327 Request EchoRequestRequest `json:"request"` 328 Session EchoRequestSession `json:"session"` 329 Version string `json:"version"` 330 } 331 332 //验证请求是否有效 333 // second int 允许过时多久? 334 // bool true有效,false无效 335 func (T *EchoRequest) VerifyTimestamp(second int) bool { 336 reqTimestamp, err := time.Parse(time.RFC3339, T.Request.Timestamp) 337 if err != nil { 338 return false 339 } 340 if time.Since(reqTimestamp) < time.Duration(second)*time.Second { 341 return true 342 } 343 return false 344 } 345 346 //读取语言类型 347 // string 语言类型 348 func (T *EchoRequest) GetLocale() string { 349 return T.Request.Locale 350 } 351 352 //读取程序ID 353 // string 程序ID 354 func (T *EchoRequest) GetApplicationID() string { 355 return T.Session.Application.ApplicationID 356 } 357 358 //读取本次会话的ID。如果用户结束会话,再发起会话,这个ID将是一个全新ID。 359 // string 会话ID 360 func (T *EchoRequest) GetSessionID() string { 361 return T.Session.SessionID 362 } 363 364 //读取用户的ID 365 // string 用户ID 366 func (T *EchoRequest) GetUserID() string { 367 return T.Session.User.UserID 368 } 369 370 //读取用户的令牌 371 // string 令牌 372 func (T *EchoRequest) GetAccessToken() string { 373 return T.Session.User.AccessToken 374 } 375 376 377 //读取意图类型,有效:LaunchRequest, IntentRequest, SessionEndedRequest 378 // string 意图类型 379 func (T *EchoRequest) GetRequestType() string { 380 return T.Request.Type 381 } 382 383 //读取意图名称,如标注符:{Map} 384 // string 意图名称 385 func (T *EchoRequest) GetIntentName() string { 386 if T.GetRequestType() == "IntentRequest" { 387 return T.Request.Intent.Name 388 } 389 return "" 390 } 391 392 //读取出所有Solt对象,所有值,包含空值 393 // slots 所有跟踪名称和值 394 // err 错误,如果不是意图类型请求,调用这个方法,将会返回错误 395 func (T *EchoRequest) GetSlots() (slots map[string]*EchoRequestRequestIntentSlot, err error) { 396 if T.GetRequestType() != "IntentRequest" { 397 return nil, fmt.Errorf("valexa: 此意图类型不支持读取插槽,仅支持IntentRequest类型。") 398 } 399 400 slots = T.Request.Intent.Slots 401 if slots == nil { 402 return nil, fmt.Errorf("valexa: 插槽为nil") 403 } 404 return 405 } 406 407 //读取出所有Solt对象,非空值的 408 // slots 所有跟踪名称和值 409 // err 错误,如果不是意图类型请求,调用这个方法,将会返回错误 410 func (T *EchoRequest) GetValueSlots() (slots map[string]*EchoRequestRequestIntentSlot, err error) { 411 gslots, err := T.GetSlots() 412 if err != nil { 413 return 414 } 415 slots = make(map[string]*EchoRequestRequestIntentSlot) 416 for key, slot := range gslots { 417 if slot.Value != "" { 418 slots[key] = slot 419 } 420 } 421 return slots, nil 422 } 423 424 425 426 //读取出所有Solt名称 427 // names 所有跟踪名称 428 func (T *EchoRequest) GetSlotNames() (names []string) { 429 names = []string{} 430 slots, err := T.GetSlots() 431 if err != nil { 432 return 433 } 434 for k, _ := range slots { 435 names = append(names, k) 436 } 437 return 438 } 439 440 //读取Solt值 441 // slotName 跟踪名称 442 // val 跟踪的值 443 // err 错误,如果这个名称不存在,将会返回错误 444 func (T *EchoRequest) GetSlotValue(slotName string) (val string, err error) { 445 slots, err := T.GetSlots() 446 if err != nil { 447 return 448 } 449 if slot, ok := slots[slotName]; ok { 450 return slot.Value, nil 451 } 452 return "", fmt.Errorf("valexa: 名称(%s)没有找到匹配 Solt !", slotName) 453 } 454 455 //读取Solt对象 456 // slotName 跟踪名称 457 // slot 跟踪的对象 458 // err 错误,如果这个名称不存在,将会返回错误 459 func (T *EchoRequest) GetSlot(slotName string) (slot *EchoRequestRequestIntentSlot, err error) { 460 slots, err := T.GetSlots() 461 if err != nil { 462 return 463 } 464 slot, ok := slots[slotName] 465 if ok { 466 return 467 } 468 return nil, fmt.Errorf("valexa: 名称(%s)没有找到匹配 Solt !", slotName) 469 }