Pu Zhibing
2025-11-25 333ddc9a4f963237b6f3da3565cbbb0f7aec9e80
新增加成都监管对接代码
15个文件已添加
3个文件已修改
1821 ■■■■■ 已修改文件
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/ChengDuJianGuanUtil.java 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDEquipmentInfo.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDOrderInfo.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDStationInfo.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ChargeFeeDetail.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ConnectorChargeStatusInfo.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/EDIMessagePack.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/NotificationStationFee.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Cryptos.java 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Digests.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Encodes.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Exceptions.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/GBSignUtils.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/HttpRequestUtil.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/SignUtils.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorInfo.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorStatusInfo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/StationInfo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/ChengDuJianGuanUtil.java
New file
@@ -0,0 +1,402 @@
package com.ruoyi.integration.chengdujianguan;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.ruoyi.integration.chengdujianguan.model.*;
import com.ruoyi.integration.chengdujianguan.util.Cryptos;
import com.ruoyi.integration.chengdujianguan.util.Encodes;
import com.ruoyi.integration.chengdujianguan.util.GBSignUtils;
import com.ruoyi.integration.chengdujianguan.util.HttpRequestUtil;
import com.ruoyi.integration.drainage.model.ConnectorInfo;
import com.ruoyi.integration.drainage.model.ConnectorStatusInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ChengDuJianGuanUtil {
    private static String OperatorID = "987654321";
    private static String OperatorSecret = "1234567890abcdef";    // 运营商秘钥
    private static String SigSecret = "1234567890abcdef";              // 签名秘钥
    private static String DataSecret = "1234567890abcdef";           // 消息密钥
    private static String DataSecretIV = "1234567890abcdef";        // 消息密钥初始化向量
    private static String requestUrl = "http://testdataexchange.evchargeonline.com:82/shevcs/v1";
    public static void main(String[] args) {
        CDStationInfo stationInfo = new CDStationInfo();
        stationInfo.setStationID("241231001");
        stationInfo.setOperatorID("906171535");
        stationInfo.setEquipmentOwnerID("M01234567");
        stationInfo.setStationName("灵泉大道充电站");
        stationInfo.setIsAloneApply(1);
        stationInfo.setAccountNumber("0110042963");
        stationInfo.setCountryCode("CN");
        stationInfo.setAreaCode("510903");
        stationInfo.setAreaCodeCountryside("510903000000");
        stationInfo.setAddress("灵泉大道中国石化僧家沟加油站B区旁边前进150米");
        stationInfo.setServiceTel("18081278695");
        stationInfo.setStationType(1);
        stationInfo.setStationStatus(50);
        stationInfo.setParkNums(10);
        stationInfo.setStationLng(new BigDecimal(105.616058));
        stationInfo.setStationLat(new BigDecimal(30.527943));
        stationInfo.setConstruction(8);
        stationInfo.setOpenAllDay(1);
        stationInfo.setElectricityFee("{\"00:00-07:00\":\"0.42\",\n" +
                "\"07:00-10:00\":\"0.49\",\n" +
                "\"10:00-12:00\":\"0.52\",\n" +
                "\"12:00-15:00\":\"0.49\",\n" +
                "\"15:00-21:00\":\"0.52\",\n" +
                "\"21:00-23:00\":\"0.49\",\n" +
                "\"23:00-00:00\":\"0.42\"}");
        stationInfo.setServiceFee("{\"00:00-07:00\":\"0.42\",\n" +
                "\"07:00-10:00\":\"0.49\",\n" +
                "\"10:00-12:00\":\"0.52\",\n" +
                "\"12:00-15:00\":\"0.49\",\n" +
                "\"15:00-21:00\":\"0.52\",\n" +
                "\"21:00-23:00\":\"0.49\",\n" +
                "\"23:00-00:00\":\"0.42\"}");
        stationInfo.setParkFeeType(3);
        stationInfo.setToiletFlag(0);
        stationInfo.setStoreFlag(0);
        stationInfo.setLoungeFlag(0);
        stationInfo.setCanopyFlag(0);
        stationInfo.setPrinterFlag(0);
        stationInfo.setBarrierFlag(1);
        stationInfo.setParkingLockFlag(0);
        stationInfo.setIsDemandResponse(1);
        stationInfo.setIsSupportOrderlyCharging(1);
        stationInfo.setIsEnergyStorage(0);
        stationInfo.setElectricityType(3);
        stationInfo.setRatedPower(new BigDecimal(600));
        stationInfo.setPeriodFee(1);
        stationInfo.setOfficialRunTime("2024-12-31");
        stationInfo.setVideoMonitor(1);
        List<CDEquipmentInfo> equipmentInfos1 = new ArrayList<>();
        CDEquipmentInfo cdEquipmentInfo = new CDEquipmentInfo();
        cdEquipmentInfo.setEquipmentID("2024123100001001");
        cdEquipmentInfo.setManufacturerID("12345");
        cdEquipmentInfo.setManufacturerName("12345");
        cdEquipmentInfo.setEquipmentModel("123");
        cdEquipmentInfo.setEquipmentProductCode("12345");
        cdEquipmentInfo.setConstructionTime("2024-12-31");
        cdEquipmentInfo.setEquipmentType(1);
        cdEquipmentInfo.setEquipmentStatus(50);
        cdEquipmentInfo.setEquipmentPurpose(1);
        cdEquipmentInfo.setEquipmentPower(new BigDecimal(120));
        cdEquipmentInfo.setNewNationalStandard(1);
        cdEquipmentInfo.setVinFlag(0);
        List<ConnectorInfo> connectorInfos = new ArrayList<>();
        ConnectorInfo connectorInfo = new ConnectorInfo();
        connectorInfo.setConnectorID("202412310000100101");
        connectorInfo.setConnectorName("1号桩01枪");
        connectorInfo.setConnectorType(4);
        connectorInfo.setVoltageUpperLimits(new BigDecimal(380));
        connectorInfo.setVoltageLowerLimits(new BigDecimal(220));
        connectorInfo.setCurrent(120);
        connectorInfo.setPower(new BigDecimal(250));
        connectorInfo.setNationalStandard(2);
        connectorInfo.setAuxPower(1);
        connectorInfo.setOpreateStatus(50);
        connectorInfos.add(connectorInfo);
        cdEquipmentInfo.setConnectorInfos(connectorInfos);
        equipmentInfos1.add(cdEquipmentInfo);
        stationInfo.setEquipmentInfos1(equipmentInfos1);
        ChengDuJianGuanUtil.notificationStationInfo(null, stationInfo);
    }
    /**
     * 请求联联,获取token
     */
    public static String getToken(RedisTemplate redisTemplate) {
        try {
//            Object o = redisTemplate.opsForValue().get("LLTOKEN");
//            if(null != o){
//                return o.toString();
//            }
            // 请求data
            Map<String, String> data = new HashMap<>();
            data.put("OperatorID", OperatorID);
            data.put("OperatorSecret", OperatorSecret);
            String dataJson = JacksonUtils.toJson(data);
            // 加密
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            // 生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String tokenRequest = JacksonUtils.toJson(request);
            log.info("【成都监管-获取token】请求参数明文:" + dataJson);
            log.info("【成都监管-获取token】请求参数密文:" + tokenRequest);
            String response = HttpUtil.post(requestUrl + "/query_token", tokenRequest);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            log.info("【成都监管-获取token】响应参数密文:" + response);
            if (result.getRet() == 0) {
                //解密data
                byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64((String) result.getData()),
                        DataSecret.getBytes(), DataSecretIV.getBytes());
                String dataStr = new String(plainText, "UTF-8");
                log.info("【成都监管-获取token】响应参数明文:" + dataStr);
                JSONObject jsonObject = JSON.parseObject(dataStr);
                Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
                String accessToken = jsonObject.getString("AccessToken");
                Long tokenAvailableTime = jsonObject.getLong("TokenAvailableTime");
//                redisTemplate.opsForValue().set("LLTOKEN", accessToken, Long.valueOf(tokenAvailableTime), TimeUnit.SECONDS);
                return accessToken;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("【成都监管-获取token】获取Token异常", e);
        }
        return null;
    }
    /**
     * 充电站信息变化推送
     * @param redisTemplate
     * @param stationInfo
     */
    public static void notificationStationInfo(RedisTemplate redisTemplate, CDStationInfo stationInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("StationInfo", stationInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-充电站信息变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-充电站信息变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationInfo", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-充电站信息变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-充电站信息变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-充电站信息变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-充电站信息变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 站点费率变化推送
     * @param redisTemplate
     * @param notificationStationFee
     */
    public static void notificationStationFee(RedisTemplate redisTemplate, NotificationStationFee notificationStationFee){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("StationFee", notificationStationFee);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-站点费率变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-站点费率变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationFee", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-站点费率变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-站点费率变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-站点费率变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 设备状态变化推送
     * @param redisTemplate
     * @param connectorStatusInfo
     */
    public static void notificationStationStatus(RedisTemplate redisTemplate, ConnectorStatusInfo connectorStatusInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ConnectorStatusInfo", connectorStatusInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-设备状态变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-设备状态变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_stationStatus", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-设备状态变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-设备状态变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-设备状态变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 设备充电中状态变化推送
     * @param redisTemplate
     * @param connectorChargeStatusInfo
     */
    public static void notificationConnectorChargeStatus(RedisTemplate redisTemplate, ConnectorChargeStatusInfo connectorChargeStatusInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ConnectorChargeStatusInfo", connectorChargeStatusInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-设备充电中状态变化推送】请求参数明文:" + dataJson);
            log.info("【成都监管-设备充电中状态变化推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_connector_charge_status", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-设备充电中状态变化推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-设备充电中状态变化推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-设备充电中状态变化推送】异常:" + e.getMessage());
        }
    }
    /**
     * 订单信息推送
     * @param redisTemplate
     * @param orderInfo
     */
    public static void notificationOrderInfo(RedisTemplate redisTemplate, CDOrderInfo orderInfo){
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ConnectorStatusInfo", orderInfo);
            String dataJson = JacksonUtils.toJson(jsonObject);
            byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes("UTF-8"),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String strData = Encodes.encodeBase64(encryptText);
            Map<String, String> request = new LinkedHashMap<>();
            request.put("OperatorID", OperatorID);
            request.put("Data", strData);
            request.put("TimeStamp", System.currentTimeMillis() + "");
            request.put("Seq", "0001");
            //生成签名
            String sig = GBSignUtils.sign(request, SigSecret);
            request.put("Sig", sig);
            String notifyStartResult = JacksonUtils.toJson(request);
            log.info("【成都监管-订单信息推送】请求参数明文:" + dataJson);
            log.info("【成都监管-订单信息推送】请求参数密文:" + notifyStartResult);
            String response = HttpRequestUtil.httpPost(requestUrl + "/notification_orderInfo", notifyStartResult, "Bearer " + getToken(redisTemplate));
            log.info("【成都监管-订单信息推送】响应参数密文:" + response);
            EDIMessagePack result = JacksonUtils.toObj(response, EDIMessagePack.class);
            if(0 != result.getRet()){
                log.info("【成都监管-站点费率变化推送】失败:", result.getMsg());
                return;
            }
            String rData = result.getData().toString();
            byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
                    DataSecret.getBytes(), DataSecretIV.getBytes());
            String plainData = new String(plainText, "UTF-8");
            log.info("【成都监管-订单信息推送】响应参数明文:" + plainData);
        }catch (Exception e){
            e.printStackTrace();
            log.info("【成都监管-订单信息推送】异常:" + e.getMessage());
        }
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDEquipmentInfo.java
New file
@@ -0,0 +1,67 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.ConnectorInfo;
import com.ruoyi.integration.drainage.model.EquipmentInfo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class CDEquipmentInfo extends EquipmentInfo {
    /**
     * 设备出厂编码
     */
    @JsonProperty("EquipmentProductCode")
    private String equipmentProductCode;
    /**
     * 建设时间
     * yyyy-MM-dd
     */
    @JsonProperty("ConstructionTime")
    private String constructionTime;
    /**
     * 设备状态
     * 0:未知
     * 1:建设中
     * 5:关闭下线
     * 6:维护中
     * 50:正常使用
     */
    @JsonProperty("EquipmentStatus")
    private Integer equipmentStatus;
    /**
     * 设备用途
     * 1:公共
     * 50:个人
     * 100:公交(专用)
     * 101:环卫(专用)
     * 102:物流(专用)
     * 103:出租车(专用)
     * 104:分时租赁(专用)
     * 106:单位(专用)
     * 107:移动站点(移动储能设备)
     * 108:居民小区(公共)
     * 109:居民小区(专用)
     */
    @JsonProperty("EquipmentPurpose")
    private Integer equipmentPurpose;
    /**
     * 额定功率
     */
    @JsonProperty("EquipmentPower")
    private BigDecimal equipmentPower;
    /**
     * 新国标
     * 0:否,1:是
     */
    @JsonProperty("NewNationalStandard")
    private Integer newNationalStandard;
    /**
     * 是否支持VIN码识别
     * 0:否,1:是
     */
    @JsonProperty("VinFlag")
    private Integer vinFlag;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDOrderInfo.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.ChargeDetail;
import com.ruoyi.integration.drainage.model.SupChargeOrderInfo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class CDOrderInfo extends SupChargeOrderInfo {
    /**
     * 充电订单号
     */
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 用户发起充电类型
     * 1:非蓉城充启动
     * 2:卡启动
     * 3:蓉城充启动
     * 10:其他
     */
    @JsonProperty("UserChargeType")
    private Integer userChargeType;
    /**
     * 用户手机号
     */
    @JsonProperty("MobileNumber")
    private String mobileNumber;
    /**
     * 本次充电消费总金额
     */
    @JsonProperty("Money")
    private BigDecimal money;
    /**
     * 本次充电电费总金额
     */
    @JsonProperty("ElectMoney")
    private BigDecimal electMoney;
    /**
     * 本次充电服务费总金额
     */
    @JsonProperty("ServiceMoney")
    private BigDecimal serviceMoney;
    /**
     * 本次充电电量
     */
    @JsonProperty("Elect")
    private BigDecimal elect;
    /**
     * 本次充放电开始时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 本次充放电开始时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 支付金额
     */
    @JsonProperty("PaymentAmount")
    private BigDecimal paymentAmount;
    /**
     * 支付方式
     * 1:支付宝
     * 2:微信支付
     * 3:交通卡
     * 4:预充卡
     * 5:银联
     * 6:其他自定义
     */
    @JsonProperty("PayChannel")
    private Integer payChannel;
    /**
     * 结束充电原因
     * 0:用户手动停止充电
     * 1:客户归属运营商平台停止充电
     * 2:BMS停止充电
     * 3:充电机设备故障
     * 4:连接器断开
     * 5-99:自定义
     */
    @JsonProperty("StopReason")
    private Integer stopReason;
    /**
     * 接口额定功率
     */
    @JsonProperty("Power")
    private BigDecimal power;
    /**
     * 充电时长 秒
     */
    @JsonProperty("ChargeLast")
    private Integer chargeLast;
    /**
     * 电表总起值
     */
    @JsonProperty("MeterValueStart")
    private BigDecimal meterValueStart;
    /**
     * 电表总止值
     */
    @JsonProperty("MeterValueEnd")
    private BigDecimal meterValueEnd;
    /**
     * 充电明细信息
     */
    @JsonProperty("ChargeDetails")
    private ChargeDetail chargeDetails;
    /**
     * 推送时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("PushTimeStamp")
    private String pushTimeStamp;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/CDStationInfo.java
New file
@@ -0,0 +1,103 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.model.EquipmentInfo;
import com.ruoyi.integration.drainage.model.StationInfo;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
@Data
public class CDStationInfo extends StationInfo {
    /**
     * 是否独立报桩
     * 0否,1是
     */
    @JsonProperty("IsAloneApply")
    private Integer isAloneApply;
    /**
     * 户号
     * 国家电网账单户号
     */
    @JsonProperty("AccountNumber")
    private String accountNumber;
    /**
     * 是否全天开放
     * 0:否,1:是
     */
    @JsonProperty("OpenAllDay")
    private Integer openAllDay;
    /**
     * 听测收费类型
     * 0:停车收费
     * 1:停车免费
     * 2:限时免费
     * 3:充电限免
     */
    @JsonProperty("ParkFeeType")
    private Integer parkFeeType;
    /**
     * 是否配备卫生间
     * 0:无,1:有
     */
    @JsonProperty("ToiletFlag")
    private Integer toiletFlag;
    /**
     * 是否配备便利店
     * 0:无,1:有
     */
    @JsonProperty("StoreFlag")
    private Integer storeFlag;
    /**
     * 是否配备休息室
     * 0:无,1:有
     */
    @JsonProperty("LoungeFlag")
    private Integer loungeFlag;
    /**
     * 是否配备雨棚
     * 0:无,1:有
     */
    @JsonProperty("CanopyFlag")
    private Integer canopyFlag;
    /**
     * 是否有道闸
     * 0:无,1:有
     */
    @JsonProperty("BarrierFlag")
    private Integer barrierFlag;
    /**
     * 是否有地锁
     * 0:无,1:有
     */
    @JsonProperty("ParkingLockFlag")
    private Integer parkingLockFlag;
    /**
     * 是否参与需求响应
     * 0:无,1:有
     */
    @JsonProperty("IsDemandResponse")
    private Integer isDemandResponse;
    /**
     * 有序充电场站
     * 0:无,1:有
     */
    @JsonProperty("IsSupportOrderlyCharging")
    private Integer isSupportOrderlyCharging;
    /**
     * 是否有储能设施
     * 0:无,1:有
     */
    @JsonProperty("IsEnergyStorage")
    private Integer isEnergyStorage;
    /**
     * 充电设备信息列表
     */
    @NotNull
    @JsonProperty("EquipmentInfos")
    private List<CDEquipmentInfo> equipmentInfos1;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ChargeFeeDetail.java
New file
@@ -0,0 +1,41 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ChargeFeeDetail {
    /**
     * 设备类型
     * 1:直流设备
     * 2:交流设备
     * 3:交直流一体设备
     */
    @JsonProperty("EquipmentType")
    private Integer equipmentType;
    /**
     * 计费开始时间
     * 00:00
     */
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 计费结束时间
     * 00:00
     */
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 电费
     */
    @JsonProperty("ElectricityFee")
    private BigDecimal electricityFee;
    /**
     * 服务费
     */
    @JsonProperty("ServiceFee")
    private BigDecimal serviceFee;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/ConnectorChargeStatusInfo.java
New file
@@ -0,0 +1,129 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ConnectorChargeStatusInfo {
    /**
     * 运营平台ID
     */
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 产权所属单位ID
     */
    @JsonProperty("EquipmentOwnerID")
    private String equipmentOwnerID;
    /**
     * 充电站ID
     */
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 充电设备编码
     */
    @JsonProperty("EquipmentID")
    private String equipmentID;
    /**
     * 充电订单号
     */
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电设备接口编码
     */
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口状态
     * 1:空闲
     * 2:占用(未充电)
     * 3:占用(充电中)
     * 4:占用(预约锁定)
     * 5:占用(放电中)
     * 255:故障
     */
    @JsonProperty("ConnectorStatus")
    private Integer connectorStatus;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:充放电完成
     * 5:订单挂起
     * 6:充电异常结束
     * 7:启动失败
     * 8:放电中
     */
    @JsonProperty("OrderStatus")
    private Integer orderStatus;
    /**
     * A相电流
     */
    @JsonProperty("CurrentA")
    private BigDecimal currentA;
    /**
     * A相电压
     */
    @JsonProperty("VoltageA")
    private BigDecimal voltageA;
    /**
     * 电池剩余电量
     */
    @JsonProperty("Soc")
    private BigDecimal soc;
    /**
     * 开始充电时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 结束充电时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 本次推送时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("PushTime")
    private String pushTime;
    /**
     * 上次推送时间
     * yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("LastPushTime")
    private String lastPushTime;
    /**
     * 累计充电量
     */
    @JsonProperty("TotalPower")
    private BigDecimal totalPower;
    /**
     * 累计电费
     */
    @JsonProperty("ElecMoney")
    private BigDecimal elecMoney;
    /**
     * 累计服务费
     */
    @JsonProperty("SeviceMoney")
    private BigDecimal seviceMoney;
    /**
     * 累计总金额
     */
    @JsonProperty("TotalMoney")
    private BigDecimal totalMoney;
    /**
     * 电池剩余电量
     */
    @JsonProperty("SOC")
    private BigDecimal soc1;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/EDIMessagePack.java
New file
@@ -0,0 +1,41 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Map;
/**
 * 返回结果
 *
 * @author 联联充电
 *
 */
@Data
public class EDIMessagePack {
    /**
     * 系统错误码
     */
    @JsonProperty("Ret")
    int ret = 0;
    /**
     * 返回提示信息
     */
    @JsonProperty("Msg")
    String msg = "";
    /**
     * 返回结果
     */
    @JsonProperty("Data")
    Object data;
    /**
     * 签名
     */
    @JsonProperty("Sig")
    String sig;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/model/NotificationStationFee.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.integration.chengdujianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class NotificationStationFee {
    /**
     * 运营平台ID
     */
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 充电站ID
     */
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 费率详情
     */
    @JsonProperty("ChargeFeeDetail")
    private List<ChargeFeeDetail> chargeFeeDetail;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Cryptos.java
New file
@@ -0,0 +1,248 @@
/**
 */
package com.ruoyi.integration.chengdujianguan.util;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Arrays;
public class Cryptos {
    private static final String AES = "AES";
    private static final String AES_CBC = "AES/CBC/PKCS5Padding";
    private static final String HMACSHA1 = "HmacSHA1";
    private static final String DEFAULT_URL_ENCODING = "UTF-8";
    private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
    private static final int DEFAULT_AES_KEYSIZE = 128;
    private static final int DEFAULT_IVSIZE = 16;
    private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
    private static SecureRandom random = new SecureRandom();
    //-- HMAC-SHA1 funciton --//
    /**
     * 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
     *
     * @param input 原始输入字符数组
     * @param key HMAC-SHA1密钥
     */
    public static byte[] hmacSha1(byte[] input, byte[] key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
            Mac mac = Mac.getInstance(HMACSHA1);
            mac.init(secretKey);
            return mac.doFinal(input);
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * 校验HMAC-SHA1签名是否正确.
     *
     * @param expected 已存在的签名
     * @param input 原始输入字符串
     * @param key 密钥
     */
    public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
        byte[] actual = hmacSha1(input, key);
        return Arrays.equals(expected, actual);
    }
    /**
     * 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节).
     * HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节).
     */
    public static byte[] generateHmacSha1Key() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1);
            keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    //-- AES funciton --//
    /**
     * 使用AES加密原始字符串.
     *
     * @param input 原始输入字符数组
     */
    public static String aesEncrypt(String input) {
        try {
            return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
    /**
     * 使用AES加密原始字符串.
     *
     * @param input 原始输入字符数组
     * @param key 符合AES要求的密钥
     */
    public static String aesEncrypt(String input, String key) {
        try {
            return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
    /**
     * 使用AES加密原始字符串.
     *
     * @param input 原始输入字符数组
     * @param key 符合AES要求的密钥
     */
    public static byte[] aesEncrypt(byte[] input, byte[] key) {
        return aes(input, key, Cipher.ENCRYPT_MODE);
    }
    /**
     * 使用AES加密原始字符串.
     *
     * @param input 原始输入字符数组
     * @param key 符合AES要求的密钥
     * @param iv 初始向量
     */
    public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
        return aes(input, key, iv, Cipher.ENCRYPT_MODE);
    }
    /**
     * 使用AES解密字符串, 返回原始字符串.
     *
     * @param input Hex编码的加密字符串
     */
    public static String aesDecrypt(String input) {
        try {
            return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
    /**
     * 使用AES解密字符串, 返回原始字符串.
     *
     * @param input Hex编码的加密字符串
     * @param key 符合AES要求的密钥
     */
    public static String aesDecrypt(String input, String key) {
        try {
            return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
    /**
     * 使用AES解密字符串, 返回原始字符串.
     *
     * @param input Hex编码的加密字符串
     * @param key 符合AES要求的密钥
     */
    public static byte[] aesDecrypt(byte[] input, byte[] key) {
        return aes(input, key, Cipher.DECRYPT_MODE);
    }
    /**
     * 使用AES解密字符串, 返回原始字符串.
     *
     * @param input Hex编码的加密字符串
     * @param key 符合AES要求的密钥
     * @param iv 初始向量
     */
    public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
        return aes(input, key, iv, Cipher.DECRYPT_MODE);
    }
    /**
     * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
     *
     * @param input 原始字节数组
     * @param key 符合AES要求的密钥
     * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
     */
    private static byte[] aes(byte[] input, byte[] key, int mode) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(mode, secretKey);
            return cipher.doFinal(input);
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
     *
     * @param input 原始字节数组
     * @param key 符合AES要求的密钥
     * @param iv 初始向量
     * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
     */
    private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, AES);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            Cipher cipher = Cipher.getInstance(AES_CBC);
            cipher.init(mode, secretKey, ivSpec);
            return cipher.doFinal(input);
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
     */
    public static String generateAesKeyString() {
        return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
    }
    /**
     * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
     */
    public static byte[] generateAesKey() {
        return generateAesKey(DEFAULT_AES_KEYSIZE);
    }
    /**
     * 生成AES密钥,可选长度为128,192,256位.
     */
    public static byte[] generateAesKey(int keysize) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
            keyGenerator.init(keysize);
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
     */
    public static byte[] generateIV() {
        byte[] bytes = new byte[DEFAULT_IVSIZE];
        random.nextBytes(bytes);
        return bytes;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Digests.java
New file
@@ -0,0 +1,113 @@
/**
 */
package com.ruoyi.integration.chengdujianguan.util;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
public class Digests {
    private static final String SHA1 = "SHA-1";
    private static final String MD5 = "MD5";
    private static SecureRandom random = new SecureRandom();
    /**
     * 对输入字符串进行md5散列.
     */
    public static byte[] md5(byte[] input) {
        return digest(input, MD5, null, 1);
    }
    public static byte[] md5(byte[] input, int iterations) {
        return digest(input, MD5, null, iterations);
    }
    /**
     * 对输入字符串进行sha1散列.
     */
    public static byte[] sha1(byte[] input) {
        return digest(input, SHA1, null, 1);
    }
    public static byte[] sha1(byte[] input, byte[] salt) {
        return digest(input, SHA1, salt, 1);
    }
    public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
        return digest(input, SHA1, salt, iterations);
    }
    /**
     * 对字符串进行散列, 支持md5与sha1算法.
     */
    private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            if (salt != null) {
                digest.update(salt);
            }
            byte[] result = digest.digest(input);
            for (int i = 1; i < iterations; i++) {
                digest.reset();
                result = digest.digest(result);
            }
            return result;
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * 生成随机的Byte[]作为salt.
     *
     * @param numBytes byte数组的大小
     */
    public static byte[] generateSalt(int numBytes) {
        Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
        byte[] bytes = new byte[numBytes];
        random.nextBytes(bytes);
        return bytes;
    }
    /**
     * 对文件进行md5散列.
     */
    public static byte[] md5(InputStream input) throws IOException {
        return digest(input, MD5);
    }
    /**
     * 对文件进行sha1散列.
     */
    public static byte[] sha1(InputStream input) throws IOException {
        return digest(input, SHA1);
    }
    private static byte[] digest(InputStream input, String algorithm) throws IOException {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            int bufferLength = 8 * 1024;
            byte[] buffer = new byte[bufferLength];
            int read = input.read(buffer, 0, bufferLength);
            while (read > -1) {
                messageDigest.update(buffer, 0, read);
                read = input.read(buffer, 0, bufferLength);
            }
            return messageDigest.digest();
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Encodes.java
New file
@@ -0,0 +1,142 @@
/**
 * Copyright (c) 2005-2012 springside.org.cn
 */
package com.ruoyi.integration.chengdujianguan.util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class Encodes {
    private static final String DEFAULT_URL_ENCODING = "UTF-8";
    private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
    /**
     * Hex编码.
     */
    public static String encodeHex(byte[] input) {
        return new String(Hex.encodeHex(input));
    }
    /**
     * Hex解码.
     */
    public static byte[] decodeHex(String input) {
        try {
            return Hex.decodeHex(input.toCharArray());
        } catch (DecoderException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * Base64编码.
     */
    public static String encodeBase64(byte[] input) {
        return new String(Base64.encodeBase64(input));
    }
    /**
     * Base64编码.
     */
    public static String encodeBase64(String input) {
        try {
            return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
//    /**
//     * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
//     */
//    public static String encodeUrlSafeBase64(byte[] input) {
//        return Base64.encodeBase64URLSafe(input);
//    }
    /**
     * Base64解码.
     */
    public static byte[] decodeBase64(String input) {
        return Base64.decodeBase64(input.getBytes());
    }
    /**
     * Base64解码.
     */
    public static String decodeBase64String(String input) {
        try {
            return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }
    /**
     * Base62编码。
     */
    public static String encodeBase62(byte[] input) {
        char[] chars = new char[input.length];
        for (int i = 0; i < input.length; i++) {
            chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
        }
        return new String(chars);
    }
    /**
     * Html 转码.
     */
    public static String escapeHtml(String html) {
        return StringEscapeUtils.escapeHtml4(html);
    }
    /**
     * Html 解码.
     */
    public static String unescapeHtml(String htmlEscaped) {
        return StringEscapeUtils.unescapeHtml4(htmlEscaped);
    }
    /**
     * Xml 转码.
     */
    public static String escapeXml(String xml) {
        return StringEscapeUtils.escapeXml10(xml);
    }
    /**
     * Xml 解码.
     */
    public static String unescapeXml(String xmlEscaped) {
        return StringEscapeUtils.unescapeXml(xmlEscaped);
    }
    /**
     * URL 编码, Encode默认为UTF-8.
     */
    public static String urlEncode(String part) {
        try {
            return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * URL 解码, Encode默认为UTF-8.
     */
    public static String urlDecode(String part) {
        try {
            return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw Exceptions.unchecked(e);
        }
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/Exceptions.java
New file
@@ -0,0 +1,72 @@
package com.ruoyi.integration.chengdujianguan.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
 * 关于异常的工具类.
 */
public class Exceptions {
    private static Logger logger = LoggerFactory.getLogger(Exceptions.class);
    /**
     * 将CheckedException转换为UncheckedException.
     */
    public static RuntimeException unchecked(Exception e) {
        if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        } else {
            return new RuntimeException(e);
        }
    }
    /**
     * 将ErrorStack转化为String.
     */
    public static String getStackTraceAsString(Throwable e) {
        if (e == null) {
            return "";
        }
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
    }
    /**
     * 判断异常是否由某些底层的异常引起.
     */
    public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
        Throwable cause = ex.getCause();
        while (cause != null) {
            for (Class<? extends Exception> causeClass : causeExceptionClasses) {
                if (causeClass.isInstance(cause)) {
                    return true;
                }
            }
            cause = cause.getCause();
        }
        return false;
    }
    /**
     * 在request中获取异常类
     *
     * @param request
     * @return
     */
    public static Throwable getThrowable(HttpServletRequest request) {
        Throwable ex = null;
        if (request.getAttribute("exception") != null) {
            ex = (Throwable) request.getAttribute("exception");
        } else if (request.getAttribute("javax.servlet.error.exception") != null) {
            ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
        }
        return ex;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/GBSignUtils.java
New file
@@ -0,0 +1,58 @@
package com.ruoyi.integration.chengdujianguan.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Map;
public class GBSignUtils {
    public static final Logger logger = LoggerFactory.getLogger(GBSignUtils.class);
    public static String sign(Map<String, String> paramValues, String secret) {
        try {
            StringBuilder sb = new StringBuilder();
            for (String value : paramValues.values()) {
                if (StringUtils.isNotBlank(value)) {
                    sb.append(value);
                }
            }
            logger.debug("需要签名的内容:{},密钥{}", sb.toString(), secret);
            System.out.println("需要签名的内容:" + sb.toString() + ",密钥" + secret);
            byte[] md5Digest = HmacMD5Encrypt(sb.toString(), secret);
            String result = Encodes.encodeHex(md5Digest).toUpperCase();
            logger.debug("HmacSHA1的签名内容:{}", result);
            System.out.println("HmacSHA1的签名内容:" + result);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("数据签名出错", e);
        }
    }
    /**
     * 使用 HMAC-MD5 签名方法对对encryptText进行签名
     *
     * @param encryptText 被签名的字符串
     * @param encryptKey  密钥
     * @return
     * @throws Exception
     */
    public static byte[] HmacMD5Encrypt(String encryptText, String encryptKey) throws Exception {
        byte[] data = encryptKey.getBytes("UTF-8");
        // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        SecretKey secretKey = new SecretKeySpec(data, "HmacMD5");
        // 生成一个指定 Mac 算法 的 Mac 对象
        Mac mac = Mac.getInstance("HmacMD5");
        // 用给定密钥初始化 Mac 对象
        mac.init(secretKey);
        byte[] text = encryptText.getBytes("UTF-8");
        // 完成 Mac 操作
        return mac.doFinal(text);
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/HttpRequestUtil.java
New file
@@ -0,0 +1,85 @@
package com.ruoyi.integration.chengdujianguan.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
/**
 * @author 联联充电
 */
@Slf4j
@SuppressWarnings(value = "unused")
public class HttpRequestUtil {
    /**
     * httpClient--post请求--http
     *
     * @param url
     * @param json
     * @return
     */
    public static String httpPost(String url, String json, String token) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        try {
            //创建httpPost
            HttpPost httpPost = new HttpPost(url);
            //设置Content-Type
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", token);
            //写入json数据
            httpPost.setEntity(new StringEntity(json));
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(50000)
                    .setConnectionRequestTimeout(50000)
                    .setSocketTimeout(50000)
                    .build();
            httpPost.setConfig(requestConfig);
            //发起请求,获取response对象
            response = httpClient.execute(httpPost);
            //获取结果状态码
            int resultCode = response.getStatusLine().getStatusCode();
            if (resultCode == 200) {
                //获取返回数据实体对象
                HttpEntity entity = response.getEntity();
                //转化为字符串
                String result = EntityUtils.toString(entity, "UTF-8");
                //封装统一的返回数据接收类
                //ResponseMsg responseMsg = (ResponseMsg) JSON.parse(result);
                return result;
            } else {
                log.info("http请求失败");
            }
        } catch (Exception e) {
            log.info("http请求异常");
        } finally {
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                log.info(e.getMessage(), e);
            }
        }
        return null;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/chengdujianguan/util/SignUtils.java
New file
@@ -0,0 +1,116 @@
package com.ruoyi.integration.chengdujianguan.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.*;
public class SignUtils {
    private static String UTF_8 = "UTF-8";
    /**
     * 使用<code>secret</code>对paramValues按以下算法进行签名: <br/>
     * uppercase(hex(sha1(secretkey1value1key2value2...secret))
     *
     * @param paramValues
     *            参数列表
     * @param secret
     * @return
     */
    public static String sign(Map<String, String> paramValues, String secret) {
        return sign(paramValues, null, secret);
    }
    /**
     * 对paramValues进行签名,其中ignoreParamNames这些参数不参与签名
     *
     * @param paramValues
     * @param ignoreParamNames
     * @param secret
     * @return
     */
    public static String sign(Map<String, String> paramValues, List<String> ignoreParamNames, String secret) {
        try {
            StringBuilder sb = new StringBuilder();
            List<String> paramNames = new ArrayList<String>(paramValues.size());
            paramNames.addAll(paramValues.keySet());
            if (ignoreParamNames != null && ignoreParamNames.size() > 0) {
                for (String ignoreParamName : ignoreParamNames) {
                    paramNames.remove(ignoreParamName);
                }
            }
            Collections.sort(paramNames);
            sb.append(secret);
            for (String paramName : paramNames) {
                sb.append(paramName).append(paramValues.get(paramName));
            }
            sb.append(secret);
            System.out.println("原始的签名:" + sb.toString());
            byte[] sha1Digest = getSHA1Digest(sb.toString());
            System.out.println("sha-1的二进制码:" + String.valueOf(sha1Digest));
            return byte2hex(sha1Digest);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static String utf8Encoding(String value, String sourceCharsetName) {
        try {
            return new String(value.getBytes(sourceCharsetName), UTF_8);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }
    private static byte[] getSHA1Digest(String data) throws IOException {
        byte[] bytes = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            bytes = md.digest(data.getBytes(UTF_8));
        } catch (GeneralSecurityException gse) {
            throw new IOException(gse.getMessage())    ;
        }
        return bytes;
    }
    //    private static byte[] getMD5Digest(String data) throws IOException {
    //        byte[] bytes = null;
    //        try {
    //            MessageDigest md = MessageDigest.getInstance("MD5");
    //            bytes = md.digest(data.getBytes(UTF_8));
    //        } catch (GeneralSecurityException gse) {
    //            throw new IOException(gse.getMessage());
    //        }
    //        return bytes;
    //    }
    /**
     * 二进制转十六进制字符串
     *
     * @param bytes
     * @return
     */
    private static String byte2hex(byte[] bytes) {
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toUpperCase());
        }
        System.out.println("最终的签名:" + sign);
        return sign.toString();
    }
    public static String getUUID() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().toUpperCase();
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorInfo.java
@@ -1,6 +1,5 @@
package com.ruoyi.integration.drainage.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -86,28 +85,53 @@
    @Null
    @JsonProperty("QRCode")
    private String QRCode;
    /**
     * 恒功率电压上限
     */
    @Null
    @JsonProperty("ConstantVoltageUpperLimits")
    private BigDecimal constantVoltageUpperLimits;
    /**
     * 恒功率电压下限
     */
    @Null
    @JsonProperty("ConstantVoltageLowerLimits")
    private BigDecimal constantVoltageLowerLimits;
    /**
     * 恒功率电压上限
     */
    @Null
    @JsonProperty("ConstantCurrentUpperLimits")
    private BigDecimal constantCurrentUpperLimits;
    /**
     * 恒功率电压下限
     */
    @Null
    @JsonProperty("ConstantCurrentLowerLimits")
    private BigDecimal constantCurrentLowerLimits;
    /**
     * 辅助电源
     * 1:12V
     * 2:24V
     */
    @NotNull
    @JsonProperty("AuxPower")
    private Integer auxPower;
    /**
     * 运营状态
     * 0:未知
     * 1:建设中
     * 5:关闭下线
     * 6:维护中
     * 50:正常使用
     */
    @NotNull
    @TableField("OpreateStatus")
    @JsonProperty("OpreateStatus")
    private Integer opreateStatus;
    /**
     * 运营时间
     */
    @Null
    @TableField("OpreateHours")
    @JsonProperty("OpreateHours")
    private String opreateHours;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorStatusInfo.java
@@ -26,6 +26,7 @@
     * 2:占用(未充电)
     * 3:占用(充电中)
     * 4:占用(预约锁定)
     * 5:占用(放电中)
     * 255:故障
     */
    @NotNull
@@ -49,17 +50,29 @@
    @Null
    @JsonProperty("LookStatus")
    private Integer lookStatus;
    /**
     *
     */
    @JsonProperty("ConnectorStatusInfo")
    private ConnectorStatusInfo connectorStatusInfo;
    /**
     * 运营平台ID
     */
    @JsonProperty("OperatorID")
    private String OperatorID;
    /**
     * 产权所属单位ID
     */
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    /**
     * 充电站ID
     */
    @JsonProperty("StationID")
    private String StationID;
    /**
     * 充电设备编码
     */
    @JsonProperty("EquipmentID")
    private String EquipmentID;
    /**
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/StationInfo.java
@@ -1,8 +1,6 @@
package com.ruoyi.integration.drainage.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;