From ec1991af2409134eb6b8813b83b278956bd3d0cc Mon Sep 17 00:00:00 2001 From: xuhy <3313886187@qq.com> Date: 星期三, 26 三月 2025 11:09:37 +0800 Subject: [PATCH] 监管平台 --- ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java | 217 ++++++++++++++++++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java | 20 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java | 122 ++++++++++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java | 56 ++++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java | 55 ++++ ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java | 74 ++++++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java | 26 ++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java | 126 +++++----- 8 files changed, 619 insertions(+), 77 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java index c41fbbd..c990aed 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java @@ -178,6 +178,80 @@ return result.toString(); } + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param token token + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param,String token) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setRequestProperty("Authorization", "Bearer "+token); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + public static String sendSSLPost(String url, String param) { StringBuilder result = new StringBuilder(); diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java index 9e28bdf..db89dda 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java @@ -25,6 +25,7 @@ import com.ruoyi.other.api.feignClient.SystemConfigurationClient; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; @@ -84,7 +85,8 @@ @Resource private SystemConfigurationClient systemConfigurationClient; - + @Autowired + private TCECSuperviseUtil tcecSuperviseUtil; private final static String operatorId = "906171535"; /** @@ -1840,13 +1842,13 @@ for (Integer stationID : stationIDList) { StationStatusInfo stationStatusInfo = new StationStatusInfo(); stationStatusInfo.setOperatorID(operatorID); - stationStatusInfo.setEquipmentOwnerID("999999999"); + stationStatusInfo.setEquipmentOwnerID(operatorId); stationStatusInfo.setStationID(String.valueOf(stationID)); List<ConnectorStatusInfo> connectorStatusInfos = new ArrayList<>(); for (TChargingGun chargingGun : chargingGuns) { ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo(); connectorStatusInfo.setOperatorID(operatorId); - connectorStatusInfo.setEquipmentOwnerID("999999999"); + connectorStatusInfo.setEquipmentOwnerID(operatorId); connectorStatusInfo.setStationID(String.valueOf(chargingGun.getSiteId())); connectorStatusInfo.setEquipmentID(String.valueOf(chargingGun.getChargingPileId())); connectorStatusInfo.setConnectorID(chargingGun.getFullNumber()); @@ -1902,7 +1904,7 @@ public R pushSuperviseNotificationStationStatus(TChargingGun chargingGun){ ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo(); connectorStatusInfo.setOperatorID(operatorId); - connectorStatusInfo.setEquipmentOwnerID("999999999"); + connectorStatusInfo.setEquipmentOwnerID(operatorId); connectorStatusInfo.setStationID(String.valueOf(chargingGun.getSiteId())); connectorStatusInfo.setEquipmentID(String.valueOf(chargingGun.getChargingPileId())); connectorStatusInfo.setConnectorID(chargingGun.getFullNumber()); @@ -1933,7 +1935,7 @@ connectorStatusInfo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); List<Operator> operators = operatorClient.getAllOperator().getData(); for (Operator operator : operators) { - TCECSuperviseUtil.notificationStationStatus(operator, connectorStatusInfo); + tcecSuperviseUtil.notificationStationStatus(operator, connectorStatusInfo); } return R.ok(); } @@ -1945,7 +1947,7 @@ public R pushSuperviseNotificationEquipChargeStatus(TChargingOrder chargingOrder){ SupEquipChargeStatus supEquipChargeStatus = new SupEquipChargeStatus(); supEquipChargeStatus.setOperatorID(operatorId); - supEquipChargeStatus.setEquipmentOwnerID("999999999"); + supEquipChargeStatus.setEquipmentOwnerID(operatorId); supEquipChargeStatus.setStationID(String.valueOf(chargingOrder.getSiteId())); supEquipChargeStatus.setEquipmentID(String.valueOf(chargingOrder.getChargingPileId())); supEquipChargeStatus.setOrderNo(operatorId+chargingOrder.getCode()); @@ -1997,7 +1999,7 @@ supEquipChargeStatus.setTotalPower(chargingOrder.getElectrovalence()); List<Operator> operators = operatorClient.getAllOperator().getData(); for (Operator operator : operators) { - TCECSuperviseUtil.notificationSupEquipChargeStatus(operator, supEquipChargeStatus); + tcecSuperviseUtil.notificationSupEquipChargeStatus(operator, supEquipChargeStatus); } return R.ok(); } @@ -2009,7 +2011,7 @@ public R pushSuperviseNotificationChargeOrderInfo(TChargingOrder chargingOrder){ SupChargeOrderInfo supChargeOrderInfo = new SupChargeOrderInfo(); supChargeOrderInfo.setOperatorID(operatorId); - supChargeOrderInfo.setEquipmentOwnerID("999999999"); + supChargeOrderInfo.setEquipmentOwnerID(operatorId); supChargeOrderInfo.setStationID(String.valueOf(chargingOrder.getSiteId())); supChargeOrderInfo.setEquipmentID(String.valueOf(chargingOrder.getChargingPileId())); supChargeOrderInfo.setOrderNo(operatorId+chargingOrder.getCode()); @@ -2044,7 +2046,7 @@ List<Operator> operators = operatorClient.getAllOperator().getData(); for (Operator operator : operators) { - TCECSuperviseUtil.notificationChargeOrderInfo(operator, supChargeOrderInfo); + tcecSuperviseUtil.notificationChargeOrderInfo(operator, supChargeOrderInfo); } return R.ok(); } diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java new file mode 100644 index 0000000..05d84e2 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java @@ -0,0 +1,217 @@ +package com.ruoyi.integration.drainage; + +import com.alibaba.fastjson.JSON; +import com.alibaba.nacos.common.utils.JacksonUtils; +import com.ruoyi.chargingPile.api.feignClient.*; +import com.ruoyi.chargingPile.api.model.*; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.dto.ChargingPercentProvinceDto; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.web.page.PageInfo; +import com.ruoyi.integration.api.model.UploadRealTimeMonitoringData; +import com.ruoyi.integration.api.vo.StartChargeResult; +import com.ruoyi.integration.drainage.kuaidian.TCECKDUtil; +import com.ruoyi.integration.drainage.kuaidian.model.*; +import com.ruoyi.integration.drainage.model.*; +import com.ruoyi.integration.drainage.model.enu.*; +import com.ruoyi.integration.mongodb.service.UploadRealTimeMonitoringDataService; +import com.ruoyi.order.api.feignClient.ChargingOrderAccountingStrategyClient; +import com.ruoyi.order.api.feignClient.ChargingOrderClient; +import com.ruoyi.order.api.model.AddTripartitePlatformOrder; +import com.ruoyi.order.api.model.TChargingOrder; +import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy; +import com.ruoyi.other.api.domain.Operator; +import com.ruoyi.other.api.feignClient.OperatorClient; +import com.ruoyi.other.api.feignClient.SystemConfigurationClient; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +/** + * @author zhibing.pu + * @Date 2025/1/21 17:52 + */ +@Slf4j +@Component +public class TCECPushUtil { + + @Resource + private ChargingGunClient chargingGunClient; + + @Resource + private OperatorClient operatorClient; + + @Autowired + private TCECSuperviseUtil tcecSuperviseUtil; + private final static String operatorId = "906171535"; + + /** + * 推送充电设备接口状态信息 + * @param chargingGun + * @return + */ + public R pushSuperviseNotificationStationStatus(TChargingGun chargingGun){ + ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo(); + connectorStatusInfo.setOperatorID(operatorId); + connectorStatusInfo.setEquipmentOwnerID(operatorId); + connectorStatusInfo.setStationID(String.valueOf(chargingGun.getSiteId())); + connectorStatusInfo.setEquipmentID(String.valueOf(chargingGun.getChargingPileId())); + connectorStatusInfo.setConnectorID(chargingGun.getFullNumber()); + connectorStatusInfo.setEquipmentClassification(1); + switch (chargingGun.getStatus()){ + case 1: + connectorStatusInfo.setStatus(0); + break; + case 2: + connectorStatusInfo.setStatus(1); + break; + case 3: + connectorStatusInfo.setStatus(2); + break; + case 4: + connectorStatusInfo.setStatus(3); + break; + case 5: + connectorStatusInfo.setStatus(3); + break; + case 6: + connectorStatusInfo.setStatus(4); + break; + case 7: + connectorStatusInfo.setStatus(255); + break; + } + connectorStatusInfo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + List<Operator> operators = operatorClient.getAllOperator().getData(); + for (Operator operator : operators) { + tcecSuperviseUtil.notificationStationStatus(operator, connectorStatusInfo); + } + return R.ok(); + } + /** + * 推送充电状态信息 + * @param chargingOrder + * @return + */ + public R pushSuperviseNotificationEquipChargeStatus(TChargingOrder chargingOrder){ + SupEquipChargeStatus supEquipChargeStatus = new SupEquipChargeStatus(); + supEquipChargeStatus.setOperatorID(operatorId); + supEquipChargeStatus.setEquipmentOwnerID(operatorId); + supEquipChargeStatus.setStationID(String.valueOf(chargingOrder.getSiteId())); + supEquipChargeStatus.setEquipmentID(String.valueOf(chargingOrder.getChargingPileId())); + supEquipChargeStatus.setOrderNo(operatorId+chargingOrder.getCode()); + switch (chargingOrder.getStatus()){ + case 2: + supEquipChargeStatus.setConnectorStatus(1); + break; + case 3: + supEquipChargeStatus.setConnectorStatus(2); + break; + case 4: + supEquipChargeStatus.setConnectorStatus(3); + break; + case 5: + supEquipChargeStatus.setConnectorStatus(4); + break; + } + TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingOrder.getChargingGunId()).getData(); + supEquipChargeStatus.setConnectorID(chargingGun.getFullNumber()); + supEquipChargeStatus.setEquipmentClassification(1); + supEquipChargeStatus.setPushTimeStamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + switch (chargingGun.getStatus()){ + case 1: + supEquipChargeStatus.setConnectorStatus(0); + break; + case 2: + supEquipChargeStatus.setConnectorStatus(1); + break; + case 3: + supEquipChargeStatus.setConnectorStatus(2); + break; + case 4: + supEquipChargeStatus.setConnectorStatus(3); + break; + case 5: + supEquipChargeStatus.setConnectorStatus(3); + break; + case 6: + supEquipChargeStatus.setConnectorStatus(4); + break; + case 7: + supEquipChargeStatus.setConnectorStatus(255); + break; + } + supEquipChargeStatus.setCurrentA(chargingOrder.getCurrent()); + supEquipChargeStatus.setSOC(new BigDecimal(chargingOrder.getEndSoc())); + supEquipChargeStatus.setStartTime(chargingOrder.getStartTime() != null ? chargingOrder.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : ""); + supEquipChargeStatus.setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + supEquipChargeStatus.setTotalPower(chargingOrder.getElectrovalence()); + List<Operator> operators = operatorClient.getAllOperator().getData(); + for (Operator operator : operators) { + tcecSuperviseUtil.notificationSupEquipChargeStatus(operator, supEquipChargeStatus); + } + return R.ok(); + } + /** + * 推送充电订单信息 + * @param chargingOrder + * @return + */ + public R pushSuperviseNotificationChargeOrderInfo(TChargingOrder chargingOrder){ + SupChargeOrderInfo supChargeOrderInfo = new SupChargeOrderInfo(); + supChargeOrderInfo.setOperatorID(operatorId); + supChargeOrderInfo.setEquipmentOwnerID(operatorId); + supChargeOrderInfo.setStationID(String.valueOf(chargingOrder.getSiteId())); + supChargeOrderInfo.setEquipmentID(String.valueOf(chargingOrder.getChargingPileId())); + supChargeOrderInfo.setOrderNo(operatorId+chargingOrder.getCode()); + TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingOrder.getChargingGunId()).getData(); + supChargeOrderInfo.setConnectorID(chargingGun.getFullNumber()); + supChargeOrderInfo.setEquipmentClassification(1); + supChargeOrderInfo.setPushTimeStamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + supChargeOrderInfo.setStartTime(chargingOrder.getStartTime() != null ? chargingOrder.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : ""); + supChargeOrderInfo.setEndTime(chargingOrder.getEndTime() != null ? chargingOrder.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : ""); + supChargeOrderInfo.setTotalPower(chargingOrder.getElectrovalence()); + supChargeOrderInfo.setTotalElecMoney(chargingOrder.getElectrovalence()); + supChargeOrderInfo.setTotalServiceMoney(chargingOrder.getServiceCharge()); + supChargeOrderInfo.setTotalMoney(chargingOrder.getOrderAmount()); + switch (chargingOrder.getEndMode()){ + case 0: + supChargeOrderInfo.setStopReason(5); + supChargeOrderInfo.setStopDesc("异常终止"); + break; + case 1: + supChargeOrderInfo.setStopReason(0); + supChargeOrderInfo.setStopDesc("用户手动停止充电"); + break; + case 2: + supChargeOrderInfo.setStopReason(1); + supChargeOrderInfo.setStopDesc("客户归属地运营商平台停止充电"); + break; + case 3: + supChargeOrderInfo.setStopReason(1); + supChargeOrderInfo.setStopDesc("费用不足中止"); + break; + } + + List<Operator> operators = operatorClient.getAllOperator().getData(); + for (Operator operator : operators) { + tcecSuperviseUtil.notificationChargeOrderInfo(operator, supChargeOrderInfo); + } + return R.ok(); + } +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java index fb87f7c..5d23f51 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java @@ -6,16 +6,23 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.common.utils.JacksonUtils; -import com.ruoyi.common.core.utils.SpringUtils; +import com.ruoyi.common.core.utils.HttpUtils; +import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.integration.drainage.model.*; -import com.ruoyi.integration.drainage.model.enu.InterfaceUrlEnum; +import com.ruoyi.integration.drainage.util.AesEncryption; +import com.ruoyi.integration.drainage.util.HMacMD5Util; +import com.ruoyi.integration.drainage.util.SequenceGenerator; import com.ruoyi.other.api.domain.Operator; -import com.ruoyi.other.api.feignClient.OperatorClient; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; +import java.util.concurrent.TimeUnit; + +import static com.ruoyi.integration.drainage.TCECUtil.getToken; /** * 中电联TCEC标准 @@ -23,10 +30,23 @@ * @Date 2025/1/21 11:48 */ @Slf4j +@Component public class TCECSuperviseUtil { - - private static OperatorClient operatorClient = SpringUtils.getBean(OperatorClient.class); + // 测试环境 + private static final String OperatorID = "MA01H3BQ2"; + private static final String OperatorSecret = "f1331ef0b37c2d1b"; + private static final String SigSecret = "a6fedf0e1b27d6f7"; + private static final String DataSecret = "50a61b93919c9604"; + private static final String DataSecretIV = "7c8ac6861661d584"; + + @Autowired + private RedisService redisService; + public static final String TOKEN_KEY = "charge_token:"; private final static String url = "https://dev-gov-hlht-sc.unievbj.com/evcs/v1.0.0/"; + /** + * 获取token + */ + private final static String query_token = "/query_token"; /** * 推送充电设备接口状态信息 */ @@ -45,71 +65,45 @@ /** * 获取token */ - public static String queryToken(Operator operator){ - HttpRequest post = HttpUtil.createPost(operator.getUrl() + InterfaceUrlEnum.QUERY_TOKEN.getUrl()); - JSONObject info = new JSONObject(); - info.put("OperatorID", operator.getOurOperatorId()); - info.put("OperatorSecret", operator.getOperatorSecret()); - Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); - post.contentType("application/json;charset=utf-8"); - BaseRequest baseRequest = new BaseRequest(); - baseRequest.setOperatorID(operator.getOurOperatorId()); - baseRequest.setTimeStamp(timeStamp); - baseRequest.setSeq("0001"); - String jsonString = JacksonUtils.toJson(info); - String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv()); - baseRequest.setData(encrypt); - baseRequest.setOperator(operator); -// baseRequest.setSig(buildSign(baseRequest)); - String request_json = JacksonUtils.toJson(baseRequest); - log.info("获取三方平台授权token请求地址:" + post.getUrl()); - log.info("获取三方平台授权token请求参数:" + request_json); - log.info("获取三方平台授权token请求Data:" + jsonString); - post.body(request_json); - HttpResponse execute = post.execute(); - if(200 != execute.getStatus()){ - log.error("获取三方平台授权token失败:" + execute.body()); - return null; + public String queryToken(Operator operator){ + String token = redisService.getCacheObject(TOKEN_KEY); + if(StringUtils.hasLength(token)){ + return token; } - log.info("获取三方平台授权token响应参数:" + execute.body()); - BaseResult baseResult = JSON.parseObject(execute.body(), BaseResult.class); - Integer Ret = baseResult.getRet(); - if(0 != Ret){ - log.error("获取三方平台授权token失败:" + baseResult.getMsg()); - return null; - } - //解密参数 - String decrypt = AESUtil.decrypt(baseResult.getData(), operator.getDataSecret(), operator.getDataSecretIv()); - log.info("获取三方平台授权token响应Data:" + decrypt); - QueryTokenResult queryTokenResult = JSON.parseObject(decrypt, QueryTokenResult.class); - String token = queryTokenResult.getAccessToken(); - Long tokenAvailableTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) + queryTokenResult.getTokenAvailableTime(); - operator.setAccessToken(token); - operator.setTokenAvailableTime(tokenAvailableTime); - operatorClient.editOperator(operator); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("OperatorID", OperatorID); + jsonObject.put("OperatorSecret", OperatorSecret); + String params = jsonObject.toJSONString(); + // 参数加密 + String data = AesEncryption.encrypt(DataSecret, DataSecretIV, params); + // 获取签名 + String timeStamp = System.currentTimeMillis() + ""; + SequenceGenerator generator = new SequenceGenerator(); + String nextSequence = generator.getNextSequence(); + String hmacMD5 = HMacMD5Util.getHMacMD5(OperatorID,timeStamp, data,nextSequence,SigSecret); + jsonObject = new JSONObject(); + jsonObject.put("OperatorID", OperatorID); + jsonObject.put("Data", data); + jsonObject.put("TimeStamp", timeStamp); + jsonObject.put("Seq", nextSequence); + jsonObject.put("Sig", hmacMD5); + String result = HttpUtils.sendPost(url+query_token, jsonObject.toJSONString()); + String string = JSONObject.parseObject(result).getString("Data"); + String decrypt = AesEncryption.decrypt(DataSecret, DataSecretIV, string); + JSONObject tokenResult = JSONObject.parseObject(decrypt); + token = tokenResult.getString("AccessToken"); + Integer TokenAvailableTime = tokenResult.getInteger("TokenAvailableTime"); + redisService.setCacheObject(TOKEN_KEY,token, (long) (TokenAvailableTime - 60), TimeUnit.SECONDS); return token; } - /** - * 获取token - * @return - */ - public static String getToken(Operator operator){ - if(null != operator.getTokenAvailableTime() && operator.getTokenAvailableTime() > LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)){ - return operator.getAccessToken(); - }else{ - return queryToken(operator); - } - } - - - + /** * 设备状态变化推送 * @param info */ - public static NotificationStationStatusResult notificationStationStatus(Operator operator, ConnectorStatusInfo info) { + public NotificationStationStatusResult notificationStationStatus(Operator operator, ConnectorStatusInfo info) { HttpRequest post = HttpUtil.createPost(url+supervise_notification_station_status); buildBody(post, info, operator); HttpResponse execute = post.execute(); @@ -137,7 +131,7 @@ * @param info * @return */ - public static NotificationEquipChargeStatusResult notificationSupEquipChargeStatus(Operator operator, SupEquipChargeStatus info){ + public NotificationEquipChargeStatusResult notificationSupEquipChargeStatus(Operator operator, SupEquipChargeStatus info){ HttpRequest post = HttpUtil.createPost(url+supervise_notification_equip_charge_status); buildBody(post, info, operator); HttpResponse execute = post.execute(); @@ -165,7 +159,7 @@ * @param info * @return */ - public static NotificationChargeOrderInfoResult notificationChargeOrderInfo(Operator operator, SupChargeOrderInfo info){ + public NotificationChargeOrderInfoResult notificationChargeOrderInfo(Operator operator, SupChargeOrderInfo info){ HttpRequest post = HttpUtil.createPost(url+supervise_notification_charge_order_info); buildBody(post, info, operator); HttpResponse execute = post.execute(); @@ -193,7 +187,7 @@ * @param post * @param o */ - public static void buildBody(HttpRequest post, Object o, Operator operator){ + public void buildBody(HttpRequest post, Object o, Operator operator){ Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); post.contentType("application/json;charset=utf-8"); post.header("Authorization", "Bearer " + getToken(operator)); @@ -202,7 +196,7 @@ baseRequest.setTimeStamp(timeStamp); baseRequest.setSeq("0001"); String jsonString = JacksonUtils.toJson(o); - String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv()); + String encrypt = AesEncryption.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv()); baseRequest.setData(encrypt); baseRequest.setOperator(operator); // baseRequest.setSig(buildSign(baseRequest)); diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java new file mode 100644 index 0000000..e8b4bcc --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java @@ -0,0 +1,55 @@ +package com.ruoyi.integration.drainage.util; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; + +/** + * 充电桩交互的数据的加密解密 + */ +public class AesEncryption { + + /** + * 加密 + * @param key + * @param iv + * @param data + * @return + */ + public static String encrypt(String key, String iv, String data) { + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES"); + IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] encrypted = cipher.doFinal(data.getBytes()); + return Base64.getEncoder().encodeToString(encrypted); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 解密 + * @param key + * @param iv + * @param encryptedData + * @return + */ + public static String decrypt(String key, String iv, String encryptedData) { + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES"); + IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData)); + return new String(decrypted); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} \ No newline at end of file diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java new file mode 100644 index 0000000..fd7a3c6 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java @@ -0,0 +1,122 @@ +package com.ruoyi.integration.drainage.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HMacMD5Util { + + /** + * 加签 + * @param operatorId + * @param timeStamp + * @param data + * @param seq + * @param SigSecret + * @return + */ + public static String getHMacMD5(String operatorId,String timeStamp, String data, String seq,String SigSecret) { + String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString(); + byte[] macMD5 = HMacMD5Util.getHMacMD5Bytes(SigSecret.getBytes(), m.getBytes()); + return HMacMD5Util.bytesToHexString(macMD5); + } + + + /** + * HmacMd5的计算公式为:HMAC(K,M) = H(K⊕opad∣H(K⊕ipad∣M)) + * 其中:K是密钥(byte[] key),长度可为64字节(后面涉及描述都是以字节byte进行),若小于该长度,在密钥后面用0(即0x00)补齐。 + * M是消息内容(byte[] m); + * H是散列函数(此处采用MD5); + * opad和ipad分别是由若干个0x5c和0x36组成的字符串; + * ⊕表示异或运算; + * ∣表示连接操作。 + **/ + private static byte[] getHMacMD5Bytes(byte[] key, byte[] m) { + try { + //定义长度 + int length = 64; + //定义opad和ipad + byte[] opad = new byte[length]; + byte[] ipad = new byte[length]; + for (int i = 0; i < 64; i++) { + opad[i] = 0x5C; + ipad[i] = 0x36; + } + byte[] actualKey = key; + byte[] keyArr = new byte[length]; + //如果密钥长度,大于64字节,就使用MD5算法计算其散列值,作为密钥 + if (key.length > length) { + actualKey = md5(key); + } + for (int i = 0; i < actualKey.length; i++) { + keyArr[i] = actualKey[i]; + } + //如果密钥长度不足64字节,就使用0x00补齐到64字节 + if (actualKey.length < length) { + for (int i = key.length; i < length; i++) + keyArr[i] = 0x00; + } + //使用密钥和ipad进行异或运算【K⊕ipad】 + byte[] kIpadXorResult = new byte[length]; + for (int i = 0; i < length; i++) { + kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]); + } + //将待加密数据M追加到kIpadXorResult后面【K⊕ipad∣M】 + byte[] firstAppendResult = new byte[kIpadXorResult.length + m.length]; + for (int i = 0; i < kIpadXorResult.length; i++) { + firstAppendResult[i] = kIpadXorResult[i]; + } + for (int i = 0; i < m.length; i++) { + firstAppendResult[i + keyArr.length] = m[i]; + } + //做MD5运算【H(K⊕ipad∣M)】 + byte[] firstHashResult = md5(firstAppendResult); + + //使用密钥和opad进行异或运算【K⊕opad】 + byte[] kOpadXorResult = new byte[length]; + for (int i = 0; i < length; i++) { + kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]); + } + //将firstHashResult追加到kOpadXorResult后面【K⊕opad∣H(K⊕ipad∣M)】 + byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length]; + for (int i = 0; i < kOpadXorResult.length; i++) { + secondAppendResult[i] = kOpadXorResult[i]; + } + for (int i = 0; i < firstHashResult.length; i++) { + secondAppendResult[kOpadXorResult.length + i] = firstHashResult[i]; + } + //做MD5运算【H(K⊕opad∣H(K⊕ipad∣M))】 + return md5(secondAppendResult); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } + + /** + * MD5(产生出一个128位(16字节)的散列值) + **/ + private static byte[] md5(byte[] str) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str); + return md.digest(); + } + + /** + * HEX转化为字符串 + **/ + private static String bytesToHexString(byte[] m) { + StringBuilder stringBuilder = new StringBuilder(); + if (m == null || m.length <= 0) { + return null; + } + for (int i = 0; i < m.length; i++) { + int v = m[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString().toUpperCase(); + } +} \ No newline at end of file diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java new file mode 100644 index 0000000..45da471 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java @@ -0,0 +1,56 @@ +package com.ruoyi.integration.drainage.util; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +public class SequenceGenerator { + private final ConcurrentHashMap<Long, AtomicInteger> counterMap = new ConcurrentHashMap<>(); + + public synchronized String getNextSequence() { + long currentTimestamp = System.currentTimeMillis() / 1000; // 获取当前秒级时间戳 + + AtomicInteger counter = counterMap.get(currentTimestamp); + if (counter == null) { + counter = new AtomicInteger(1); // 新的一秒,初始化计数器为1 + counterMap.put(currentTimestamp, counter); + } else { + counter.incrementAndGet(); // 同一秒内,计数器递增 + } + + // 生成四位序列号 + String sequence = String.format("%04d", counter.get()); + + return sequence; + } + + public static void main(String[] args) { + SequenceGenerator generator = new SequenceGenerator(); + + // 测试生成多个序列号 + for (int i = 0; i < 10; i++) { + System.out.println(generator.getNextSequence()); + try { + Thread.sleep(100); // 模拟同一秒内的多次调用 + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + // 模拟进入新的一秒 + try { + Thread.sleep(1100); // 等待超过1秒 + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // 再次生成序列号 + for (int i = 0; i < 10; i++) { + System.out.println(generator.getNextSequence()); + try { + Thread.sleep(100); // 模拟同一秒内的多次调用 + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java index 045faca..b3c6646 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java @@ -13,6 +13,7 @@ import com.ruoyi.chargingPile.api.vo.UpdateChargingPileStatusVo; import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.integration.api.model.*; +import com.ruoyi.integration.drainage.TCECPushUtil; import com.ruoyi.integration.iotda.constant.SendTagConstant; import com.ruoyi.integration.iotda.enums.ServiceIdMenu; import com.ruoyi.integration.iotda.utils.tools.CP56Time2aConverter; @@ -119,10 +120,14 @@ private QrCodeDeliveryReplyService qrCodeDeliveryReplyService; @Autowired private SecurityDetectionService securityDetectionService; - + @Autowired + private TCECPushUtil tcecPushUtil; + @Resource private ChargingPileClient chargingPileClient; - + @Resource + private ChargingGunClient chargingGunClient; + @Resource private RedisTemplate redisTemplate; @@ -161,6 +166,11 @@ vo1.setPile_code(pingMessage.getCharging_pile_code()); vo1.setStatus(pingMessage.getCharging_gun_status()); chargingPileClient.updateChargingPileStatus(vo1); + try { + tcecPushUtil.pushSuperviseNotificationStationStatus(chargingGunClient.getChargingGunByFullNumber(pingMessage.getCharging_pile_code()+pingMessage.getCharging_gun_code()).getData()); + }catch (Exception e){ + System.out.println("设备状态推送监管平台失败:"+e.getMessage()); + } break; case SendTagConstant.END_CHARGE: EndChargeMessage endChargeMessage = message.getEndChargeMessage(); @@ -171,6 +181,15 @@ endChargeService.create(endCharge); // 业务处理 chargingOrderClient.endCharge(endCharge.getTransaction_serial_number()); + // 监管平台 + // 查询订单信息 + try { + TChargingOrder chargingOrder = chargingOrderClient.getOrderByCode(endCharge.getTransaction_serial_number()).getData(); + tcecPushUtil.pushSuperviseNotificationChargeOrderInfo(chargingOrder); + tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder); + }catch (Exception e){ + System.out.println("充电结束推送监管平台失败:"+e.getMessage()); + } break; case SendTagConstant.ERROR_MESSAGE: ErrorMessageMessage errorMessageMessage1 = message.getErrorMessageMessage(); @@ -235,6 +254,9 @@ UploadRealTimeMonitoringDataQuery query = new UploadRealTimeMonitoringDataQuery(); BeanUtils.copyProperties(uploadRealTimeMonitoringData, query); chargingOrderClient.chargeMonitoring(query); + + tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder); + } catch (Exception e) { e.printStackTrace(); } -- Gitblit v1.7.1