Gb1400ServiceImpl.java 16.6 KB
package com.viontech.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.viontech.config.Gb1400Config;
import com.viontech.config.Gb1400RestTemplate;
import com.viontech.constant.Gb1400Constants;
import com.viontech.constant.Gb1400UriConstants;
import com.viontech.constant.RedisConstants;
import com.viontech.service.Gb1400Service;
import com.viontech.utils.DateUtil;
import com.viontech.utils.Gb1400ResponseUtil;
import com.viontech.utils.JsonMessage;
import com.viontech.utils.JsonMessageUtil;
import com.viontech.vo.gb1400.MotorVehicleObj;
import com.viontech.vo.gb1400.SubscribeNotificationsObj;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class Gb1400ServiceImpl implements Gb1400Service {
    @Autowired
    private Gb1400Config gb1400Config;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private Gb1400RestTemplate gb1400RestTemplate;

    @Override
    public JsonMessage registerToMySystem(String params) {
        JSONObject registerJson = JSONObject.parseObject(params);
        JSONObject registerObject = registerJson.getJSONObject("RegisterObject");
        String deviceID = registerObject.getString("DeviceID");
        redisTemplate.opsForSet().add(RedisConstants.GB1400_REGISTER_TO_MYSYSTEM_SET, deviceID);
        return JsonMessageUtil.getSuccessJsonMsg("success");
    }

    @Override
    public void register(String userIdentify) {
        registerHttp(userIdentify);
    }

    @Override
    public JsonMessage subscribes(String params) {
        if (StringUtils.isBlank(params)) {
            return JsonMessageUtil.getErrorJsonMsg("订阅对象不能为空!");
        }
        //单个订阅
        /*try {
            JSONObject paramObj = JSONObject.parseObject(params);
            if (paramObj == null) {
                return JsonMessageUtil.getErrorJsonMsg("订阅对象不能为空!");
            }
            if (StringUtils.isBlank(paramObj.getString("SubscribeID"))) {
                return JsonMessageUtil.getErrorJsonMsg("SubscribeID不能为空!");
            }
            if (!"50".equals(paramObj.getString("SubscribeDetail"))) {
                return JsonMessageUtil.getErrorJsonMsg("订阅类别暂不支持!");
            }
            String subscribeId = paramObj.getString("SubscribeID");
            redisTemplate.opsForHash().put(RedisConstants.GB1400_SUBSCRIBES_HASH, subscribeId, params);
        } catch (Exception e) {
            log.error("subscribes.Exception", e);
            return JsonMessageUtil.getErrorJsonMsg(e.getMessage());
        }*/
        List<JSONObject> list = new ArrayList<>();
        //批量订阅
        try {
            JSONObject paramObj = JSONObject.parseObject(params);
            if (paramObj == null) {
                return JsonMessageUtil.getErrorJsonMsg("订阅对象不能为空!");
            }
            JSONObject subscribeList = paramObj.getJSONObject("SubscribeListObject");
            if (subscribeList == null) {
                return JsonMessageUtil.getErrorJsonMsg("订阅对象不能为空!");
            }
            JSONArray objArr = subscribeList.getJSONArray("SubscribeObject");
            if (objArr == null || objArr.size() <= 0) {
                return JsonMessageUtil.getErrorJsonMsg("订阅对象不能为空!");
            }
            for (int i = 0; i < objArr.size(); i++) {
                JSONObject item = (JSONObject) objArr.get(i);
                if (item == null || StringUtils.isBlank(item.getString("SubscribeID"))) {
                    list.add(Gb1400ResponseUtil.buildResponseStatusObject(item.getString("SubscribeDetail"), "/VIID/Subscribes", 1, "SubscribeID不能为空"));
                    continue;
                }
//                if (!"50".equals(item.getString("SubscribeDetail"))) {
//                    list.add(Gb1400ResponseUtil.buildResponseStatusObject(item.getString("SubscribeDetail"), "/VIID/Subscribes", 1, "订阅类别暂不支持"));
//                    continue;
//                }
                String subscribeId = item.getString("SubscribeID");
//                String subscribeDetail = item.getString("SubscribeDetail");
                redisTemplate.opsForHash().put(RedisConstants.GB1400_SUBSCRIBES_HASH, subscribeId, item.toJSONString());
                list.add(Gb1400ResponseUtil.buildResponseStatusObject(subscribeId, "/VIID/Subscribes", 0, "成功"));
            }
        } catch (Exception e) {
            if (CollectionUtils.isEmpty(list)) {
                list.add(Gb1400ResponseUtil.buildResponseStatusObject(null, "/VIID/Subscribes", 1, "异常:"+e.getMessage()));
            }
            log.error("subscribes.Exception", e);
        }
        return JsonMessageUtil.getSuccessJsonMsg(list);
    }

    @Override
    public JsonMessage unSubscribes(String subscribeId, String params) {
        if (StringUtils.isBlank(subscribeId)) {
            return JsonMessageUtil.getErrorJsonMsg("SubscribeID不能为空!");
        }
        try {
            synchronized (this) {
                if (!redisTemplate.opsForHash().hasKey(RedisConstants.GB1400_SUBSCRIBES_HASH, subscribeId)) {
                    return JsonMessageUtil.getErrorJsonMsg("SubscribeID不存在无需取消订阅!");
                }
                redisTemplate.opsForHash().delete(RedisConstants.GB1400_SUBSCRIBES_HASH, subscribeId);
                redisTemplate.opsForHash().put(RedisConstants.GB1400_UNSUBSCRIBES_HASH, subscribeId, params);
            }
        } catch (Exception e) {
            log.error("unSubscribes.Exception", e);
            return JsonMessageUtil.getErrorJsonMsg(e.getMessage());
        }
        return JsonMessageUtil.getSuccessJsonMsg("success");
    }

    @Override
    public JsonMessage subscribeNotifications(SubscribeNotificationsObj subscribeNotificationsObj) {
        if (subscribeNotificationsObj == null) {
            return JsonMessageUtil.getErrorJsonMsg("SubscribeNotificationsObj不能为空!");
        }
        String notificationsData = JSONObject.toJSONString(subscribeNotificationsObj);
        String sendResult = gb1400RestTemplate.doPost(gb1400Config.getUserIdentify(), Gb1400UriConstants.SUBSCRIBENOTIFICATIONS, notificationsData);
        if (StringUtils.isBlank(sendResult)) {
            return JsonMessageUtil.getErrorJsonMsg(sendResult);
        }
        JSONObject resultObj = JSONObject.parseObject(sendResult);
        if (resultObj != null && resultObj.getJSONObject("ResponseStatusListObject") != null) {
            JSONObject resultlistObj = resultObj.getJSONObject("ResponseStatusListObject");
            if (resultlistObj != null && resultlistObj.getJSONArray("ResponseStatusObject") != null) {
                JSONArray arr = resultlistObj.getJSONArray("ResponseStatusObject");
                if (arr != null && arr.size() > 0) {
                    JSONObject item = (JSONObject) arr.get(0);
                    if (item != null && item.getInteger("StatusCode") == 0) {
                        return JsonMessageUtil.getSuccessJsonMsg("success", sendResult);
                    } else {
                        return JsonMessageUtil.getErrorJsonMsg(sendResult);
                    }
                }
            }
        }
        return JsonMessageUtil.getErrorJsonMsg(sendResult);
    }

    @Override
    public JsonMessage selectNotifications(SubscribeNotificationsObj.SubscribeNotificationObject notificationObject) {
        Map params = new HashMap();
        if (StringUtils.isNotBlank(notificationObject.getNotificationID())) {
            params.put("NotificationID", notificationObject.getNotificationID());
        }
        if (StringUtils.isNotBlank(notificationObject.getSubscribeID())) {
            params.put("SubscribeID", notificationObject.getSubscribeID());
        }
        String sendResult = gb1400RestTemplate.doGet(gb1400Config.getUserIdentify(), Gb1400UriConstants.SUBSCRIBENOTIFICATIONS, params);
        return JsonMessageUtil.getSuccessJsonMsg(sendResult);
    }

    @Override
    public JsonMessage deleteNotifications(String ids) {
        if (StringUtils.isBlank(ids)) {
            return JsonMessageUtil.getErrorJsonMsg("IDList不能为空!");
        }
        Map params = new HashMap();
        params.put("IDList", ids);
        String sendResult = gb1400RestTemplate.doDelete(gb1400Config.getUserIdentify(), Gb1400UriConstants.SUBSCRIBENOTIFICATIONS, params);
        return JsonMessageUtil.getSuccessJsonMsg(sendResult);
    }

    private String getRedisAuth(){
        Object auth = redisTemplate.opsForHash().get(RedisConstants.GB1400_REGISTER_AUTH, gb1400Config.getIpPort());
        return auth == null ? null : String.valueOf(auth);
    }

    private void registerHttp(String lkh) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.add("User-Identify", lkh);
            headers.add("Content-Type", "application/VIID+JSON;charset=utf-8");
            String redisAuth = getRedisAuth();
            if (!org.springframework.util.StringUtils.isEmpty(redisAuth)) {
                headers.add("Authorization", redisAuth);
            }
//            String currentTime = DateUtil.getCurrentTime(DateUtil.TIMESTAMP_NO_DELIMITER);
//            headers.add("User-SendTime", currentTime);
//            String content = "{\"DeviceID\":\""+lkh+"\"}";
            String content = "{\"RegisterObject\":{\"DeviceID\":\""+lkh+"\"}}";
            HttpEntity<String> entity = new HttpEntity<>(content, headers);
            String url = "http://"+gb1400Config.getIpPort()+"/VIID/System/Register";
            ResponseEntity<String> postForEntity = restTemplate.postForEntity(url, entity, String.class);
            String body = postForEntity.getBody();
            log.info("register.result[{}]:{}", lkh, body);
            //{"ResponseStatusObject":{"RequestURL":"/VIID/System/Register","StatusCode":0,"StatusString":null,"Id":null,"LocalTime":"20210202170607"}}
            JSONObject registerResult = JSONObject.parseObject(body);
            if (registerResult != null && registerResult.getJSONObject("ResponseStatusObject") != null) {
                JSONObject responseStatusObject = registerResult.getJSONObject("ResponseStatusObject");
                if (!"0".equals(responseStatusObject.getString("StatusCode"))) {
                    try {
                        TimeUnit.SECONDS.sleep(60);
                    } catch (InterruptedException e1) {
                        throw new RuntimeException(e1);
                    }
                    redisTemplate.opsForHash().delete(RedisConstants.GB1400_REGISTER_AUTH, gb1400Config.getIpPort());
                    registerHttp(lkh);
                } else {
                    Gb1400Constants.LinkStatus = true;
                }
            } else {
                try {
                    TimeUnit.SECONDS.sleep(60);
                } catch (InterruptedException e1) {
                    throw new RuntimeException(e1);
                }
                redisTemplate.opsForHash().delete(RedisConstants.GB1400_REGISTER_AUTH, gb1400Config.getIpPort());
                registerHttp(lkh);
            }
        } catch (HttpClientErrorException e) {
            int rawStatusCode = e.getRawStatusCode();
            if (rawStatusCode == 401) {
                HttpHeaders responseHeaders = e.getResponseHeaders();
                if (responseHeaders == null) {
                    throw new RuntimeException("1400 register 401 error,", e);
                }
                log.info("register.responseHeaders={}", JSONObject.toJSONString(responseHeaders));
                List<String> strings = responseHeaders.get("WWW-Authenticate");
                String auth = "";
                if (strings == null || strings.size() == 0 || org.springframework.util.StringUtils.isEmpty(strings.get(0))) {
                    throw new RuntimeException("1400 register 401 error,", e);
                } else {
                    auth = strings.get(0);
                    log.info("401auth:" + auth);
                    String authStr = getAuth(auth);
                    redisTemplate.opsForHash().put(RedisConstants.GB1400_REGISTER_AUTH, gb1400Config.getIpPort(), authStr);
                    registerHttp(lkh);
                }
            } else {
                log.error("register.HttpClientErrorException", e);
                try {
                    TimeUnit.SECONDS.sleep(60);
                } catch (InterruptedException e1) {
                    throw new RuntimeException(e1);
                }
                registerHttp(lkh);
            }
        } catch (Exception e){
            log.error("register.Exception",e);
            try {
                TimeUnit.SECONDS.sleep(60);
            } catch (InterruptedException e1) {
                throw new RuntimeException(e1);
            }
            registerHttp(lkh);
        }
    }

    private String getAuth(String digest) {
        String substring = "{" + digest.substring(7) + "}";
        String s = substring.trim().replaceAll("=", ":");
        JSONObject digestJson = JSONObject.parseObject(s);
        String qop = digestJson.getString("qop");
        String opaque = digestJson.getString("opaque");
        String realm = digestJson.getString("realm");
        String nonce = digestJson.getString("nonce");
        String cnonce = UUID.randomUUID().toString().replaceAll("-", "");
        //HA1=MD5(username:realm:password)
        String HA1 = DigestUtils.md5DigestAsHex((gb1400Config.getUsername()+":" + realm + ":"+gb1400Config.getPassword()).getBytes());
        //HA2=MD5(method:uri) and toHex
        String HA2 = DigestUtils.md5DigestAsHex(("POST:/VIID/System/Register").getBytes());
        //HD=nonce:noncecount:cnonce:qop
        String HD = nonce + ":00000001:" + cnonce + ":" + qop;
        //response=MD5(HA1:HD:HA2)
        String response = DigestUtils.md5DigestAsHex((HA1 + ":" + HD + ":" + HA2).getBytes());
        StringBuilder sb = new StringBuilder("Digest username=\"");
        sb.append(gb1400Config.getUsername()).append("\",realm=\"").append(realm).append("\", nonce=\"").append(nonce)
                .append("\", uri=\"/VIID/System/Register\", response=\"").append(response)
                .append("\", opaque=\"").append(opaque).append("\", qop=\"").append(qop)
                .append("\", nc=00000001, cnonce=\"").append(cnonce).append("\"");
        return sb.toString();
    }

    public static void main(String[] args) {
        SubscribeNotificationsObj subscribeNotificationsObj = new SubscribeNotificationsObj();
        SubscribeNotificationsObj.SubscribeNotificationListObject subscribeNotificationListObject = new SubscribeNotificationsObj.SubscribeNotificationListObject();
        List<SubscribeNotificationsObj.SubscribeNotificationObject> subscribeNotificationObjects = new ArrayList<>();

        SubscribeNotificationsObj.SubscribeNotificationObject obj1 = new SubscribeNotificationsObj.SubscribeNotificationObject();

        obj1.setTitle("测试tile");
        obj1.setNotificationID("123456");
        obj1.setSubscribeID("789");

        MotorVehicleObj motorVehicleObjectList = new MotorVehicleObj();
        List<MotorVehicleObj.MotorVehicleObject> motorVehicleList = new ArrayList<>();

        MotorVehicleObj.MotorVehicleObject motorVehicle = new MotorVehicleObj.MotorVehicleObject();
        motorVehicle.setDeviceID("ididi123");
        motorVehicle.setLaneNo(2);
        motorVehicle.setBreakRuleMode("17170");
        motorVehicleList.add(motorVehicle);

        MotorVehicleObj.MotorVehicleObject motorVehicle2 = new MotorVehicleObj.MotorVehicleObject();
        motorVehicle2.setDeviceID("nsl123");
        motorVehicle2.setLaneNo(1);
        motorVehicleList.add(motorVehicle2);

        motorVehicleObjectList.setMotorVehicleObject(motorVehicleList);

        obj1.setMotorVehicleObjectList(motorVehicleObjectList);

        subscribeNotificationObjects.add(obj1);
        subscribeNotificationListObject.setSubscribeNotificationObjects(subscribeNotificationObjects);
        subscribeNotificationsObj.setSubscribeNotificationListObject(subscribeNotificationListObject);

        log.info(JSONObject.toJSONString(subscribeNotificationsObj));
    }
}