使用Java实现与天猫精灵智能设备的对接

1. https://open.bot.tmall.com/   首先了解天猫精灵智能设备的对接文档

2.创建技能什么的都不用讲了,这里主要讲一下服务配置

3.服务配置好以后,我们开始搭建OAuth2授权服务器,这里我选用JAVA,本身自己就是做安卓的,JAVA会比较容易上手

直接贴代码

package com.hjzn.oauth.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.tools.JavaCompiler;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.request.OAuthRequest;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.http.HttpStatus;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hjzn.oauth.entity.HotelRoom;
import com.hjzn.oauth.entity.Room;
import com.hjzn.oauth.entity.User;
import com.hjzn.oauth.service.RoomService;
import com.hjzn.oauth.service.UserService;
import com.hjzn.oauth.utils.JnaNative;
import com.hjzn.oauth.utils.JnaUtils;
import com.sun.jna.Native;

@Controller
public class OAuthController {
	
	@Autowired
	private UserService userService;		//登录授权数据层
	@Autowired
	private RoomService roomService;
	private String baseURL = "https://www.xxxxx.com";	//OAuth2授权服务器发布的地址
	//private String baseURL = "https://4598907a.ngrok.io";
	private String cutURL = baseURL+"/HjznOAuth2/";		//天猫精灵请求授权接口
	private String OAuthURL = baseURL+"/HjznOAuth2/responseCode";	//登录成功后将code通过天猫回调地址返回给天猫
	private int cutlength = cutURL.length();  //截去参数的时候需要
	private String userName;	//登录帐号
	
	

	/**
	 * 用户登录授权界面
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 * @throws OAuthSystemException
	 */
    @RequestMapping("/userLogin")
    public String userlogin(HttpServletRequest request) throws IOException, OAuthSystemException
    {
    	String url = request.getHeader("referer");
        //获取到登录帐号
    	String username = request.getParameter("username");
        //获取登录密码
    	String password = request.getParameter("password");
        //登录验证
    	User user= userService.userLogin(username, password);

         if(user!= null)
    		{
    			userName = user.getUsername();
    			log("登录成功!");
    			String outURL = java.net.URLDecoder.decode(url, "GBK");
    			log("decode后的地址:"+outURL);
    			int outlength = outURL.length();   //解密后的请求参数长度
    			String responseURL = outURL.substring(cutlength, outlength);
    			log("截取出请求的参数:"+responseURL);
    			String responseCodeUrl = OAuthURL + responseURL;

    			log("拼接responseCodeUrl接口:"+responseCodeUrl);
    			/*
    			 * 拼接完后应该这样子 https://www.xxxxx.com/HjznOAuth2/responseCode?redirect_uri=https://open.bot.tmall.com/oauth/callback?skillId=20690&token=NDExNjU2Nzg1M0FGRUhJTkZEVlE=&client_id=123&response_type=code&state=0.7387369400561126
    			 * */
    			return "redirect:" + responseCodeUrl; //重定向后就会进入/responseCode 
    		}
    		else
    		{
    			return "redirect:/error.jsp";
    		}
    		
		return "redirect:/error.jsp";
    }

	/**
	 *	登录成功将code返回给客户端
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping("/responseCode")
	public String rspCode(HttpServletRequest request){
		log("进入responseCode");
		try {
			//构建OAuth授权请求
			OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
			String token = oauthRequest.getParam("token");
			String state = oauthRequest.getParam("state");
		
			if (oauthRequest.getClientId()!=null&&oauthRequest.getClientId()!="") {
				//设置授权码
				String authorizationCode = UUID.randomUUID().toString().replace("-", "").substring(0, 18);
				log("生成code:"+authorizationCode);
				//利用oauth授权请求设置responseType
				OAuthASResponse.OAuthAuthorizationResponseBuilder builder=
						OAuthASResponse.authorizationResponse(request,HttpServletResponse.SC_FOUND);
				//设置授权码
				builder.setParam("token", token);
				System.out.println(state);
				builder.setParam("state", state);
				builder.setCode(authorizationCode);
				//得到客户端重定向的地址
				String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
				log("客户端回调地址:"+redirectURI);
				
				//构建响应
				OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
				String responseUri =response.getLocationUri();
				log("responseUri:"+responseUri);
	            return "redirect:"+responseUri;	
				
			}
				
			} catch (Exception e) {
		}
	 return null;	
	}
	
	/**
	 * 客户端使用code请求AccessToken
	 * @param request
	 * @return
	 * @throws OAuthSystemException
	 */
	@RequestMapping(value = "/responseAccessToken",method = RequestMethod.POST)  
	public HttpEntity token(HttpServletRequest request) throws OAuthSystemException{
	    	log("进入responseAccessToken");
			OAuthIssuer oauthIssuerImpl=null;
			 OAuthResponse response=null;
			//构建OAuth请求  
		      try {
				OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);
				String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE); 
				String clientSecret = oauthRequest.getClientSecret();
				if(clientSecret!=null||clientSecret!=""){
					//生成Access Token
		            oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
		            final String accessToken = oauthIssuerImpl.accessToken();
		            final String refreshToken = oauthIssuerImpl.refreshToken();
		            //生成OAuth响应
		            response = OAuthASResponse
		                    .tokenResponse(HttpServletResponse.SC_OK)
		                    .setAccessToken(accessToken)
		                    .setRefreshToken(refreshToken)
		                    .setParam("expires_in", "17600000") 
		                    .buildJSONMessage();
                       
		            try {
                        //这里可以将用户名和token绑定起来 ,在控制设备的时候,可以识别token对应的用户
		            	userService.updateToken(userName, accessToken);
					} catch (Exception e) {
						log(e.getMessage());
					}
				}
				log("response.getBody:"+response.getBody().toString());
	            //根据OAuthResponse生成ResponseEntity
	            return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			} catch (OAuthSystemException e) {
				response = OAuthASResponse
	                    .tokenResponse(HttpServletResponse.SC_OK)
	                    .setParam("error", "101")
	                    .setParam("error_description", "内部错误")
	                    .buildJSONMessage();
				log("错误"+response.getBody().toString());
				return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			} catch (OAuthProblemException e) {
				response = OAuthASResponse
	                    .tokenResponse(HttpServletResponse.SC_OK)
	                    .setParam("error", "102")
	                    .setParam("error_description", "参数错误")
	                    .buildJSONMessage();
				log("错误"+response.getBody().toString());
				log(OAuthURL);
				return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			}
		}
	
	
	
	
	private void log(String msg){
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
		System.out.println(df.format(new Date())+"\t"+msg);
	}	
	
	
        // 接收天猫精灵发送过来的命令,可以通过json中的namespace来区分命令类型,这里没有进行区分,只做了设备列表假数据的返回
	    @RequestMapping(value ="/getMessage",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
	    @ResponseBody
	    public List<String> getMessage(HttpServletRequest request, HttpServletResponse response,BufferedReader br)
	    {
            
	    	log("模拟智能设备进行返回");
	    	//Header部分
	    	JSONObject MerchineList = new JSONObject();
	    	JSONArray jSONArray = new JSONArray();
    	    JSONObject header = new JSONObject();
	    	JSONObject payload = new JSONObject();
	    	List<JSONObject> devices =  new ArrayList();
    	    List<JSON> properties = new ArrayList();
	    	List actions = new ArrayList();
	    	JSONObject extentions = new JSONObject();
	        log(request.getHeaderNames());
	        Enumeration<?> enum1 = request.getHeaderNames();
	        while (enum1.hasMoreElements()) {
	          String key = (String) enum1.nextElement();
	          String value = request.getHeader(key);
	          log(key + "\t" + value);
	        }
	        //body部分
	        String inputLine;
	        String str = "";
	        try {
	          while ((inputLine = br.readLine()) != null) {
	            str += inputLine;
	          }
	          br.close();
	        } catch (IOException e) {
	          log("IOException: " + e);
	        }
            log("请求参数:" + str);
	        JSONObject recieveHeader = new JSONObject();
	        recieveHeader = JSON.parseObject(str);
	        String str1 = recieveHeader.getString("header");
	        log("header:" + recieveHeader.getString("header"));
	        JSONObject recieveMessageId = new JSONObject();
	        recieveMessageId = JSON.parseObject(str1);
	        header.put("namespace", "AliGenie.Iot.Device.Discovery");
	        header.put("name", "DiscoveryDevicesResponse");
	        header.put("messageId", recieveMessageId.getString("messageId"));
	        header.put("payLoadVersion", 1);
	        
	        
	        JSONObject device = new JSONObject();
	        JSONObject propertie = new JSONObject();

	        device.put("deviceId", "34ea34cf2e63");
	        device.put("deviceName", "单孔插座");
	        device.put("deviceType", "outlet");
	        device.put("zone", "test");
	        device.put("brand", "test");
	        device.put("model", "test");
	        device.put("icon", "https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1531878000&di=c989660f4b827a0049c3b7aec4fe38e1&src=http://img.czvv.com/sell/599adfe4d2f0b1b2f118606f/20170905113247194.jpg");
      
		
	        propertie.put("name", "powerstate");
	        propertie.put("value", "off");
	        properties.add(propertie);
	        device.put("properties", properties);
	        
	        actions.add("TurnOn");
	        actions.add("TurnOff");
	        device.put("actions", actions);
	        
	        extentions.put("extension1", "tset");
	        extentions.put("extension2", "test");
	        device.put("extentions", extentions);
	        
	        devices.add(device);
	        payload.put("devices", devices);
	        
	        MerchineList.put("header", header);
	        MerchineList.put("payload", payload);
	        log(MerchineList.toString());
	        List<String> json = new ArrayList<String>();
	        json.add(MerchineList.toString());
	        return json;
	      }
	

	

	
}

4.授权服务器搭建好后,进入下面第四步,点击测试验证中帐号设置进入你自己写的H5登录授权界面

5.输入帐号密码

6.登陆成功后,你的服务器会自己调用下面的接口,然后生成code传给天猫精灵。

7.天猫精灵携带code,通过下面去请求token

8.返回token到天猫精灵,整个授权流程结束

猜你喜欢

转载自blog.csdn.net/hm283691724/article/details/83858410
今日推荐