From db0b7644a9a5a62ac2da3cf571fee41bb8b6974f Mon Sep 17 00:00:00 2001
From: Pu Zhibing <393733352@qq.com>
Date: 星期四, 25 九月 2025 15:54:15 +0800
Subject: [PATCH] 添加E路通推送数据功能
---
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java | 40 +
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java | 6
ruoyi-service/ruoyi-chargingPile/pom.xml | 4
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java | 30
ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | 3
pom.xml | 7
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java | 26
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java | 12
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java | 43 +
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java | 64 ++
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java | 36 +
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java | 130 ++++
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java | 97 +++
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java | 145 ++++
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java | 16
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java | 51 +
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java | 32 +
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java | 61 +
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java | 36 +
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java | 135 ++++
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java | 79 ++
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java | 201 ++++++
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java | 20
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java | 32 +
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java | 69 ++
ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java | 18
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java | 341 +++++++++++
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java | 111 +++
28 files changed, 1,837 insertions(+), 8 deletions(-)
diff --git a/pom.xml b/pom.xml
index dba8ee3..3f8b860 100644
--- a/pom.xml
+++ b/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>
diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java
index 5b58570..9ca22ef 100644
--- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/model/Site.java
+++ b/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;
// /**
// * 换电设备信息
// */
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java
new file mode 100644
index 0000000..0fc7224
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java
new file mode 100644
index 0000000..510fcc3
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java
new file mode 100644
index 0000000..64fd0ec
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/ConnectorStatusReq.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java
new file mode 100644
index 0000000..f821eb1
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/EquipmentInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java
new file mode 100644
index 0000000..3cde73e
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/OperatorInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java
new file mode 100644
index 0000000..8f5db62
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java
new file mode 100644
index 0000000..04a314a
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationInfoReq.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java
new file mode 100644
index 0000000..8711fc2
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationStausInfo.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java
new file mode 100644
index 0000000..38de087
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/elutong/model/StationsStatusReq.java
@@ -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;
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java
new file mode 100644
index 0000000..96cc0ed
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/factory/ELuTongClientFallbackFactory.java
@@ -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());
+ }
+ };
+ }
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java
new file mode 100644
index 0000000..d119974
--- /dev/null
+++ b/ruoyi-api/ruoyi-api-jianguan/src/main/java/com/ruoyi/integration/api/feignClient/ELuTongClient.java
@@ -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);
+}
diff --git a/ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 3538350..ffd095b 100644
--- a/ruoyi-api/ruoyi-api-jianguan/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/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
\ No newline at end of file
+com.ruoyi.integration.api.factory.ChargingMessageClientFallbackFactory
+com.ruoyi.integration.api.factory.ELuTongClientFallbackFactory
\ No newline at end of file
diff --git a/ruoyi-service/ruoyi-chargingPile/pom.xml b/ruoyi-service/ruoyi-chargingPile/pom.xml
index 07f0e31..adabae8 100644
--- a/ruoyi-service/ruoyi-chargingPile/pom.xml
+++ b/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>
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java
index 90ec317..2df41df 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java
+++ b/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;
+ }
}
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
index ed2cadc..4347bdb 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
+++ b/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();
}
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java
index a463b33..af9be75 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/util/TaskUtil.java
+++ b/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);
+ }
+ }};
+ }
}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java
new file mode 100644
index 0000000..af337a4
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/AppServerConfig.java
@@ -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;
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java
new file mode 100644
index 0000000..b1438a5
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/HttpsClientRequestFactory.java
@@ -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;
+ }
+ }
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java
new file mode 100644
index 0000000..affa36a
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/config/RestConfigBean.java
@@ -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();
+ }
+
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java
new file mode 100644
index 0000000..6e613f0
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/controller/SampleController.java
@@ -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("推送接口请求失败");
+ }
+
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java
new file mode 100644
index 0000000..80ec58f
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/AESTools.java
@@ -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("生成加密秘钥");
+ }
+ }
+
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java
new file mode 100644
index 0000000..3e81600
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/Base64Tools.java
@@ -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));
+ }
+
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java
new file mode 100644
index 0000000..9541b9f
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonRequest.java
@@ -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";
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java
new file mode 100644
index 0000000..8895a3a
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/CommonResponse.java
@@ -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;
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java
new file mode 100644
index 0000000..edca3b1
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignAlgorithm.java
@@ -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;
+ }
+
+}
diff --git a/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java
new file mode 100644
index 0000000..8619067
--- /dev/null
+++ b/ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/elutong/core/SignatureTools.java
@@ -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;
+ }
+
+
+}
--
Gitblit v1.7.1