公司的智能家居產品需要接入語音控制,目前在對接阿里語音的天貓精靈
對接天貓精靈的第一步是完成outh鑒權
https://doc-bot.tmall.com/docs/doc.htm?spm=0.7629140.0.0.84a01780RQrNoT&treeId=393&articleId=106999&docType=1
鑒權的博客可以參照如下博客
1.Java實現Aligenie天貓精靈OAuth2.0認證授權流程
https://blog.csdn.net/willianfu/article/details/87464528
免登錄式的
https://blog.csdn.net/weixin_41581158/article/details/81120028
帶有登錄的
貼個代碼說說自己的實現
天貓精靈的文檔還是很詳細的,第一步是登錄認證,認證OK之后重定向天貓精靈的地址(帶上code的)
登錄過程還是必要的,例如我的登錄過程,登錄上報了單元房ID,這樣就把這個天貓精靈和房屋建立關系了,通過這個code賦值的token也是單元房ID,這樣在設備控制和查詢的時候通過token就知道是查詢哪個單元房的設備了
第一步登錄,將回調地址放入map中,等待登錄成功后回調地址+code信息重定向
@RequestMapping(value = "/login") public String login(@ModelAttribute LoginForm loginForm, HttpServletRequest request) { String unicede = IdUtil.getId() + ""; String repsonse = "login"; try { //構建OAuth 授權請求 OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request); //if (oauthRequest.getClientId() != null && oauthRequest.getClientId().equals(clientId)) { LOG.info("clientID:" + oauthRequest.getClientId()); //利用oauth授權請求設置responseType,目前僅支持CODE,另外還有TOKEN String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE); //進行OAuth響應構建 OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND); builder.setParam("state", oauthRequest.getState()); //得到到客戶端重定向地址 String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI); //構建響應 OAuthResponse response = builder.location(redirectURI).buildQueryMessage(); String responceUri = response.getLocationUri(); //將url放入map,待用戶登錄后填上code做回調 loginForm.setUnicode(unicede); map.put(unicede, responceUri); //} } catch (OAuthSystemException e) { LOG.error("處理獲取code請求時發生異常", e); repsonse = "error"; } catch (OAuthProblemException e) { LOG.error("處理獲取code請求時發生異常", e); repsonse = "error"; } return repsonse; }
第二部登錄鑒權,登錄成功重定向至天貓精靈服務器,即返回天貓精靈code
@RequestMapping(value = "/loginSucess") public String add(@ModelAttribute LoginForm loginForm) { String uniCode = loginForm.getUnicode(); String redirectURL = map.get(uniCode); if (redirectURL == null) { LOG.error("用戶回調url為null,需要重新登錄"); return "error"; } map.remove(uniCode); //houseID鑒權 String house = loginForm.getHouseId(); IotGwInfo iotGwInfo = new IotGwInfo(); iotGwInfo.setIhouseId(house); List<IotGwInfo> iotGwInfoList = iotGwInfoService.getIotGwInfos(iotGwInfo); if (iotGwInfoList == null || iotGwInfoList.isEmpty()) { LOG.error("上報的houseid:{}下找不到網關", house); return "error"; } redirectURL = redirectURL + "&code=" + loginForm.getHouseId(); LOG.info("登錄回調地址:" + redirectURL); return "redirect:" + redirectURL; }
第三部 返回token,我的代碼里token值=代碼值=單元房ID,因為服務器做的是支持多網關的,一個單元房可以有多個網關
@RequestMapping(value = "/accessToken", method = RequestMethod.POST) public HttpEntity token(HttpServletRequest request) throws OAuthSystemException { OAuthResponse response = null; //構建OAuth請求 try { OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request); String id = oauthRequest.getClientSecret(); LOG.info("clientID:" + id); //if (id != null && id.equals(clientId)) { String token = request.getParameter("code"); //生成OAuth響應 response = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) .setAccessToken(token) .setRefreshToken(token) .setParam("expires_in", EXPIRE_TIME) .buildJSONMessage(); //} //根據OAuthResponse生成ResponseEntity return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } catch (OAuthSystemException e) { LOG.error("獲取accessToken發生問題", e); response = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) .setParam("error", "101") .setParam("error_description", "內部錯誤") .buildJSONMessage(); return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } catch (OAuthProblemException e) { LOG.error("獲取accessToken發生問題", e); response = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) .setParam("error", "102") .setParam("error_description", "參數錯誤") .buildJSONMessage(); return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } }
設備操作這塊就是json的了,主要是設備發現,設備查詢,設備控制三種功能。
@ApiOperation(value = "設備接口", notes = "設備接口") @RequestMapping(value = "/deviceHandle", method = RequestMethod.POST) public AliDevice deviceHandle(@RequestBody AliDevice aliDeviceReq) { LOG.info("請求數據:" + JSON.toJSONString(aliDeviceReq)); String action = aliDeviceReq.getHeader().getNamespace(); AliDevice resp = new AliDevice(); resp.setHeader(aliDeviceReq.getHeader()); switch (action) { case Constants.Namespace.deviceDiscovery: { aliboxDeviceService.deviceDiscovery(aliDeviceReq.getPayload().getAccessToken(), resp); resp.getHeader().setName(Constants.Name.deviceDiscoveryResp); break; } case Constants.Namespace.deviceControl: { aliboxDeviceService.deviceControl(aliDeviceReq, resp); break; } case Constants.Namespace.deviceQuery: { break; } default: { } } LOG.info("返回數據:" + JSON.toJSONString(resp)); return resp; }
以上是天貓精靈對接
在后台服務器里還需要一個天貓精靈的登錄頁面,就直接寫在后台了,使用thymeleaf,這塊就是學習做了,因為對前段不輸,就是白板寫出了功能。
spring: profiles: shypro thymeleaf: prefix: classpath:/templates/ suffix: .html mode: LEGACYHTML5 encoding: UTF-8 content-type: text/html cache: false
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"></meta> <title>login</title> </head> <body> <h1>login</h1> <div th:object="${loginForm}"> <p th:text="*{houseId}"></p> <p th:text="*{unicode}"></p> </div> <form action="#" th:action="@{/alibox/loginSucess}" th:object="${loginForm}" method="post"> <input type="text" th:field="*{houseId}"/> <input type="text" th:field="*{unicode}" text="${loginForm.unicode}"/> <input type="submit"/> </form> </body> </html>