xuhy
2025-03-26 ec1991af2409134eb6b8813b83b278956bd3d0cc
监管平台
4个文件已修改
4个文件已添加
688 ■■■■ 已修改文件
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECSuperviseUtil.java 122 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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();
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();
    }
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECPushUtil.java
New file
@@ -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();
    }
}
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 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";
    
    private static OperatorClient operatorClient = SpringUtils.getBean(OperatorClient.class);
    @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,62 +65,36 @@
    /**
     * 获取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;
        }
        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);
    public String queryToken(Operator operator){
        String token = redisService.getCacheObject(TOKEN_KEY);
        if(StringUtils.hasLength(token)){
        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);
        }
        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;
    }
    
    
@@ -109,7 +103,7 @@
     * 设备状态变化推送
     * @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));
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/AesEncryption.java
New file
@@ -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;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/HMacMD5Util.java
New file
@@ -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();
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/util/SequenceGenerator.java
New file
@@ -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();
            }
        }
    }
}
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,9 +120,13 @@
    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();
                }