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;