|
|
@@ -1,33 +1,59 @@
|
|
|
package com.zsElectric.boot.charging.service.impl;
|
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.zsElectric.boot.business.mapper.ChargeOrderInfoMapper;
|
|
|
+import com.zsElectric.boot.business.mapper.PolicyFeeMapper;
|
|
|
+import com.zsElectric.boot.business.mapper.UserAccountMapper;
|
|
|
+import com.zsElectric.boot.business.mapper.UserFirmMapper;
|
|
|
+import com.zsElectric.boot.business.model.entity.ChargeOrderInfo;
|
|
|
+import com.zsElectric.boot.business.model.entity.UserAccount;
|
|
|
+import com.zsElectric.boot.business.model.entity.UserFirm;
|
|
|
import com.zsElectric.boot.charging.entity.ConnectorStatusInfo;
|
|
|
import com.zsElectric.boot.charging.entity.StationStatusInfo;
|
|
|
+import com.zsElectric.boot.charging.entity.ThirdPartyChargeStatus;
|
|
|
import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
|
|
|
+import com.zsElectric.boot.charging.mapper.ThirdPartyChargeStatusMapper;
|
|
|
import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
|
|
|
import com.zsElectric.boot.charging.service.ChargingReceptionService;
|
|
|
-import com.zsElectric.boot.charging.vo.*;
|
|
|
+import com.zsElectric.boot.charging.vo.ChargeResponseVO;
|
|
|
+import com.zsElectric.boot.charging.vo.QueryStationStatusVO;
|
|
|
import com.zsElectric.boot.common.constant.ConnectivityConstants;
|
|
|
import com.zsElectric.boot.common.util.electric.ChargingUtil;
|
|
|
import com.zsElectric.boot.common.util.electric.RequestParmsEntity;
|
|
|
import com.zsElectric.boot.common.util.electric.ResponseParmsEntity;
|
|
|
import com.zsElectric.boot.core.exception.BusinessException;
|
|
|
+import com.zsElectric.boot.system.mapper.DictItemMapper;
|
|
|
+import com.zsElectric.boot.system.model.entity.DictItem;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
+import org.redisson.api.RLock;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.function.Consumer;
|
|
|
|
|
|
import static com.zsElectric.boot.common.constant.ConnectivityConstants.FAIL_REASON_NONE;
|
|
|
import static com.zsElectric.boot.common.constant.ConnectivityConstants.STATUS_OK;
|
|
|
import static com.zsElectric.boot.common.util.HmacMD5Util.genSign;
|
|
|
import static com.zsElectric.boot.common.util.HmacMD5Util.verify;
|
|
|
|
|
|
+/**
|
|
|
+ * 第三方充电推送接收服务实现
|
|
|
+ *
|
|
|
+ * @author system
|
|
|
+ * @since 2025-12-11
|
|
|
+ */
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@RequiredArgsConstructor
|
|
|
@@ -35,226 +61,323 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
|
|
|
|
|
|
private final ChargingUtil chargingUtil;
|
|
|
private final ThirdPartyConnectorInfoMapper connectorInfoMapper;
|
|
|
-
|
|
|
- private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ private final ThirdPartyChargeStatusMapper chargeStatusMapper;
|
|
|
+ private final ObjectMapper objectMapper;
|
|
|
+ private final ChargeOrderInfoMapper chargeOrderInfoMapper;
|
|
|
+ private final RedissonClient redissonClient;
|
|
|
+ private final UserAccountMapper userAccountMapper;
|
|
|
+ private final UserFirmMapper userFirmMapper;
|
|
|
+ private final PolicyFeeMapper policyFeeMapper;
|
|
|
+ private final DictItemMapper dictItemMapper;
|
|
|
+
|
|
|
+ /** 熔断检查锁前缀 */
|
|
|
+ private static final String BREAK_CHECK_LOCK_KEY = "charging:break:check:";
|
|
|
+ /** 锁等待时间(秒) */
|
|
|
+ private static final long LOCK_WAIT_TIME = 3;
|
|
|
+ /** 锁持有时间(秒) */
|
|
|
+ private static final long LOCK_LEASE_TIME = 10;
|
|
|
+
|
|
|
+ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+
|
|
|
+ // ==================== 接口实现 ====================
|
|
|
|
|
|
@Override
|
|
|
public ResponseParmsEntity chargeResponse(RequestParmsEntity requestDTO) {
|
|
|
log.info("接收推送启动充电结果请求参数:{}", requestDTO);
|
|
|
- ChargingStatusResponseVO chargingStatusResponseVO;
|
|
|
- // 响应参数 答复处理
|
|
|
- ChargeResponseVO chargeResponseVO = new ChargeResponseVO();
|
|
|
- String encryptData;
|
|
|
- String genSign;
|
|
|
- try {
|
|
|
- String data = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
- if(verify(data, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())){
|
|
|
- String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
- log.info("解密后的数据:{}", decryptData);
|
|
|
- JsonNode jsonNode = objectMapper.readTree(decryptData);
|
|
|
-// equipChargeStatusResponseVO = objectMapper.readValue(decryptData, EquipChargeStatusResponseVO.class);
|
|
|
- //todo 业务代码待处理
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- chargeResponseVO.setStartChargeSeq(jsonNode.get("StartChargeSeq").asText());
|
|
|
-// chargeResponseVO.setStartChargeSeq(equipChargeStatusResponseVO.getStartChargeSeq());
|
|
|
- chargeResponseVO.setSuccStat(STATUS_OK);
|
|
|
- chargeResponseVO.setFailReason(FAIL_REASON_NONE);
|
|
|
- encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(chargeResponseVO));
|
|
|
- genSign = genSign(STATUS_OK, "请求成功", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
- }else {
|
|
|
- log.error("数据验签失败");
|
|
|
- throw new BusinessException("数据验签失败");
|
|
|
- }
|
|
|
- }catch (Exception e){
|
|
|
- log.error("数据解密失败:{}", e.getMessage());
|
|
|
- throw new BusinessException("数据解密失败:" + e.getMessage(), e);
|
|
|
- }
|
|
|
- ResponseParmsEntity responseParmsEntity = new ResponseParmsEntity();
|
|
|
- responseParmsEntity.setRet(STATUS_OK);
|
|
|
- responseParmsEntity.setMsg("请求成功");
|
|
|
- responseParmsEntity.setData(encryptData);
|
|
|
- responseParmsEntity.setSig(genSign);
|
|
|
- return responseParmsEntity;
|
|
|
-
|
|
|
+ return processChargeRequest(requestDTO, jsonNode -> {
|
|
|
+ // TODO: 启动充电结果业务处理
|
|
|
+ log.debug("启动充电结果 - StartChargeSeq: {}", getTextValue(jsonNode, "StartChargeSeq"));
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public ResponseParmsEntity chargeStatusResponse(RequestParmsEntity requestDTO) {
|
|
|
log.info("接收推送充电状态请求参数:{}", requestDTO);
|
|
|
- EquipChargeStatusResponseVO equipChargeStatusResponseVO;
|
|
|
- ChargeResponseVO chargeResponseVO = new ChargeResponseVO();
|
|
|
- String encryptData;
|
|
|
- String genSign;
|
|
|
+ return processChargeRequest(requestDTO, this::saveOrUpdateChargeStatus);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResponseParmsEntity stopChargeResponse(RequestParmsEntity requestDTO) {
|
|
|
+ log.info("接收推送停止充电结果请求参数:{}", requestDTO);
|
|
|
+ return processChargeRequest(requestDTO, jsonNode -> {
|
|
|
+ // TODO: 停止充电结果业务处理
|
|
|
+ log.debug("停止充电结果 - StartChargeSeq: {}", getTextValue(jsonNode, "StartChargeSeq"));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResponseParmsEntity chargeOrderResponse(RequestParmsEntity requestDTO) {
|
|
|
+ log.info("接收推送充电订单信息请求参数:{}", requestDTO);
|
|
|
+ return processChargeRequest(requestDTO, jsonNode -> {
|
|
|
+ // TODO: 充电订单信息业务处理
|
|
|
+ log.debug("充电订单信息 - StartChargeSeq: {}", getTextValue(jsonNode, "StartChargeSeq"));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResponseParmsEntity stationStatus(RequestParmsEntity requestDTO) {
|
|
|
+ log.info("接收设备状态变化推送请求参数:{}", requestDTO);
|
|
|
+ return processStationStatusRequest(requestDTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 公共处理方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用充电请求处理模板
|
|
|
+ */
|
|
|
+ private ResponseParmsEntity processChargeRequest(RequestParmsEntity requestDTO, Consumer<JsonNode> businessHandler) {
|
|
|
try {
|
|
|
- String data = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
- if(verify(data, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())){
|
|
|
- String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
- log.info("解密后的数据:{}", decryptData);
|
|
|
- JsonNode jsonNode = objectMapper.readTree(decryptData);
|
|
|
-// equipChargeStatusResponseVO = objectMapper.readValue(decryptData, EquipChargeStatusResponseVO.class);
|
|
|
- //todo 业务代码待处理
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- chargeResponseVO.setStartChargeSeq(jsonNode.get("StartChargeSeq").asText());
|
|
|
-// chargeResponseVO.setStartChargeSeq(equipChargeStatusResponseVO.getStartChargeSeq());
|
|
|
- chargeResponseVO.setSuccStat(STATUS_OK);
|
|
|
- chargeResponseVO.setFailReason(FAIL_REASON_NONE);
|
|
|
- encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(chargeResponseVO));
|
|
|
- genSign = genSign(STATUS_OK, "请求成功", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
- }else {
|
|
|
- log.error("数据验签失败");
|
|
|
- throw new BusinessException("数据验签失败");
|
|
|
- }
|
|
|
+ JsonNode jsonNode = verifyAndDecrypt(requestDTO);
|
|
|
+
|
|
|
+ // 执行业务处理
|
|
|
+ businessHandler.accept(jsonNode);
|
|
|
+
|
|
|
+ // 构建响应
|
|
|
+ return buildChargeResponse(getTextValue(jsonNode, "StartChargeSeq"));
|
|
|
+ } catch (BusinessException e) {
|
|
|
+ throw e;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理请求失败:{}", e.getMessage());
|
|
|
+ throw new BusinessException("处理请求失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理设备状态变化推送请求
|
|
|
+ */
|
|
|
+ private ResponseParmsEntity processStationStatusRequest(RequestParmsEntity requestDTO) {
|
|
|
+ try {
|
|
|
+ String decryptData = verifyAndDecryptRaw(requestDTO);
|
|
|
+
|
|
|
+ // 解析并更新设备状态
|
|
|
+ QueryStationStatusVO stationStatusVO = objectMapper.readValue(decryptData, QueryStationStatusVO.class);
|
|
|
+ updateConnectorStatus(stationStatusVO);
|
|
|
+
|
|
|
+ // 构建响应
|
|
|
+ return buildStatusResponse();
|
|
|
+ } catch (BusinessException e) {
|
|
|
+ throw e;
|
|
|
} catch (Exception e) {
|
|
|
- log.error("数据解密失败:{}", e.getMessage());
|
|
|
- throw new BusinessException("数据解密失败:" + e.getMessage(), e);
|
|
|
+ log.error("处理设备状态推送失败:{}", e.getMessage());
|
|
|
+ throw new BusinessException("处理设备状态推送失败:" + e.getMessage(), e);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- ResponseParmsEntity responseParmsEntity = new ResponseParmsEntity();
|
|
|
- responseParmsEntity.setRet(STATUS_OK);
|
|
|
- responseParmsEntity.setMsg("请求成功");
|
|
|
- responseParmsEntity.setData(encryptData);
|
|
|
- responseParmsEntity.setSig(genSign);
|
|
|
- return responseParmsEntity;
|
|
|
+ /**
|
|
|
+ * 验签并解密请求数据
|
|
|
+ */
|
|
|
+ private JsonNode verifyAndDecrypt(RequestParmsEntity requestDTO) throws Exception {
|
|
|
+ String decryptData = verifyAndDecryptRaw(requestDTO);
|
|
|
+ return objectMapper.readTree(decryptData);
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 验签并解密请求数据(返回原始字符串)
|
|
|
+ */
|
|
|
+ private String verifyAndDecryptRaw(RequestParmsEntity requestDTO) throws Exception {
|
|
|
+ String signData = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
+ if (!verify(signData, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())) {
|
|
|
+ log.error("数据验签失败");
|
|
|
+ throw new BusinessException("数据验签失败");
|
|
|
+ }
|
|
|
+ String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
+ log.info("解密后的数据:{}", decryptData);
|
|
|
+ return decryptData;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public ResponseParmsEntity stopChargeResponse(RequestParmsEntity requestDTO) {
|
|
|
- log.info("接收推送停止充电结果请求参数:{}", requestDTO);
|
|
|
- StopChargingResponseVO stopChargingResponseVO;
|
|
|
+ // ==================== 响应构建 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建充电响应
|
|
|
+ */
|
|
|
+ private ResponseParmsEntity buildChargeResponse(String startChargeSeq) throws Exception {
|
|
|
ChargeResponseVO chargeResponseVO = new ChargeResponseVO();
|
|
|
- String encryptData;
|
|
|
- String genSign;
|
|
|
+ chargeResponseVO.setStartChargeSeq(startChargeSeq);
|
|
|
+ chargeResponseVO.setSuccStat(STATUS_OK);
|
|
|
+ chargeResponseVO.setFailReason(FAIL_REASON_NONE);
|
|
|
+
|
|
|
+ String encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(chargeResponseVO));
|
|
|
+ String sign = genSign(STATUS_OK, "请求成功", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
+
|
|
|
+ ResponseParmsEntity response = new ResponseParmsEntity();
|
|
|
+ response.setRet(STATUS_OK);
|
|
|
+ response.setMsg("请求成功");
|
|
|
+ response.setData(encryptData);
|
|
|
+ response.setSig(sign);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建设备状态响应
|
|
|
+ */
|
|
|
+ private ResponseParmsEntity buildStatusResponse() throws Exception {
|
|
|
+ Map<String, Integer> statusMap = new HashMap<>();
|
|
|
+ statusMap.put("Status", 0);
|
|
|
+
|
|
|
+ String encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(statusMap));
|
|
|
+ String sign = genSign(STATUS_OK, "", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
+
|
|
|
+ ResponseParmsEntity response = new ResponseParmsEntity();
|
|
|
+ response.setRet(STATUS_OK);
|
|
|
+ response.setMsg("");
|
|
|
+ response.setData(encryptData);
|
|
|
+ response.setSig(sign);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 状态更新 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新充电接口状态
|
|
|
+ */
|
|
|
+ private void updateConnectorStatus(QueryStationStatusVO stationStatusVO) {
|
|
|
+ if (stationStatusVO == null || CollectionUtils.isEmpty(stationStatusVO.getStationStatusInfos())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (StationStatusInfo stationStatusInfo : stationStatusVO.getStationStatusInfos()) {
|
|
|
+ List<ConnectorStatusInfo> connectorStatusInfos = stationStatusInfo.getConnectorStatusInfos();
|
|
|
+ if (CollectionUtils.isEmpty(connectorStatusInfos)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (ConnectorStatusInfo connectorStatus : connectorStatusInfos) {
|
|
|
+ connectorInfoMapper.update(null, Wrappers.<ThirdPartyConnectorInfo>lambdaUpdate()
|
|
|
+ .eq(ThirdPartyConnectorInfo::getConnectorId, connectorStatus.getConnectorID())
|
|
|
+ .set(ThirdPartyConnectorInfo::getStatus, connectorStatus.getStatus()));
|
|
|
+ log.debug("更新充电接口状态 - connectorId: {}, status: {}",
|
|
|
+ connectorStatus.getConnectorID(), connectorStatus.getStatus());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存或更新充电状态数据
|
|
|
+ */
|
|
|
+ private void saveOrUpdateChargeStatus(JsonNode jsonNode) {
|
|
|
try {
|
|
|
- String data = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
- if(verify(data, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())){
|
|
|
- String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
- log.info("解密后的数据:{}", decryptData);
|
|
|
- JsonNode jsonNode = objectMapper.readTree(decryptData);
|
|
|
-// equipChargeStatusResponseVO = objectMapper.readValue(decryptData, EquipChargeStatusResponseVO.class);
|
|
|
- //todo 业务代码待处理
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- chargeResponseVO.setStartChargeSeq(jsonNode.get("StartChargeSeq").asText());
|
|
|
-// chargeResponseVO.setStartChargeSeq(equipChargeStatusResponseVO.getStartChargeSeq());
|
|
|
- chargeResponseVO.setSuccStat(STATUS_OK);
|
|
|
- chargeResponseVO.setFailReason(FAIL_REASON_NONE);
|
|
|
- encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(chargeResponseVO));
|
|
|
- genSign = genSign(STATUS_OK, "请求成功", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
- }else {
|
|
|
- log.error("数据验签失败");
|
|
|
- throw new BusinessException("数据验签失败");
|
|
|
+ String startChargeSeq = jsonNode.get("StartChargeSeq").asText();
|
|
|
+
|
|
|
+ // 查询是否已存在该订单
|
|
|
+ ThirdPartyChargeStatus existing = chargeStatusMapper.selectOne(
|
|
|
+ Wrappers.<ThirdPartyChargeStatus>lambdaQuery()
|
|
|
+ .eq(ThirdPartyChargeStatus::getStartChargeSeq, startChargeSeq)
|
|
|
+ );
|
|
|
+
|
|
|
+ ThirdPartyChargeStatus chargeStatus = (existing != null) ? existing : new ThirdPartyChargeStatus();
|
|
|
+
|
|
|
+ // 设置字段值
|
|
|
+ chargeStatus.setStartChargeSeq(startChargeSeq);
|
|
|
+ chargeStatus.setConnectorId(getTextValue(jsonNode, "ConnectorID"));
|
|
|
+ chargeStatus.setConnectorStatus(getIntValue(jsonNode, "ConnectorStatus"));
|
|
|
+ chargeStatus.setStartChargeSeqStat(getIntValue(jsonNode, "StartChargeSeqStat"));
|
|
|
+ chargeStatus.setStartTime(parseDateTime(getTextValue(jsonNode, "StartTime")));
|
|
|
+ chargeStatus.setEndTime(parseDateTime(getTextValue(jsonNode, "EndTime")));
|
|
|
+ chargeStatus.setTotalPower(getDecimalValue(jsonNode, "TotalPower"));
|
|
|
+ chargeStatus.setTotalMoney(getDecimalValue(jsonNode, "TotalMoney"));
|
|
|
+ chargeStatus.setElecMoney(getDecimalValue(jsonNode, "ElecMoney"));
|
|
|
+ chargeStatus.setServiceMoney(getDecimalValue(jsonNode, "SeviceMoney")); // 注意:第三方字段名SeviceMoney
|
|
|
+ chargeStatus.setSoc(getIntValue(jsonNode, "Soc"));
|
|
|
+ chargeStatus.setVoltageA(getDecimalValue(jsonNode, "VoltageA"));
|
|
|
+ chargeStatus.setVoltageB(getDecimalValue(jsonNode, "VoltageB"));
|
|
|
+ chargeStatus.setVoltageC(getDecimalValue(jsonNode, "VoltageC"));
|
|
|
+ chargeStatus.setCurrentA(getDecimalValue(jsonNode, "CurrentA"));
|
|
|
+ chargeStatus.setCurrentB(getDecimalValue(jsonNode, "CurrentB"));
|
|
|
+ chargeStatus.setCurrentC(getDecimalValue(jsonNode, "CurrentC"));
|
|
|
+
|
|
|
+ if (existing != null) {
|
|
|
+ chargeStatus.setUpdateTime(LocalDateTime.now());
|
|
|
+ chargeStatusMapper.updateById(chargeStatus);
|
|
|
+ log.info("更新充电状态成功 - startChargeSeq: {}", startChargeSeq);
|
|
|
+ } else {
|
|
|
+ chargeStatus.setCreateTime(LocalDateTime.now());
|
|
|
+ chargeStatusMapper.insert(chargeStatus);
|
|
|
+ log.info("新增充电状态成功 - startChargeSeq: {}", startChargeSeq);
|
|
|
}
|
|
|
+ //熔断保护
|
|
|
+ isNeedBreak(startChargeSeq);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("数据解密失败:{}", e.getMessage());
|
|
|
- throw new BusinessException("数据解密失败:" + e.getMessage(), e);
|
|
|
+ log.error("保存充电状态数据失败", e);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- ResponseParmsEntity responseParmsEntity = new ResponseParmsEntity();
|
|
|
- responseParmsEntity.setRet(STATUS_OK);
|
|
|
- responseParmsEntity.setMsg("请求成功");
|
|
|
- responseParmsEntity.setData(encryptData);
|
|
|
- responseParmsEntity.setSig(genSign);
|
|
|
- return responseParmsEntity;
|
|
|
+ // ==================== JSON解析工具方法 ====================
|
|
|
|
|
|
+ private String getTextValue(JsonNode node, String fieldName) {
|
|
|
+ JsonNode field = node.get(fieldName);
|
|
|
+ return (field != null && !field.isNull()) ? field.asText() : null;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public ResponseParmsEntity chargeOrderResponse(RequestParmsEntity requestDTO) {
|
|
|
- log.info("接收推送充电订单信息请求参数:{}", requestDTO);
|
|
|
- ChargingOrderVO chargingOrderVO;
|
|
|
- ChargeResponseVO chargeResponseVO = new ChargeResponseVO();
|
|
|
- String encryptData;
|
|
|
- String genSign;
|
|
|
+ private Integer getIntValue(JsonNode node, String fieldName) {
|
|
|
+ JsonNode field = node.get(fieldName);
|
|
|
+ return (field != null && !field.isNull()) ? field.asInt() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal getDecimalValue(JsonNode node, String fieldName) {
|
|
|
+ JsonNode field = node.get(fieldName);
|
|
|
+ return (field != null && !field.isNull()) ? new BigDecimal(field.asText()) : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private LocalDateTime parseDateTime(String dateTimeStr) {
|
|
|
+ if (dateTimeStr == null || dateTimeStr.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
try {
|
|
|
- String data = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
- if(verify(data, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())){
|
|
|
- String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
- log.info("解密后的数据:{}", decryptData);
|
|
|
- JsonNode jsonNode = objectMapper.readTree(decryptData);
|
|
|
-// equipChargeStatusResponseVO = objectMapper.readValue(decryptData, EquipChargeStatusResponseVO.class);
|
|
|
- //todo 业务代码待处理
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- chargeResponseVO.setStartChargeSeq(jsonNode.get("StartChargeSeq").asText());
|
|
|
-// chargeResponseVO.setStartChargeSeq(equipChargeStatusResponseVO.getStartChargeSeq());
|
|
|
- chargeResponseVO.setSuccStat(STATUS_OK);
|
|
|
- chargeResponseVO.setFailReason(FAIL_REASON_NONE);
|
|
|
- encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(chargeResponseVO));
|
|
|
- genSign = genSign(STATUS_OK, "请求成功", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
- }else {
|
|
|
- log.error("数据验签失败");
|
|
|
- throw new BusinessException("数据验签失败");
|
|
|
- }
|
|
|
+ return LocalDateTime.parse(dateTimeStr, DATE_TIME_FORMATTER);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("数据解密失败:{}", e.getMessage());
|
|
|
- throw new BusinessException("数据解密失败:" + e.getMessage(), e);
|
|
|
+ log.warn("解析时间失败: {}", dateTimeStr);
|
|
|
+ return null;
|
|
|
}
|
|
|
- ResponseParmsEntity responseParmsEntity = new ResponseParmsEntity();
|
|
|
- responseParmsEntity.setRet(STATUS_OK);
|
|
|
- responseParmsEntity.setMsg("请求成功");
|
|
|
- responseParmsEntity.setData(encryptData);
|
|
|
- responseParmsEntity.setSig(genSign);
|
|
|
- return responseParmsEntity;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public ResponseParmsEntity stationStatus(RequestParmsEntity requestDTO) {
|
|
|
- log.info("接收设备状态变化推送请求参数:{}", requestDTO);
|
|
|
- String encryptData = "";
|
|
|
- String genSign = "";
|
|
|
- ResponseParmsEntity responseParmsEntity = new ResponseParmsEntity();
|
|
|
-
|
|
|
+ /**
|
|
|
+ * 根据充电订单号StartChargeSeq 获取订单信息判断是否需要熔断,提前跳枪
|
|
|
+ * 使用分布式锁防止并发重复检查
|
|
|
+ */
|
|
|
+ private void isNeedBreak(String startChargeSeq) {
|
|
|
+ String lockKey = BREAK_CHECK_LOCK_KEY + startChargeSeq;
|
|
|
+ RLock lock = redissonClient.getLock(lockKey);
|
|
|
try {
|
|
|
- String data = requestDTO.getOperatorID() + requestDTO.getData() + requestDTO.getTimeStamp() + requestDTO.getSeq();
|
|
|
- if (verify(data, ConnectivityConstants.SIG_SECRET, requestDTO.getSig())) {
|
|
|
- String decryptData = chargingUtil.decryptData(requestDTO.getData());
|
|
|
- log.info("解密后的数据:{}", decryptData);
|
|
|
-
|
|
|
- // 解析设备状态变化推送数据
|
|
|
- QueryStationStatusVO stationStatusVO = objectMapper.readValue(decryptData, QueryStationStatusVO.class);
|
|
|
- if (stationStatusVO != null && !CollectionUtils.isEmpty(stationStatusVO.getStationStatusInfos())) {
|
|
|
- for (StationStatusInfo stationStatusInfo : stationStatusVO.getStationStatusInfos()) {
|
|
|
- List<ConnectorStatusInfo> connectorStatusInfos = stationStatusInfo.getConnectorStatusInfos();
|
|
|
- if (!CollectionUtils.isEmpty(connectorStatusInfos)) {
|
|
|
- for (ConnectorStatusInfo connectorStatus : connectorStatusInfos) {
|
|
|
- // 根据连接器ID更新状态
|
|
|
- connectorInfoMapper.update(null, Wrappers.<ThirdPartyConnectorInfo>lambdaUpdate()
|
|
|
- .eq(ThirdPartyConnectorInfo::getConnectorId, connectorStatus.getConnectorID())
|
|
|
- .set(ThirdPartyConnectorInfo::getStatus, connectorStatus.getStatus()));
|
|
|
- log.debug("更新充电接口状态 - connectorId: {}, status: {}",
|
|
|
- connectorStatus.getConnectorID(), connectorStatus.getStatus());
|
|
|
- }
|
|
|
+ // 尝试获取锁,最多等待3秒,持有锁最多10秒
|
|
|
+ if (lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, TimeUnit.SECONDS)) {
|
|
|
+ try {
|
|
|
+ ChargeOrderInfo chargeOrderInfo = chargeOrderInfoMapper.selectOne(
|
|
|
+ Wrappers.<ChargeOrderInfo>lambdaQuery()
|
|
|
+ .eq(ChargeOrderInfo::getChargeOrderNo, startChargeSeq)
|
|
|
+ .eq(ChargeOrderInfo::getStatus, 1)
|
|
|
+ .eq(ChargeOrderInfo::getIsDeleted, 0)
|
|
|
+ );
|
|
|
+ if (null != chargeOrderInfo) {
|
|
|
+ // TODO: 根据业务需求实现熔断条件判断(例如:余额不足、超时等)
|
|
|
+ DictItem dictItem = dictItemMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<DictItem>()
|
|
|
+ .eq(DictItem::getDictCode, "up_recharge")
|
|
|
+ .eq(DictItem::getStatus, 1)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ //安全价
|
|
|
+ BigDecimal upRecharge = new BigDecimal(dictItem.getValue());
|
|
|
+ //获取用户余额
|
|
|
+ BigDecimal balance = userAccountMapper.selectOne(Wrappers.<UserAccount>lambdaQuery()
|
|
|
+ .eq(UserAccount::getUserId, chargeOrderInfo.getUserId())
|
|
|
+ .eq(UserAccount::getIsDeleted, 0)).getBalance();
|
|
|
+ //企业价
|
|
|
+ BigDecimal firmPrice;
|
|
|
+ //根据用户ID去查询当前用户是否有归属企业
|
|
|
+ UserFirm userFirm = userFirmMapper.selectOne(Wrappers.<UserFirm>lambdaQuery()
|
|
|
+ .eq(UserFirm::getUserId, chargeOrderInfo.getUserId())
|
|
|
+ .eq(UserFirm::getIsDeleted, 0));
|
|
|
+ if(null != userFirm){
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+ } finally {
|
|
|
+ lock.unlock();
|
|
|
}
|
|
|
-
|
|
|
- Map<String, Integer> statusMap = new HashMap<>();
|
|
|
- statusMap.put("Status", 0);
|
|
|
- encryptData = chargingUtil.encryptData(objectMapper.writeValueAsString(statusMap));
|
|
|
- genSign = genSign(STATUS_OK, "", encryptData, ConnectivityConstants.SIG_SECRET);
|
|
|
-
|
|
|
- responseParmsEntity.setRet(STATUS_OK);
|
|
|
- responseParmsEntity.setMsg("");
|
|
|
- responseParmsEntity.setData(encryptData);
|
|
|
- responseParmsEntity .setSig(genSign);
|
|
|
} else {
|
|
|
- log.error("数据验签失败");
|
|
|
- throw new BusinessException("数据验签失败");
|
|
|
+ log.warn("获取熔断检查锁超时 - startChargeSeq: {}", startChargeSeq);
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("数据解密失败:{}", e.getMessage());
|
|
|
- throw new BusinessException("数据解密失败:" + e.getMessage(), e);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("获取熔断检查锁被中断 - startChargeSeq: {}", startChargeSeq, e);
|
|
|
}
|
|
|
-
|
|
|
- return responseParmsEntity;
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
}
|