Pu Zhibing
5 天以前 db0b7644a9a5a62ac2da3cf571fee41bb8b6974f
添加E路通推送数据功能
7个文件已修改
21个文件已添加
1845 ■■■■■ 已修改文件
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -247,6 +247,13 @@
                <version>${ruoyi.version}</version>
            </dependency>
            <!-- 监管接口 -->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-api-jianguan</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java
@@ -447,6 +447,12 @@
    @TableField("supportOrder")
    @ApiModelProperty(value = "2.0修改字段-是否支持预约 0不支持1支持")
    private Integer supportOrder;
    /**
     * 高速路服务区编号
     */
    @TableField("serAreaCode")
    @ApiModelProperty(value = "高速路服务区编号")
    private String serAreaCode;
//    /**
//     * 换电设备信息
//     */
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
@Data
public class ConnectorInfo {
    /**
     * 充电设备接口编码
     * 充电设备接口编码,同一运营商内唯一
     */
    private String connectorId;
    /**
     * 充电设备接口名称
     */
    private String connectorName;
    /**
     * 充电设备接口类型
     * 1:家用插座(模式2);
     * 2:交流接口插座(模式3,连接方式B );
     * 3:交流接口插头(带枪线,模式3,连接方式C);
     * 4:直流接口枪头(带枪线,模式4);
     * 5:无线充电座;
     * 6:其他
     */
    private Integer connectorType;
    /**
     * 额定电压上限
     */
    private Integer voltageUpperLimits;
    /**
     * 额定电压下限
     */
    private Integer voltageLowerLimits;
    /**
     * 额定电流
     */
    private Integer current;
    /**
     * 充电设备总功率
     */
    private Double power;
    /**
     * 车位号
     */
    private String parkNo;
    /**
     * 国家标准
     * 1:2011;2:2015
     */
    private Integer nationalStandard;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
@Data
public class ConnectorStatusInfo {
    /**
     * 充电设备接口编码
     * 充电设备接口编码,同一运营商内唯一
     */
    private String connectorId;
    /**
     * 充电设备接口状态
     * 0:离网;
     * 1:空闲;
     * 2:占用(未充电);
     * 3:占用(充电中);
     * 4:占用(预约锁定);
     * 255:故障
     */
    private Integer status;
    /**
     * 电池剩余电量
     */
    private Double soc;
    /**
     * 估算剩余充电时间(min)
     */
    private Integer remainingTime;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.util.List;
@Data
public class ConnectorStatusReq {
    /**
     * 充电运营商ID
     * 使用运营商组织机构代码
     */
    private String operatorId;
    /**
     * 服务区编码
     * 如上送具体的服务区信息时,该字段必填,否则可为空
     */
    private String serAreaCode;
    /**
     * 充电站ID
     * 充电站唯一编码
     * 运营商未提供:使用服务区编码+充电站(CD)/换电站(HD)+顺序码
     * 顺序码规则:两位字符,取值范围01~99
     * 运营商提供:使用运营商提供的充电站编码。同一运营商内唯一
     */
    private String stationId;
    /**
     * 总记录条数
     * 符合条件的充电站总数,记录数不超过50
     */
    private Integer itemSize;
    /**
     * 充电设备接口状态列表
     */
    private List<ConnectorStatusInfo> connectorStatusInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java
New file
@@ -0,0 +1,61 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.util.List;
@Data
public class EquipmentInfo {
    /**
     * 设备编码
     * 设备唯一编码,对同一运营商,保证唯一
     */
    private String equipmentId;
    /**
     * 充电设备名称
     * 运营商名称简写+设备名称
     */
    private String equipmentName;
    /**
     * 设备生产商组织机构代码
     */
    private String manufacturerId;
    /**
     * 设备生产商名称
     */
    private String manufacturerName;
    /**
     * 设备型号
     */
    private String equipmentModel;
    /**
     * 设备生产日期
     * YYYY-MM-DD
     */
    private String productionDate;
    /**
     * 设备类型
     * 1:直流设备;
     * 2:交流设备;
     * 3:交直流一体设备;
     * 4:无线设备;
     * 5:其他
     */
    private Integer equipmentType;
    /**
     * 充电设备经度
     */
    private Double equipmentLng;
    /**
     * 充电设备维度
     */
    private Double equipmentLat;
    /**
     * 充电设备总功率
     */
    private Double power;
    /**
     * 充电设备接口信息列表
     */
    private List<ConnectorInfo> connectorInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
@Data
public class OperatorInfo {
    /**
     * 运营商ID
     * 组织机构代码
     */
    private String operatorId;
    /**
     * 运营商名称
     */
    private String operatorName;
    /**
     * 运营商客服电话1
     */
    private String operatorTel1;
    /**
     * 运营商客服电话2
     */
    private String operatorTel2;
    /**
     * 运营商注册地址
     */
    private String operatorRegAddress;
    /**
     * 备注
     */
    private String operatorNote;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java
New file
@@ -0,0 +1,145 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class StationInfo {
    /**
     * 服务区编码
     * 由部级管理平台统一管理和分配
     */
    private String serAreaCode;
    /**
     * 运营商ID
     * 组织机构代码
     */
    private String operatorId;
    /**
     * 充/换电站ID
     * 充电站唯一编码
     * 运营商未提供:使用服务区编码+充电站(CD)/换电站(HD)+顺序码
     * 顺序码规则:两位字符,取值范围01~99
     * 运营商提供:使用运营商提供的充电站编码。同一运营商内唯一
     */
    private String stationId;
    /**
     * 充电站名称
     */
    private String stationName;
    /**
     * 站点模式
     * CD:充电站
     * HD:换电站
     */
    private String stationMode;
    /**
     * 充电站省市辖区编码
     */
    private String areaCode;
    /**
     * 服务电话
     */
    private String serviceTel;
    /**
     * 站点类型
     * 1:公共;
     * 50:个人;
     * 100:公交(专用);
     * 101:环卫(专用);
     * 102:物流(专用);
     * 103:出租车(专用);
     * 255:其他
     */
    private Integer stationType;
    /**
     * 站点状态
     * 0:未知;
     * 1:建设中;
     * 5:关闭下线;
     * 6:维护中;
     * 50:正常使用
     */
    private Integer stationStatus;
    /**
     * 车位数量
     */
    private Integer parkNums;
    /**
     * 经度
     */
    private Double stationLng;
    /**
     * 纬度
     */
    private Double stationLat;
    /**
     * 站点引导
     */
    private String siteGuide;
    /**
     * 建设场所
     * 1:居民区;
     * 2:公共机构;
     * 3:企事业单位;
     * 4:写字楼;
     * 5:工业园区;
     * 6:交通枢纽;
     * 7:大型文体设施;
     * 8:城市绿地;
     * 9:大型建筑配建停车场;
     * 10:路边停车位;
     * 11:城际高速服务区;
     * 255:其他
     */
    private Integer construction;
    /**
     * 站点照片
     */
    private List<String> pictures;
    /**
     * 使用车型描述
     */
    private String matchCars;
    /**
     * 营业时间
     */
    private String busineHours;
    /**
     * 充电电费率
     */
    private BigDecimal electricityFee;
    /**
     * 服务费率
     */
    private BigDecimal serviceFee;
    /**
     * 停车费
     */
    private BigDecimal parkFee;
    /**
     * 支付方式
     * 1:刷卡
     * 2:线上
     * 3:现金
     * 101:ETC支付
     * 说明:其中电子钱包类卡为刷卡,身份鉴权卡、微信/支付宝、APP为线上
     */
    private String payment;
    /**
     * 是否支持预约
     * 0:否
     * 1:是
     */
    private Integer supportOrder;
    /**
     * 备注
     */
    private String remark;
    /**
     * 充电设备信息列表
     */
    private List<EquipmentInfo> equipmentInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.util.List;
@Data
public class StationInfoReq {
    /**
     * 充电运营商ID
     * 使用运营商组织机构代码
     */
    private String operatorId;
    /**
     * 服务区编码
     * 如上送具体的服务区信息时,该字段必填,否则可为空
     */
    private String serAreaCode;
    /**
     * 充电站ID
     * 充电站唯一编码
     * 运营商未提供:使用服务区编码+充电站(CD)/换电站(HD)+顺序码
     * 顺序码规则:两位字符,取值范围01~99
     * 运营商提供:使用运营商提供的充电站编码。同一运营商内唯一
     */
    private String stationId;
    /**
     * 基础设施运营商信息
     */
    private OperatorInfo operatorInfo;
    /**
     * 总记录条数
     * 符合条件的充电站总数,记录数不超过50
     */
    private Integer itemSize;
    /**
     * 充电站信息列表
     */
    private List<StationInfo> stationInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.util.List;
@Data
public class StationStausInfo {
    /**
     * 充/换电站ID
     * 使用服务区编码+充电站(CD)/换电站(HD)+顺序码
     */
    private String stationId;
    /**
     * 充电设备接口状态列表
     */
    private List<ConnectorStatusInfo> connectorStatusInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.integration.api.elutong.model;
import lombok.Data;
import java.util.List;
@Data
public class StationsStatusReq {
    /**
     * 充电运营商ID
     * 使用运营商组织机构代码
     */
    private String operatorId;
    /**
     * 服务区编码
     * 如上送具体的服务区信息时,该字段必填,否则可为空
     */
    private String serAreaCode;
    /**
     * 充电站ID
     * 充电站唯一编码
     * 运营商未提供:使用服务区编码+充电站(CD)/换电站(HD)+顺序码
     * 顺序码规则:两位字符,取值范围01~99
     * 运营商提供:使用运营商提供的充电站编码。同一运营商内唯一
     */
    private String stationId;
    /**
     * 总记录条数
     * 符合条件的充电站总数,记录数不超过50
     */
    private Integer itemSize;
    /**
     * 充电站状态信息列表
     */
    private List<StationStausInfo> stationStausInfos;
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.integration.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.integration.api.elutong.model.ConnectorStatusReq;
import com.ruoyi.integration.api.elutong.model.StationInfoReq;
import com.ruoyi.integration.api.elutong.model.StationsStatusReq;
import com.ruoyi.integration.api.feignClient.ELuTongClient;
import org.springframework.cloud.openfeign.FallbackFactory;
public class ELuTongClientFallbackFactory implements FallbackFactory<ELuTongClient> {
    @Override
    public ELuTongClient create(Throwable cause) {
        return new ELuTongClient() {
            @Override
            public R pushStationInfo(StationInfoReq stationInfoReq) {
                return R.fail("推送充电站静态信息失败:" + cause.getMessage());
            }
            @Override
            public R pushStationsStatus(StationsStatusReq stationsStatusReq) {
                return R.fail("推送充电站状态信息失败:" + cause.getMessage());
            }
            @Override
            public R pushConnectorStatus(ConnectorStatusReq connectorStatusReq) {
                return R.fail("推送设备接口状态信息失败:" + cause.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java
New file
@@ -0,0 +1,43 @@
package com.ruoyi.integration.api.feignClient;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.integration.api.elutong.model.ConnectorStatusReq;
import com.ruoyi.integration.api.elutong.model.StationInfoReq;
import com.ruoyi.integration.api.elutong.model.StationsStatusReq;
import com.ruoyi.integration.api.factory.ELuTongClientFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(contextId = "ELuTongClient", value = ServiceNameConstants.JIANGUAN_SERVICE, fallbackFactory = ELuTongClientFallbackFactory.class)
public interface ELuTongClient {
    /**
     * 推送充电站静态信息
     * @param stationInfoReq
     * @return
     */
    @PostMapping("/elutong/pushStationInfo")
    R pushStationInfo(@RequestBody StationInfoReq stationInfoReq);
    /**
     * 推送充电站状态信息
     * @param stationsStatusReq
     * @return
     */
    @PostMapping("/elutong/pushStationsStatus")
    R pushStationsStatus(@RequestBody StationsStatusReq stationsStatusReq);
    /**
     * 推送设备接口状态信息
     * @param connectorStatusReq
     * @return
     */
    @PostMapping("/elutong/pushConnectorStatus")
    R pushConnectorStatus(@RequestBody ConnectorStatusReq connectorStatusReq);
}
ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1,2 @@
com.ruoyi.integration.api.factory.ChargingMessageClientFallbackFactory
com.ruoyi.integration.api.factory.ChargingMessageClientFallbackFactory
com.ruoyi.integration.api.factory.ELuTongClientFallbackFactory
ruoyi-service/ruoyi-chargingPile/pom.xml
@@ -158,6 +158,10 @@
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-api-jianguan</artifactId>
        </dependency>
    </dependencies>
    <build>
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java
@@ -3,9 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.chargingPile.api.model.TChargingPile;
import com.ruoyi.chargingPile.api.model.TFaultMessage;
import com.ruoyi.chargingPile.api.model.*;
import com.ruoyi.chargingPile.api.query.TChargingGunQuery;
import com.ruoyi.chargingPile.api.vo.TChargingGunVO;
import com.ruoyi.chargingPile.api.vo.UpdateChargingPileStatusVo;
@@ -15,6 +13,7 @@
import com.ruoyi.chargingPile.dto.GetChargingGunMonitoring;
import com.ruoyi.chargingPile.service.*;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.chargingPile.api.dto.PageChargingPileListDTO;
@@ -30,6 +29,11 @@
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.annotation.Logical;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.integration.api.elutong.model.ConnectorStatusInfo;
import com.ruoyi.integration.api.elutong.model.ConnectorStatusReq;
import com.ruoyi.integration.api.elutong.model.StationStausInfo;
import com.ruoyi.integration.api.elutong.model.StationsStatusReq;
import com.ruoyi.integration.api.feignClient.ELuTongClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.order.api.feignClient.ChargingOrderClient;
import com.ruoyi.order.api.model.TChargingOrder;
@@ -39,6 +43,7 @@
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
@@ -60,6 +65,7 @@
 * @author xiaochen
 * @since 2024-08-06
 */
@Slf4j
@Api(tags = "充电桩")
@RestController
@RequestMapping("/t-charging-pile")
@@ -79,6 +85,14 @@
    
    @Resource
    private TCECClient tcecClient;
    @Resource
    private ELuTongClient eLuTongClient;
    @Resource
    private ISiteService siteService;
    @Autowired
@@ -268,6 +282,7 @@
                    public void run() {
                        //推送状态给三方平台
                        tcecClient.pushChargingGunStatus(tChargingGun.getFullNumber(), tChargingGun1.getStatus());
                        pushConnectorStatus(tChargingGun);
                    }
                }).start();
                
@@ -296,6 +311,7 @@
                    public void run() {
                        //推送状态给三方平台
                        tcecClient.pushChargingGunStatus(tChargingGun.getFullNumber(), tChargingGun1.getStatus());
                        pushConnectorStatus(tChargingGun);
                    }
                }).start();
                
@@ -349,6 +365,7 @@
                        public void run() {
                            //推送状态给三方平台
                            tcecClient.pushChargingGunStatus(tChargingGun.getFullNumber(), tChargingGun1.getStatus());
                            pushConnectorStatus(tChargingGun);
                        }
                    }).start();
                }else{
@@ -361,6 +378,7 @@
                        public void run() {
                            //推送状态给三方平台
                            tcecClient.pushChargingGunStatus(tChargingGun.getFullNumber(), tChargingGun1.getStatus());
                            pushConnectorStatus(tChargingGun);
                        }
                    }).start();
                }
@@ -374,5 +392,60 @@
            }
        }
    }
    /**
     * 推送设备接口状态信息
     * @param chargingGun
     */
    private void pushConnectorStatus(TChargingGun chargingGun){
        Site site = siteService.getById(chargingGun.getSiteId());
        if(StringUtils.isNotEmpty(site.getSerAreaCode())){
            ConnectorStatusReq connectorStatusReq = new ConnectorStatusReq();
            connectorStatusReq.setOperatorId("91510903906171535D");
            connectorStatusReq.setSerAreaCode(site.getSerAreaCode());
            connectorStatusReq.setStationId(site.getId().toString());
            List<ConnectorStatusInfo> connectorStatusInfos = new ArrayList<>();
            connectorStatusInfos.add(buildConnectorStatus(chargingGun));
            connectorStatusReq.setItemSize(connectorStatusInfos.size());
            connectorStatusReq.setConnectorStatusInfos(connectorStatusInfos);
            R r = eLuTongClient.pushConnectorStatus(connectorStatusReq);
            if(200 != r.getCode()){
                log.error(r.getMsg());
            }
        }
    }
    private ConnectorStatusInfo buildConnectorStatus(TChargingGun chargingGun){
        ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
        connectorStatusInfo.setConnectorId(chargingGun.getId().toString());
        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.setSoc(0D);
        connectorStatusInfo.setRemainingTime(0);
        return connectorStatusInfo;
    }
}
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
@@ -24,6 +24,8 @@
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.integration.api.elutong.model.*;
import com.ruoyi.integration.api.feignClient.ELuTongClient;
import com.ruoyi.integration.api.feignClient.IntegrationClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.other.api.domain.TVip;
@@ -41,7 +43,11 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -90,6 +96,8 @@
    
    @Resource
    private TCECClient tcecClient;
    @Resource ELuTongClient eLuTongClient;
    
    
    /**
@@ -196,9 +204,176 @@
        }
        site.setMark(0);
        this.save(site);
        if(StringUtils.isNotEmpty(site.getSerAreaCode())){
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
            threadPoolExecutor.execute(()->{
                StationInfoReq stationInfoReq = new StationInfoReq();
                stationInfoReq.setOperatorId("91510903906171535D");
                stationInfoReq.setStationId(site.getId().toString());
                OperatorInfo operatorInfo = new OperatorInfo();
                operatorInfo.setOperatorId("91510903906171535D");
                operatorInfo.setOperatorName("四川明星新能源科技有限公司");
                operatorInfo.setOperatorTel1("18683346252");
                operatorInfo.setOperatorTel2("13982508784");
                operatorInfo.setOperatorRegAddress("遂宁市船山区渠河南路18号");
                stationInfoReq.setOperatorInfo(operatorInfo);
                List<StationInfo> stationInfos = new ArrayList<>();
                stationInfos.add(buildStationInfo(site));
                stationInfoReq.setItemSize(stationInfos.size());
                stationInfoReq.setStationInfos(stationInfos);
                R r = eLuTongClient.pushStationInfo(stationInfoReq);
                if(200 != r.getCode()){
                    System.out.println(r.getMsg());
                }
            });
        }
        return AjaxResult.success();
    }
    private StationInfo buildStationInfo(Site site){
        StationInfo stationInfo = new StationInfo();
        stationInfo.setSerAreaCode(site.getSerAreaCode());
        stationInfo.setOperatorId("91510903906171535D");
        stationInfo.setStationId(site.getId().toString());
        stationInfo.setStationName(site.getName());
        stationInfo.setStationMode("CD");
        stationInfo.setAreaCode(site.getDistrictsCode());
        stationInfo.setServiceTel(site.getServicePhone());
        switch (site.getSiteType()){
            case 0:
                stationInfo.setStationType(255);
                break;
            case 1:
                stationInfo.setStationType(1);
                break;
            case 2:
                stationInfo.setStationType(50);
                break;
            case 3:
                stationInfo.setStationType(100);
                break;
            case 4:
                stationInfo.setStationType(101);
                break;
            case 5:
                stationInfo.setStationType(102);
                break;
            case 6:
                stationInfo.setStationType(103);
                break;
        }
        switch (site.getStatus()){
            case 3:
                stationInfo.setStationStatus(5);
                break;
            case 2:
                stationInfo.setStationStatus(6);
                break;
            case 1:
                stationInfo.setStationStatus(50);
                break;
        }
        stationInfo.setParkNums(site.getParkingSpace());
        stationInfo.setStationLng(Double.parseDouble(site.getLon()));
        stationInfo.setStationLat(Double.parseDouble(site.getLat()));
        stationInfo.setSiteGuide(site.getGuide());
        switch (site.getConstructionSite()){
            case 1:
                stationInfo.setConstruction(1);
                break;
            case 2:
                stationInfo.setConstruction(2);
                break;
            case 3:
                stationInfo.setConstruction(3);
                break;
            case 4:
                stationInfo.setConstruction(4);
                break;
            case 5:
                stationInfo.setConstruction(5);
                break;
            case 6:
                stationInfo.setConstruction(6);
                break;
            case 7:
                stationInfo.setConstruction(7);
                break;
            case 8:
                stationInfo.setConstruction(8);
                break;
            case 9:
                stationInfo.setConstruction(9);
                break;
            case 10:
                stationInfo.setConstruction(10);
                break;
            case 11:
                stationInfo.setConstruction(11);
                break;
            case 0:
                stationInfo.setConstruction(255);
                break;
        }
        if(StringUtils.isNotEmpty(site.getImgUrl())){
            stationInfo.setPictures(Arrays.asList(site.getImgUrl().split(",")));
        }
        stationInfo.setMatchCars(site.getVehicleDescription());
        stationInfo.setBusineHours(site.getStartServiceTime() + " - " + site.getEndServiceTime());
        stationInfo.setEquipmentInfos(buildEquipmentInfo(site));
        return stationInfo;
    }
    private List<EquipmentInfo> buildEquipmentInfo(Site site){
        List<TChargingPile> list = chargingPileService.list(new LambdaQueryWrapper<TChargingPile>()
                .eq(TChargingPile::getSiteId, site.getId()).eq(TChargingPile::getDelFlag, 0));
        return new ArrayList<EquipmentInfo>(){{
            for (TChargingPile chargingPile : list) {
                EquipmentInfo equipmentInfo = new EquipmentInfo();
                equipmentInfo.setEquipmentId(chargingPile.getId().toString());
                equipmentInfo.setEquipmentName(chargingPile.getName());
                equipmentInfo.setManufacturerId(chargingPile.getManufacturerCode());
                equipmentInfo.setManufacturerName(chargingPile.getManufacturer());
                equipmentInfo.setEquipmentModel(chargingPile.getEquipmentType());
                if(null != chargingPile.getProductionDate()){
                    equipmentInfo.setProductionDate(chargingPile.getProductionDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                equipmentInfo.setEquipmentType(0 == chargingPile.getType() ? 5 : chargingPile.getType());
                if(StringUtils.isNotEmpty(chargingPile.getEquipmentLng())){
                    equipmentInfo.setEquipmentLng(Double.parseDouble(chargingPile.getEquipmentLng()));
                }
                if(StringUtils.isNotEmpty(chargingPile.getEquipmentLat())){
                    equipmentInfo.setEquipmentLat(Double.parseDouble(chargingPile.getEquipmentLat()));
                }
                equipmentInfo.setPower(chargingPile.getRatedPower().doubleValue());
                equipmentInfo.setConnectorInfos(buildConnectorInfo(chargingPile));
                add(equipmentInfo);
            }
        }};
    }
    private List<ConnectorInfo> buildConnectorInfo(TChargingPile chargingPile){
        List<TChargingGun> list = chargingGunService.list(new LambdaQueryWrapper<TChargingGun>()
                .eq(TChargingGun::getChargingPileId, chargingPile.getId()).eq(TChargingGun::getDelFlag, 0));
        return new ArrayList<ConnectorInfo>(){{
            for (TChargingGun chargingGun : list) {
                ConnectorInfo connectorInfo = new ConnectorInfo();
                connectorInfo.setConnectorId(chargingGun.getId().toString());
                connectorInfo.setConnectorName(chargingGun.getName());
                connectorInfo.setConnectorType(0 == chargingGun.getType() ? 6 : chargingGun.getType());
                connectorInfo.setVoltageUpperLimits(chargingGun.getUpperRatedVoltage().intValue());
                connectorInfo.setVoltageLowerLimits(chargingGun.getLowerLimitOfRatedVoltage().intValue());
                connectorInfo.setCurrent(chargingGun.getRatedCurrent().intValue());
                connectorInfo.setPower(chargingGun.getRatedPower().doubleValue());
                connectorInfo.setParkNo(chargingGun.getParkingNumber());
                connectorInfo.setNationalStandard(Integer.parseInt(chargingGun.getNationalStandard()));
                add(connectorInfo);
            }
        }};
    }
    
    /**
     * 编辑站点
@@ -227,7 +402,29 @@
        
        this.updateById(site);
        tcecClient.superviseNotificationStationInfo(site.getId());
        if(StringUtils.isNotEmpty(site.getSerAreaCode())){
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
            threadPoolExecutor.execute(()->{
                StationInfoReq stationInfoReq = new StationInfoReq();
                stationInfoReq.setOperatorId("91510903906171535D");
                stationInfoReq.setStationId(site.getId().toString());
                OperatorInfo operatorInfo = new OperatorInfo();
                operatorInfo.setOperatorId("91510903906171535D");
                operatorInfo.setOperatorName("四川明星新能源科技有限公司");
                operatorInfo.setOperatorTel1("18683346252");
                operatorInfo.setOperatorTel2("13982508784");
                operatorInfo.setOperatorRegAddress("遂宁市船山区渠河南路18号");
                stationInfoReq.setOperatorInfo(operatorInfo);
                List<StationInfo> stationInfos = new ArrayList<>();
                stationInfos.add(buildStationInfo(site));
                stationInfoReq.setItemSize(stationInfos.size());
                stationInfoReq.setStationInfos(stationInfos);
                R r = eLuTongClient.pushStationInfo(stationInfoReq);
                if(200 != r.getCode()){
                    System.out.println(r.getMsg());
                }
            });
        }
        return AjaxResult.success();
    }
    
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java
@@ -1,18 +1,32 @@
package com.ruoyi.chargingPile.util;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.chargingPile.api.model.Site;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.chargingPile.service.ISiteService;
import com.ruoyi.chargingPile.service.TChargingGunService;
import com.ruoyi.chargingPile.service.TChargingPileService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.integration.api.elutong.model.*;
import com.ruoyi.integration.api.feignClient.ELuTongClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * 定时任务工具类
 */
@Slf4j
@Component
public class TaskUtil implements ApplicationListener<WebServerInitializedEvent> {
    
@@ -20,6 +34,15 @@
    private TChargingPileService chargingPileService;
    
    private Integer port = null;
    @Resource
    private ELuTongClient eLuTongClient;
    @Resource
    private ISiteService siteService;
    @Resource
    private TChargingGunService chargingGunService;
    
    
    @Override
@@ -35,8 +58,78 @@
    public void taskMinute(){
        if(null != port && port == 5300){
            chargingPileService.updateStatus();
            pushStationsStatus();
        }
    }
    /**
     * 1分钟定时推送设备状态E路通
     */
    private void pushStationsStatus(){
        List<Site> list = siteService.list(new LambdaQueryWrapper<Site>().eq(Site::getDelFlag, 0).isNotNull(Site::getSerAreaCode));
        for (Site site : list) {
            if(StringUtils.isEmpty(site.getSerAreaCode())){
                continue;
            }
            StationsStatusReq stationsStatusReq = new StationsStatusReq();
            stationsStatusReq.setOperatorId("91510903906171535D");
            stationsStatusReq.setSerAreaCode(site.getSerAreaCode());
            stationsStatusReq.setStationId(site.getId().toString());
            List<StationStausInfo> stationStausInfos = new ArrayList<>();
            stationStausInfos.add(buildStationStaus(site));
            stationsStatusReq.setItemSize(stationStausInfos.size());
            stationsStatusReq.setStationStausInfos(stationStausInfos);
            R r = eLuTongClient.pushStationsStatus(stationsStatusReq);
            if(200 != r.getCode()){
                log.error(r.getMsg());
            }
        }
    }
    private StationStausInfo buildStationStaus(Site site){
        StationStausInfo stationStausInfo = new StationStausInfo();
        stationStausInfo.setStationId(site.getId().toString());
        stationStausInfo.setConnectorStatusInfos(buildConnectorStatus(site));
        return stationStausInfo;
    }
    private List<ConnectorStatusInfo> buildConnectorStatus(Site site){
        List<TChargingGun> list = chargingGunService.list(new LambdaQueryWrapper<TChargingGun>().eq(TChargingGun::getDelFlag, 0)
                .eq(TChargingGun::getSiteId, site.getId()));
        return new ArrayList<ConnectorStatusInfo>(){{
            for (TChargingGun chargingGun : list) {
                ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
                connectorStatusInfo.setConnectorId(chargingGun.getId().toString());
                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.setSoc(0D);
                connectorStatusInfo.setRemainingTime(0);
                add(connectorStatusInfo);
            }
        }};
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.jianguan.elutong.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "app.server.config")
public class AppServerConfig {
    //应用ID
    private String appId;
    //应用密码
    private String appSecret;
    //应用公钥
    private String pubKey;
    //应用私钥
    private String priKey;
    //AES秘钥
    private String aesKey;
    //接口地址
    private String serverUrl;
    //验签公钥
    private String signPub;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java
New file
@@ -0,0 +1,130 @@
package com.ruoyi.jianguan.elutong.config;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.*;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.security.cert.X509Certificate;
/**
 * TLS的三个作用:
 * (1)身份认证
 * 通过证书认证来确认对方的身份,防止中间人攻击
 * (2)数据私密性
 * 使用对称性密钥加密传输的数据,由于密钥只有客户端/服务端有,其他人无法窥探。
 * (3)数据完整性
 * 使用摘要算法对报文进行计算,收到消息后校验该值防止数据被篡改或丢失。
 * <p>
 * 使用RestTemplate进行HTTPS请求访问:
 * private static RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());
 */
public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) {
        try {
            if (!(connection instanceof HttpsURLConnection)) {
                throw new RuntimeException("An instance of HttpsURLConnection is expected");
            }
            HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        }
                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        }
                    }
            };
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            httpsConnection.setSSLSocketFactory(new MyCustomSSLSocketFactory(sslContext.getSocketFactory()));
            httpsConnection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
            super.prepareConnection(httpsConnection, httpMethod);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static class MyCustomSSLSocketFactory extends SSLSocketFactory {
        private final SSLSocketFactory delegate;
        public MyCustomSSLSocketFactory(SSLSocketFactory delegate) {
            this.delegate = delegate;
        }
        // 返回默认启用的密码套件。除非一个列表启用,对SSL连接的握手会使用这些密码套件。
        // 这些默认的服务的最低质量要求保密保护和服务器身份验证
        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }
        // 返回的密码套件可用于SSL连接启用的名字
        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        }
        @Override
        public Socket createSocket(final Socket socket, final String host, final int port,
                                   final boolean autoClose) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(socket, host, port, autoClose);
            return overrideProtocol(underlyingSocket);
        }
        @Override
        public Socket createSocket(final String host, final int port) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port);
            return overrideProtocol(underlyingSocket);
        }
        @Override
        public Socket createSocket(final String host, final int port, final InetAddress localAddress,
                                   final int localPort) throws
                IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
            return overrideProtocol(underlyingSocket);
        }
        @Override
        public Socket createSocket(final InetAddress host, final int port) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port);
            return overrideProtocol(underlyingSocket);
        }
        @Override
        public Socket createSocket(final InetAddress host, final int port, final InetAddress localAddress,
                                   final int localPort) throws
                IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
            return overrideProtocol(underlyingSocket);
        }
        private Socket overrideProtocol(final Socket socket) {
            if (!(socket instanceof SSLSocket)) {
                throw new RuntimeException("An instance of SSLSocket is expected");
            }
            //((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"});
            ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
            return socket;
        }
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.jianguan.elutong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestConfigBean {
//    @Bean
//    public RestTemplate getRestTemplate() {
//        return new RestTemplate(new HttpsClientRequestFactory());
//    }
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java
New file
@@ -0,0 +1,341 @@
package com.ruoyi.jianguan.elutong.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.jianguan.elutong.config.AppServerConfig;
import com.ruoyi.jianguan.elutong.core.AESTools;
import com.ruoyi.jianguan.elutong.core.CommonRequest;
import com.ruoyi.jianguan.elutong.core.CommonResponse;
import com.ruoyi.jianguan.elutong.core.SignatureTools;
import com.ruoyi.integration.api.elutong.model.ConnectorStatusReq;
import com.ruoyi.integration.api.elutong.model.StationInfoReq;
import com.ruoyi.integration.api.elutong.model.StationsStatusReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
@RestController
@RequestMapping("/elutong")
public class SampleController {
    @Autowired
    private AppServerConfig appServerConfig;
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 签名
     *
     * @param request
     * @param privateKey
     * @return
     */
    public static CommonRequest sign(CommonRequest request, String privateKey) {
        String signStr = SignatureTools.buildSignStr(request);
        signStr = signStr + "&filename=" + request.getFilename();
        log.info("【E路通】signStr : {}", signStr);
        String sign = SignatureTools.rsa256Sign(signStr, privateKey);
        request.setSign(sign);
        return request;
    }
    /**
     * 验签
     *
     * @param response
     * @return
     */
    public boolean verifySign(CommonResponse response) {
        String signStr = SignatureTools.buildSignStr(response);
        log.info("【E路通】signStr : {}", signStr);
        log.info("【E路通】sign : {}", response.getSign());
        return SignatureTools.rsa256Verify(signStr, appServerConfig.getSignPub(), response.getSign());
    }
    @GetMapping("/test")
    public String test() {
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String filename = "CHARGE_DATA_STATIONINFO_REQ"+"_"+appServerConfig.getAppId()+"_"+format.format(date)+".json";
        //String filename = "SAIS_SERVICEAREA_LPAGE_REQ" + "_" + appServerConfig.getAppId() + "_" + format.format(date) + ".json";
        CommonRequest req = new CommonRequest();
        req.setEncryptType("AES");
        req.setSignType("RSA256");
        req.setFilename(filename);
        format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        req.setTimestamp(format.format(date));
        String requestJson = "{\n" +
        "\"operatorId\":\"91530xxxxK3LK15Y\",\n" +
                "\"operatorInfo\":{\n" +
                "\"operatorId\":\"91530xxxxK3LK15Y\",\n" +
                "\"operatorName\":\"xxx产业发展有限公司\",\n" +
                "\"operatorTel1\":\"0871-61408801\",\n" +
                "\"operatorTel2\":\"0871-61408801\",\n" +
                "\"operatorRegAddress\":\"xxx西山区前卫街道前福路231号\",\n" +
                "\"operatorNote\":null\n" +
                "},\n" +
                "\"stationId\":\"G56-111111-220-2-02819-0-CD-01025001\",\n" +
                "\"serAreaCode\":\"G56-111111-220-2-02819-0\",\n" +
                "\"itemSize\":1,\n" +
                "\"stationInfos\":[\n" +
                "{\n" +
                "\"serAreaCode\":\"G56-111111-220-2-02819-0\",\n" +
                "\"stationId\":\"G56-111111-220-2-02819-0-CD-01025001\",\n" +
                "\"stationMode\":\"CD\",\n" +
                "\"operatorId\":\"915300016K3LK15Y\",\n" +
                "\"stationName\":\"黄草xxx车区上行\",\n" +
                "\"areaCode\":\"510100\",\n" +
                "\"serviceTel\":\"0871-68408801\",\n" +
                "\"stationType\":1,\n" +
                "\"stationStatus\":50,\n" +
                "\"parkNums\":2,\n" +
                "\"stationLng\":98.7116251,\n" +
                "\"stationLat\":24.6117291,\n" +
                "\"siteGuide\":null,\n" +
                "\"construction\":11,\n" +
                "\"pictures\":null,\n" +
                "\"matchCars\":null,\n" +
                "\"businessHours\":\"周一至周日00:00-24:00\",\n" +
                "\"electricityFee\":null,\n" +
                "\"serviceFee\":null,\n" +
                "\"parkFee\":null,\n" +
                "\"payment\":null,\n" +
                "\"supportOrder\":null,\n" +
                "\"equipmentInfos\":[\n" +
                "{\n" +
                "\"equipmentId\":\"02025001\",\n" +
                "\"manufacturerId\":\"11\",\n" +
                "\"manufacturerName\":null,\n" +
                "\"equipmentModel\":null,\n" +
                "\"productionDate\":null,\n" +
                "\"equipmentType\":1,\n" +
                "\"connectorInfos\":[\n" +
                "{\n" +
                "\"connectorId\":\"0202500101\",\n" +
                "\"connectorName\":null,\n" +
                "\"connectorType\":1,\n" +
                "\"voltageUpperLimits\":750,\n" +
                "\"voltageLowerLimits\":150,\n" +
                "\"current\":40,\n" +
                "\"power\":30.0,\n" +
                "\"parkNo\":null,\n" +
                "\"nationalStandard\":2\n" +
                "}\n" +
                "],\n" +
                "\"equipmentLng\":null,\n" +
                "\"equipmentLat\":null,\n" +
                "\"power\":37.0,\n" +
                "\"equipmentName\":null\n" +
                "}\n" +
                "],\n" +
                "\"remark\":null\n" +
                "}\n" +
                "]\n" +
                "}\n";
        //String requestJson = "{\"pageNum\":1,\"pageSize\":700}";
        System.out.println("queryParam : " + requestJson);
        String bizContentJson = AESTools.encrypt(requestJson, appServerConfig.getAesKey());
        req.setBizContent(bizContentJson);
        System.out.println("encrypt CommonRequest toJson : " + JSONObject.toJSONString(req));
        req = sign(req, appServerConfig.getPriKey());
        System.out.println("sign : " + req.getSign());
        System.out.println("request body : " + JSONObject.toJSONString(req));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        String bodyStr = JSONObject.toJSONString(req);
        HttpEntity<String> request = new HttpEntity<String>(bodyStr, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(appServerConfig.getServerUrl(), request, String.class);
        String result = "";
        if (response.getStatusCodeValue() == 200) {
            result = response.getBody();
            System.out.println("response result : " + result);
            CommonResponse commonResponse = JSONObject.parseObject(result, CommonResponse.class);
            if ("200".equals(commonResponse.getStatusCode())) {
                boolean rsa256Verify = verifySign(commonResponse);
                System.out.println("verify sign result : " + rsa256Verify);
            }
        }
        return result;
    }
    /**
     * 推送充电站静态信息
     * @param stationInfoReq
     * @return
     */
    @ResponseBody
    @PostMapping("/pushStationInfo")
    public R pushStationInfo(@RequestBody StationInfoReq stationInfoReq){
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String filename = "CHARGE_DATA_STATIONINFO_REQ_" + appServerConfig.getAppId() + "_" + format.format(date) + ".json";
        CommonRequest req = new CommonRequest();
        req.setEncryptType("AES");
        req.setSignType("RSA256");
        req.setFilename(filename);
        format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        req.setTimestamp(format.format(date));
        String requestJson = JSON.toJSONString(stationInfoReq);
        log.info("【E路通-推送充电站静态信息】queryParam : {}", requestJson);
        String bizContentJson = AESTools.encrypt(requestJson, appServerConfig.getAesKey());
        req.setBizContent(bizContentJson);
        log.info("【E路通-推送充电站静态信息】encrypt CommonRequest toJson : {}", JSONObject.toJSONString(req));
        req = sign(req, appServerConfig.getPriKey());
        log.info("【E路通-推送充电站静态信息】sign : {}", req.getSign());
        log.info("【E路通-推送充电站静态信息】request body : {}", JSONObject.toJSONString(req));
        HttpRequest post = HttpUtil.createPost(appServerConfig.getServerUrl());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        post.header(headers);
        String bodyStr = JSONObject.toJSONString(req);
        post.body(bodyStr);
        HttpResponse execute = post.execute();
        String result = "";
        if (execute.getStatus() == 200) {
            result = execute.body();
            log.info("【E路通-推送充电站静态信息】response result : {}", result);
            CommonResponse commonResponse = JSONObject.parseObject(result, CommonResponse.class);
            if ("200".equals(commonResponse.getStatusCode())) {
                boolean rsa256Verify = verifySign(commonResponse);
                log.info("【E路通-推送充电站静态信息】verify sign result : {}", rsa256Verify);
                return R.ok();
            }else{
                return R.fail(commonResponse.getErrorMsg());
            }
        }
        return R.fail("推送接口请求失败");
    }
    /**
     * 推送充电站状态信息
     * @param stationsStatusReq
     * @return
     */
    @ResponseBody
    @PostMapping("/pushStationsStatus")
    public R pushStationsStatus(@RequestBody StationsStatusReq stationsStatusReq){
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String filename = "CHARGE_DATA_STATIONSTATUS_REQ_" + appServerConfig.getAppId() + "_" + format.format(date) + ".json";
        CommonRequest req = new CommonRequest();
        req.setEncryptType("AES");
        req.setSignType("RSA256");
        req.setFilename(filename);
        format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        req.setTimestamp(format.format(date));
        String requestJson = JSON.toJSONString(stationsStatusReq);
        log.info("【E路通-推送充电站状态信息】queryParam : {}", requestJson);
        String bizContentJson = AESTools.encrypt(requestJson, appServerConfig.getAesKey());
        req.setBizContent(bizContentJson);
        log.info("【E路通-推送充电站状态信息】encrypt CommonRequest toJson : {}", JSONObject.toJSONString(req));
        req = sign(req, appServerConfig.getPriKey());
        log.info("【E路通-推送充电站状态信息】sign : {}", req.getSign());
        log.info("【E路通-推送充电站状态信息】request body : {}", JSONObject.toJSONString(req));
        HttpRequest post = HttpUtil.createPost(appServerConfig.getServerUrl());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        post.header(headers);
        String bodyStr = JSONObject.toJSONString(req);
        post.body(bodyStr);
        HttpResponse execute = post.execute();
        String result = "";
        if (execute.getStatus() == 200) {
            result = execute.body();
            log.info("【E路通-推送充电站状态信息】response result : {}", result);
            CommonResponse commonResponse = JSONObject.parseObject(result, CommonResponse.class);
            if ("200".equals(commonResponse.getStatusCode())) {
                boolean rsa256Verify = verifySign(commonResponse);
                log.info("【E路通-推送充电站状态信息】verify sign result : {}", rsa256Verify);
                return R.ok();
            }else{
                return R.fail(commonResponse.getErrorMsg());
            }
        }
        return R.fail("推送接口请求失败");
    }
    /**
     * 推送设备接口状态信息
     * @param connectorStatusReq
     * @return
     */
    @ResponseBody
    @PostMapping("/pushConnectorStatus")
    public R pushConnectorStatus(@RequestBody ConnectorStatusReq connectorStatusReq){
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String filename = "CHARGE_NOTIFICATION_CONNECTORSTAUS_REQ_" + appServerConfig.getAppId() + "_" + format.format(date) + ".json";
        CommonRequest req = new CommonRequest();
        req.setEncryptType("AES");
        req.setSignType("RSA256");
        req.setFilename(filename);
        format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        req.setTimestamp(format.format(date));
        String requestJson = JSON.toJSONString(connectorStatusReq);
        log.info("【E路通-推送设备接口状态信息】queryParam : {}", requestJson);
        String bizContentJson = AESTools.encrypt(requestJson, appServerConfig.getAesKey());
        req.setBizContent(bizContentJson);
        log.info("【E路通-推送设备接口状态信息】encrypt CommonRequest toJson : {}", JSONObject.toJSONString(req));
        req = sign(req, appServerConfig.getPriKey());
        log.info("【E路通-推送设备接口状态信息】sign : {}", req.getSign());
        log.info("【E路通-推送设备接口状态信息】request body : {}", JSONObject.toJSONString(req));
        HttpRequest post = HttpUtil.createPost(appServerConfig.getServerUrl());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        post.header(headers);
        String bodyStr = JSONObject.toJSONString(req);
        post.body(bodyStr);
        HttpResponse execute = post.execute();
        String result = "";
        if (execute.getStatus() == 200) {
            result = execute.body();
            log.info("【E路通-推送设备接口状态信息】response result : {}", result);
            CommonResponse commonResponse = JSONObject.parseObject(result, CommonResponse.class);
            if ("200".equals(commonResponse.getStatusCode())) {
                boolean rsa256Verify = verifySign(commonResponse);
                log.info("【E路通-推送设备接口状态信息】verify sign result : {}", rsa256Verify);
                return R.ok();
            }else{
                return R.fail(commonResponse.getErrorMsg());
            }
        }
        return R.fail("推送接口请求失败");
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java
New file
@@ -0,0 +1,69 @@
package com.ruoyi.jianguan.elutong.core;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESTools {
    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";// 默认的加密算法
    /**
     * AES 加密操作
     *
     * @param content  待加密内容
     * @param password 加密密码
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String password) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return Base64Tools.encodeToString(result);// 通过Base64转码返回
        } catch (Exception ex) {
            LoggerFactory.getLogger(AESTools.class).error("", ex);
            throw new RuntimeException("AES加密失败:" + content);
        }
    }
    /**
     * AES 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {
        try {
            // 实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            // 使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
            // 执行操作
            byte[] result = cipher.doFinal(Base64Tools.decodeFromString(content));
            return new String(result, "utf-8");
        } catch (Exception ex) {
            LoggerFactory.getLogger(AESTools.class).error("", ex);
            throw new RuntimeException("AES解密失败:" + content);
        }
    }
    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String password) {
        try {
            return new SecretKeySpec(password.getBytes("UTF-8"), KEY_ALGORITHM);// 转换为AES专用密钥
        } catch (Exception ex) {
            LoggerFactory.getLogger(AESTools.class).error("", ex);
            throw new RuntimeException("生成加密秘钥");
        }
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java
New file
@@ -0,0 +1,111 @@
package com.ruoyi.jianguan.elutong.core;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public abstract class Base64Tools {
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    /**
     * Base64-encode the given byte array.
     *
     * @param src the original byte array
     * @return the encoded byte array
     */
    public static byte[] encode(byte[] src) {
        if (src.length == 0) {
            return src;
        }
        return Base64.getEncoder().encode(src);
    }
    /**
     * Base64-decode the given byte array.
     *
     * @param src the encoded byte array
     * @return the original byte array
     */
    public static byte[] decode(byte[] src) {
        if (src.length == 0) {
            return src;
        }
        return Base64.getDecoder().decode(src);
    }
    /**
     * Base64-encode the given byte array using the RFC 4648 "URL and Filename Safe Alphabet".
     *
     * @param src the original byte array
     * @return the encoded byte array
     * @since 4.2.4
     */
    public static byte[] encodeUrlSafe(byte[] src) {
        if (src.length == 0) {
            return src;
        }
        return Base64.getUrlEncoder().encode(src);
    }
    /**
     * Base64-decode the given byte array using the RFC 4648 "URL and Filename Safe Alphabet".
     *
     * @param src the encoded byte array
     * @return the original byte array
     * @since 4.2.4
     */
    public static byte[] decodeUrlSafe(byte[] src) {
        if (src.length == 0) {
            return src;
        }
        return Base64.getUrlDecoder().decode(src);
    }
    /**
     * Base64-encode the given byte array to a String.
     *
     * @param src the original byte array (may be {@code null})
     * @return the encoded byte array as a UTF-8 String
     */
    public static String encodeToString(byte[] src) {
        if (src.length == 0) {
            return "";
        }
        return new String(encode(src), DEFAULT_CHARSET);
    }
    /**
     * Base64-decode the given byte array from an UTF-8 String.
     *
     * @param src the encoded UTF-8 String
     * @return the original byte array
     */
    public static byte[] decodeFromString(String src) {
        if (src.isEmpty()) {
            return new byte[0];
        }
        return decode(src.getBytes(DEFAULT_CHARSET));
    }
    /**
     * Base64-encode the given byte array to a String using the RFC 4648 "URL and Filename Safe Alphabet".
     *
     * @param src the original byte array
     * @return the encoded byte array as a UTF-8 String
     */
    public static String encodeToUrlSafeString(byte[] src) {
        return new String(encodeUrlSafe(src), DEFAULT_CHARSET);
    }
    /**
     * Base64-decode the given byte array from an UTF-8 String using the RFC 4648 "URL and Filename Safe Alphabet".
     *
     * @param src the encoded UTF-8 String
     * @return the original byte array
     */
    public static byte[] decodeFromUrlSafeString(String src) {
        return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET));
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.jianguan.elutong.core;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CommonRequest {
    private String encryptType;
    private String signType;
    private String filename;
    private String bizContent;
    private String sign;
    private String timestamp;
    private String version = "1.0";
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java
New file
@@ -0,0 +1,12 @@
package com.ruoyi.jianguan.elutong.core;
import lombok.Data;
@Data
public class CommonResponse {
    private String bizContent;
    private String errorMsg;
    private String sign;
    private String statusCode;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi.jianguan.elutong.core;
/**
 * 签名算法类型
 */
public enum SignAlgorithm {
    // The RSA signature algorithm
    NONEwithRSA("NONEwithRSA", "RSA"),
    // The MD2/MD5 with RSA Encryption signature algorithm
    MD2withRSA("MD2withRSA", "RSA"),
    MD5withRSA("MD5withRSA", "RSA"),
    // The signature algorithm with SHA-* and the RSA
    SHA1withRSA("SHA1withRSA", "RSA"),
    SHA256withRSA("SHA256withRSA", "RSA"),
    SHA384withRSA("SHA384withRSA", "RSA"),
    SHA512withRSA("SHA512withRSA", "RSA"),
    // The Digital Signature Algorithm
    NONEwithDSA("NONEwithDSA", "DSA"),
    // The DSA with SHA-1 signature algorithm
    SHA1withDSA("SHA1withDSA", "DSA"),
    // The ECDSA signature algorithms
    NONEwithECDSA("NONEwithECDSA", "EC"),
    SHA1withECDSA("SHA1withECDSA", "EC"),
    SHA256withECDSA("SHA256withECDSA", "EC"),
    SHA384withECDSA("SHA384withECDSA", "EC"),
    SHA512withECDSA("SHA512withECDSA", "EC");
    private String value;
    private String type;
    /**
     * 构造
     *
     * @param value 算法字符表示,区分大小写
     * @param type  XXXwithXXX算法的后半部分算法,如果为ECDSA,返回算法为EC
     */
    private SignAlgorithm(String value, String type) {
        this.value = value;
        this.type = type;
    }
    /**
     * 获取算法字符串表示,区分大小写
     *
     * @return 算法字符串表示
     */
    public String getValue() {
        return this.value;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java
New file
@@ -0,0 +1,135 @@
package com.ruoyi.jianguan.elutong.core;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class SignatureTools {
    public static final String PUBLIC_KEY = "RSAPublicKey";
    public static final String PRIVATE_KEY = "RSAPrivateKey";
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    /**
     * sha256WithRsa 加签
     *
     * @param content      待签名的字符串
     * @param priKeyBase64 base64编码的私钥
     * @return base64编码的签名
     */
    public static String rsa256Sign(String content, String priKeyBase64) {
        byte[] signed = sign(SignAlgorithm.SHA256withRSA, content.getBytes(DEFAULT_CHARSET), Base64Tools.decodeFromString(priKeyBase64));
        return Base64Tools.encodeToString(signed);
    }
    /**
     * sha256WithRsa 验签
     *
     * @param content      待验签的字符串
     * @param pubKeyBase64 base64编码的公钥
     * @param signBase64   base64编码签名
     * @return 签名是否正确
     */
    public static boolean rsa256Verify(String content, String pubKeyBase64, String signBase64) {
        return verify(SignAlgorithm.SHA256withRSA, content.getBytes(DEFAULT_CHARSET),
                Base64Tools.decodeFromString(signBase64), Base64Tools.decodeFromString(pubKeyBase64));
    }
    public static byte[] sign(SignAlgorithm algorithm, byte[] content, byte[] key) {
        try {
            PrivateKey priKey = generatePrivateKey(algorithm, key);
            Signature signature = Signature.getInstance(algorithm.getValue());
            signature.initSign(priKey);
            signature.update(content);
            byte[] signed = signature.sign();
            return signed;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static boolean verify(SignAlgorithm algorithm, byte[] content, byte[] sign, byte[] key) {
        try {
            Signature signature = Signature.getInstance(algorithm.getValue());
            PublicKey publicKey = generatePublicKey(algorithm, key);
            signature.initVerify(publicKey);
            signature.update(content);
            return signature.verify(sign);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public static PrivateKey generatePrivateKey(SignAlgorithm algorithmType, byte[] key)
            throws InvalidKeySpecException, NoSuchAlgorithmException {
        return generatePrivateKey(algorithmType, new PKCS8EncodedKeySpec(key));
    }
    public static PrivateKey generatePrivateKey(SignAlgorithm algorithmType, KeySpec keySpec)
            throws InvalidKeySpecException, NoSuchAlgorithmException {
        return KeyFactory.getInstance(algorithmType.getType()).generatePrivate(keySpec);
    }
    public static PublicKey generatePublicKey(SignAlgorithm algorithm, byte[] key)
            throws InvalidKeySpecException, NoSuchAlgorithmException {
        return generatePublicKey(algorithm, new X509EncodedKeySpec(key));
    }
    public static PublicKey generatePublicKey(SignAlgorithm algorithm, KeySpec keySpec)
            throws InvalidKeySpecException, NoSuchAlgorithmException {
        return KeyFactory.getInstance(algorithm.getType()).generatePublic(keySpec);
    }
    public static String buildSignStr(Object object) {
        if (object == null) {
            return null;
        }
        Map map = new HashMap();
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            try {
                if ("sign".equals(field.getName())) {
                    continue;
                }
                if ("filename".equals(field.getName())) {
                    continue;
                }
                map.put(field.getName(), field.get(object));
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        TreeMap<String, String> treeMap = new TreeMap<>(map);
        StringBuffer strBuffer = new StringBuffer();
        treeMap.entrySet().forEach(i -> {
            if (i.getValue() == null) {
                return;
            }
            if (StringUtils.isBlank(i.getValue())) {
                return;
            }
            strBuffer.append(i.getKey()).append("=").append(String.valueOf(i.getValue())).append("&");
        });
        String signStr = strBuffer.substring(0, strBuffer.length() - 1);
        return signStr;
    }
}