Files
jsowell-charger-web/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/HuaweiServiceV2.java
2024-02-22 15:37:25 +08:00

991 lines
40 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.jsowell.thirdparty.huawei;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.thirdparty.ThirdPartyOperatorIdEnum;
import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum;
import com.jsowell.common.enums.thirdparty.huawei.StartFailedReasonEnum;
import com.jsowell.common.enums.thirdparty.huawei.StopFailedReasonEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.enums.ykc.StartModeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.id.IdUtils;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.domain.huawei.HWStationInfo;
import com.jsowell.pile.dto.GenerateOrderDTO;
import com.jsowell.pile.dto.PushStationInfoDTO;
import com.jsowell.pile.dto.QueryStartChargeDTO;
import com.jsowell.pile.dto.huawei.*;
import com.jsowell.pile.service.*;
import com.jsowell.pile.transaction.dto.OrderTransactionDTO;
import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.vo.huawei.DeliverEquipBusinessPolicyVO;
import com.jsowell.pile.vo.huawei.QueryChargeStatusVO;
import com.jsowell.pile.vo.huawei.QueryEquipAuthVO;
import com.jsowell.pile.vo.huawei.QueryStartChargeVO;
import com.jsowell.pile.vo.uniapp.BillingPriceVO;
import com.jsowell.pile.vo.web.PileStationVO;
import com.jsowell.thirdparty.lianlian.common.CommonResult;
import com.jsowell.thirdparty.lianlian.domain.ConnectorStatusInfo;
import com.jsowell.thirdparty.lianlian.domain.StationStatusInfo;
import com.jsowell.thirdparty.lianlian.dto.CommonParamsDTO;
import com.jsowell.thirdparty.lianlian.service.LianLianService;
import com.jsowell.thirdparty.lianlian.util.Cryptos;
import com.jsowell.thirdparty.lianlian.util.Encodes;
import com.jsowell.thirdparty.lianlian.util.GBSignUtils;
import com.jsowell.thirdparty.lianlian.util.HttpRequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 华为Service
*
* @author Lemon
* @Date 2024/1/19 14:10:02
*/
@Service
@Slf4j
public class HuaweiServiceV2 {
@Autowired
private LianLianService lianLianService;
@Autowired
private PileStationInfoService pileStationInfoService;
@Autowired
private PileConnectorInfoService pileConnectorInfoService;
@Autowired
private PileBasicInfoService pileBasicInfoService;
@Autowired
private ThirdPartySettingInfoService thirdPartySettingInfoService;
@Autowired
private ThirdPartyPlatformConfigService thirdPartyPlatformConfigService;
@Autowired
private PileBillingTemplateService pileBillingTemplateService;
@Autowired
private OrderBasicInfoService orderBasicInfoService;
@Autowired
private MemberPlateNumberRelationService memberPlateNumberRelationService;
@Resource
private TransactionService transactionService;
@Autowired
private RedisCache redisCache;
/**
* 获取华为 Token
* @return
*/
public String getHuaWeiToken() {
String operatorId = Constants.OPERATORID_JIANG_SU;
String redisKey = "huawei_get_token:" + operatorId;
// 先查缓存
String cacheToken = redisCache.getCacheObject(redisKey);
if (StringUtils.isNotBlank(cacheToken)) {
return cacheToken;
}
// 通过华为的type查询出密钥配置
ThirdPartySettingInfo info = new ThirdPartySettingInfo();
info.setType(ThirdPlatformTypeEnum.HUA_WEI.getCode());
ThirdPartySettingInfo settingInfo = thirdPartySettingInfoService.selectSettingInfo(info);
String operatorSecret = settingInfo.getOperatorSecret();
String dataSecret = settingInfo.getDataSecret();
String dataSecretIv = settingInfo.getDataSecretIv();
String signSecret = settingInfo.getSignSecret();
String urlAddress = settingInfo.getUrlAddress();
String requestUrl = urlAddress + "query_token";
// 拼装参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("OperatorID", operatorId);
jsonObject.put("OperatorSecret", operatorSecret);
// 加密
byte[] encryptText = Cryptos.aesEncrypt(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8),
dataSecret.getBytes(), dataSecretIv.getBytes());
String strData = Encodes.encodeBase64(encryptText);
Map<String, String> request = new LinkedHashMap<>();
request.put("OperatorID", Constants.OPERATORID_JIANG_SU);
request.put("Data", strData);
request.put("TimeStamp", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date()));
request.put("Seq", "0001");
// 生成签名
String sig = GBSignUtils.sign(request, signSecret);
request.put("Sig", sig);
String tokenRequest = JSONObject.toJSONString(request);
// 向华为发送请求
String response = HttpUtil.post(requestUrl, tokenRequest);
CommonResult<?> commonResult = JSONObject.parseObject(response, CommonResult.class);
if (commonResult.getRet() != 0) {
return commonResult.getMsg();
}
// 解密data
byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64((String) commonResult.getData()),
dataSecret.getBytes(), dataSecretIv.getBytes());
String dataStr = new String(plainText, StandardCharsets.UTF_8);
Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
int succStat = Integer.parseInt(resultMap.get("SuccStat"));
if (succStat != 0) {
return resultMap.get("FailReason");
}
String token = resultMap.get("AccessToken");
int tokenAvailableTime = Integer.parseInt(resultMap.get("TokenAvailableTime")); // 凭证有效期,单位秒
// 存入缓存
redisCache.setCacheObject(redisKey, token, tokenAvailableTime, TimeUnit.SECONDS);
return token;
}
public Map<String, String> generateToken(CommonParamsDTO dto) throws UnsupportedEncodingException {
return lianLianService.generateToken(dto);
}
public Map<String, String> checkoutSign(CommonParamsDTO dto) {
return lianLianService.checkoutSign(dto);
}
/**
* 平台充电设备编码同步
*
* notification_operation_system_info
*
* @param stationId
* @return
*/
public String notificationOperationSystemInfo(String stationId) {
String requestName = "notification_operation_system_info";
List<HWStationInfo
.EquipmentLogicInfo> equipmentLogicInfos = new ArrayList<>();
// 通过站点id查询站点信息
PileStationVO stationInfo = pileStationInfoService.getStationInfo(stationId);
if (stationInfo == null) {
return null;
}
HWStationInfo hwStationInfo = HWStationInfo.builder()
.stationId(stationInfo.getId())
.stationName(stationInfo.getStationName())
.build();
// 查询桩列表
equipmentLogicInfos = getPileList(stationId);
hwStationInfo.setEquipmentInfoNum(equipmentLogicInfos.size());
hwStationInfo.setEquipmentLogicInfos(equipmentLogicInfos);
String jsonString = JSONObject.toJSONString(hwStationInfo);
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
// String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
String result = sendMsg2HuaWei(jsonString, token, requestName);
return result;
}
/**
* 设备接口状态查询
*
* query_station_status
*
* @param stationIds
* @return
*/
public List<StationStatusInfo> queryStationStatus(List<String> stationIds) {
String requestName = "query_station_status";
// 拼装参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StationIDs", stationIds);
String jsonString = jsonObject.toJSONString();
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return new ArrayList<>();
}
// 转换成 StationStatus 对象
List<StationStatusInfo> list = JSON.parseArray(result, StationStatusInfo.class);
return list;
}
/**
* 接收设备接口状态变化推送
* 需在Controller传入operatorId
*
* @param connectorStatusInfo
* @return
*/
public Map<String, String> receiveNotificationStationStatus(ConnectorStatusInfo connectorStatusInfo) {
String pileConnectorCode = connectorStatusInfo.getConnectorID();
Integer status = connectorStatusInfo.getStatus();
ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(connectorStatusInfo.getOperatorId());
if (configInfo == null) {
return null;
}
// 将枪口状态改为对应的状态
pileConnectorInfoService.updateConnectorStatus(pileConnectorCode, String.valueOf(status));
// 构造返回参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("Status", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 请求设备认证
* @param connectorId
* @return
*/
public QueryEquipAuthVO queryEquipAuth(String connectorId) {
String requestName = "query_equip_auth";
// 生成设备认证流水号格式“运营商ID + 唯一编号”(<=27字符)
// 生成唯一编号(用时间戳表示)
long currentTimeMillis = System.currentTimeMillis();
String equipAuthSeq = Constants.OPERATORID_JIANG_SU + currentTimeMillis;
// 拼装参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("EquipAuthSeq", equipAuthSeq);
jsonObject.put("ConnectorID", connectorId);
String jsonString = jsonObject.toJSONString();
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return null;
}
// 转换成 StationStatus 对象
QueryEquipAuthVO queryEquipAuthVO = JSON.parseObject(result, QueryEquipAuthVO.class);
return queryEquipAuthVO;
}
/**
* 请求计费策略
* @param dto
* @return
*/
public Map<String, String> requestEquipBusinessPolicy(RequestEquipBusinessPolicyDTO dto) {
String pileConnectorCode = dto.getConnectorID();
String equipBizSeq = dto.getEquipBizSeq();
// 根据枪口号查询计费模板,并返回信息
ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(dto.getOperatorId());
if (configInfo == null) {
return null;
}
// 截取桩号
String pileSn = StringUtils.substring(pileConnectorCode, 0, 14);
// 查询该桩的站点id
PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
// 根据桩号查询正在使用的计费模板
List<BillingPriceVO> billingPriceVOList = pileBillingTemplateService.queryBillingPrice(String.valueOf(pileBasicInfo.getStationId()));
JSONObject resultJson = new JSONObject();
resultJson.put("EquipBizSeq", equipBizSeq);
resultJson.put("ConnectorID", pileConnectorCode);
if (CollectionUtils.isEmpty(billingPriceVOList)) {
// 为空说明未查到该枪口的计费模板
resultJson.put("SuccStat", 1);
resultJson.put("FailReason", 1);
}else {
// 延时 500ms异步调用 下发计费策略 接口
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
DeliverEquipBusinessPolicyVO vo = deliverEquipBusinessPolicy(equipBizSeq, pileConnectorCode);
log.info("华为 异步调用 下发计费策略 接口 result:{}", JSONObject.toJSONString(vo));
});
resultJson.put("SuccStat", 0);
resultJson.put("FailReason", 0);
}
// 加密
Map<String, String> resultMap = Maps.newLinkedHashMap();
// 加密数据
byte[] encryptText = Cryptos.aesEncrypt(resultJson.toJSONString().getBytes(),
configInfo.getDataSecret().getBytes(), configInfo.getDataSecretIv().getBytes());
String encryptData = Encodes.encodeBase64(encryptText);
resultMap.put("Data", encryptData);
// 生成sig
String resultSign = GBSignUtils.sign(resultMap, configInfo.getSignSecret());
resultMap.put("Sig", resultSign);
return resultMap;
}
/**
* 下发计费策略
* @param equipBizSeq 策略下发流水号
* @param pileConnectorCode 枪口号
* @return
*/
public DeliverEquipBusinessPolicyVO deliverEquipBusinessPolicy(String equipBizSeq, String pileConnectorCode) {
String requestName = "deliver_equip_business_policy";
DeliverEquipBusinessDTO params = new DeliverEquipBusinessDTO();
// 充电业务策略信息
List<DeliverEquipBusinessDTO
.ChargePolicyInfo> chargePolicyInfos = new ArrayList<>();
DeliverEquipBusinessDTO.ChargePolicyInfo chargePolicyInfo = new DeliverEquipBusinessDTO.ChargePolicyInfo();
// 业务策略信息体
List<DeliverEquipBusinessDTO
.ChargePolicyInfo
.PricePolicyInfo> pricePolicyInfos = new ArrayList<>();
DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo pricePolicyInfo = new DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo();
// 计费信息
List<DeliverEquipBusinessDTO
.ChargePolicyInfo
.PricePolicyInfo
.PolicyInfo> policyInfoList = new ArrayList<>();
DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo.PolicyInfo policyInfo = null;
// 截取桩号
String pileSn = StringUtils.substring(pileConnectorCode, 0, 14);
// 查询该桩的站点id
PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
String stationId = String.valueOf(pileBasicInfo.getStationId());
// 获取运营商组织结构代码
// MerchantInfoVO merchantInfoVO = pileMerchantInfoService.getMerchantInfoVO(String.valueOf(pileBasicInfo.getMerchantId()));
// String organizationCode = merchantInfoVO.getOrganizationCode();
// 通过站点id查询相关配置信息
// ThirdPartyStationRelation relation = new ThirdPartyStationRelation();
// relation.setStationId(Long.parseLong(stationId));
// ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
// if (relationInfo == null) {
// return null;
// }
// 根据站点id查询正在使用的计费模板
List<BillingPriceVO> billingPriceVOList = pileBillingTemplateService.queryBillingPrice(stationId);
if (CollectionUtils.isEmpty(billingPriceVOList)) {
return null;
}
for (BillingPriceVO billingPriceVO : billingPriceVOList) {
// 将时段开始时间、电费、服务费信息进行封装
policyInfo = new DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo.PolicyInfo();
String startTime = billingPriceVO.getStartTime() + ":00"; // 00:00:00 格式
// 需要将中间的冒号去掉,改为 000000 格式
String replace = StringUtils.replace(startTime, ":", "");
policyInfo.setStartTime(replace);
policyInfo.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, RoundingMode.DOWN));
policyInfo.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, RoundingMode.DOWN));
policyInfoList.add(policyInfo);
}
BillingPriceVO billingPriceVO = billingPriceVOList.get(0);
// String equipmentOwnerId = "";
// if (StringUtils.isNotBlank(organizationCode) && organizationCode.length() == 18) {
// equipmentOwnerId = StringUtils.substring(organizationCode, organizationCode.length() - 10, organizationCode.length() - 1);
// }else {
// equipmentOwnerId = Constants.OPERATORID_JIANG_SU;
// }
// 封装参数
pricePolicyInfo.setEquipBizID(Constants.OPERATORID_JIANG_SU + billingPriceVO.getTemplateCode()); // 计费策略ID
pricePolicyInfo.setValidStat(1); // 执行状态
pricePolicyInfo.setValidStartTime(billingPriceVO.getPublishTime()); // 生效时间
pricePolicyInfo.setValidEndTime("2099-12-31 23:59:59"); // 失效时间
pricePolicyInfo.setSumPeriod(policyInfoList.size()); // 时段数
pricePolicyInfo.setPolicyInfos(policyInfoList);
pricePolicyInfos.add(pricePolicyInfo);
chargePolicyInfo.setConnectorID(pileConnectorCode);
chargePolicyInfo.setPricePolicyInfos(pricePolicyInfos);
chargePolicyInfos.add(chargePolicyInfo);
params.setEquipBizSeq(equipBizSeq);
params.setSumChargePolicyInfos(pricePolicyInfos.size());
params.setChargePolicyInfos(chargePolicyInfos);
String jsonString = JSONObject.toJSONString(params);
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return null;
}
// 转换成 DeliverEquipBusinessPolicyVO 对象
DeliverEquipBusinessPolicyVO vo = JSON.parseObject(result, DeliverEquipBusinessPolicyVO.class);
return vo;
}
/**
* 请求启动充电
* 只需传枪口号、充电金额即可
* @param dto
* @return QueryStartChargeVO
*/
public QueryStartChargeVO queryStartCharge(HWQueryStartChargeDTO dto) {
String pileConnectorCode = dto.getConnectorID();
BigDecimal chargeAmount = dto.getMoneyLimit();
String requestName = "query_start_charge";
// 生成订单
String orderCode = IdUtils.getOrderCode();
String startChargeSeq = Constants.OPERATORID_JIANG_SU + "_C" + orderCode;
QueryStartChargeDTO startChargeDTO = new QueryStartChargeDTO();
startChargeDTO.setOperatorId(ThirdPartyOperatorIdEnum.HUA_WEI.getOperatorId());
startChargeDTO.setStartChargeSeq(startChargeSeq);
startChargeDTO.setConnectorID(pileConnectorCode);
startChargeDTO.setAccountBalance(chargeAmount);
Map<String, Object> map = orderBasicInfoService.generateOrderForThirdParty(startChargeDTO);
if (map == null) {
log.error("华为平台生成订单 error");
throw new BusinessException(ReturnCodeEnum.CODE_GENERATE_ORDER_ERROR);
}
// 拼装参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
jsonObject.put("ConnectorID", pileConnectorCode);
jsonObject.put("MoneyLimit", chargeAmount);
String jsonString = jsonObject.toJSONString();
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return null;
}
// 转换成 QueryStartChargeVO 对象
QueryStartChargeVO vo = JSON.parseObject(result, QueryStartChargeVO.class);
return vo;
}
/**
* 接收启动充电结果
*/
public Map<String, String> receiveStartChargeResult(ReceiveStartChargeResultDTO dto) {
String startChargeSeq = dto.getStartChargeSeq();
Integer startChargeSeqStat = dto.getStartChargeSeqStat(); // 充电订单状态
Integer failReason = dto.getFailReason();
String startTime = dto.getStartTime();
// 根据订单号查询订单信息
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(startChargeSeq);
// 判断订单状态
if (startChargeSeqStat == Constants.two) {
// 充电中
orderBasicInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue());
// 设置开始时间
orderBasicInfo.setChargeStartTime(DateUtils.parseDate(startTime));
orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo);
}
if (failReason != 0) {
// 启动失败, 将失败原因换成中文
String reason = StartFailedReasonEnum.getReasonByCode(failReason);
// 给用户退款(执行0x33中启动失败的操作流程)
orderBasicInfoService.chargingPileFailedToStart(orderBasicInfo.getTransactionCode(), reason);
}
// 构建返回参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
jsonObject.put("SuccStat", 0);
jsonObject.put("FailReason", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 查询充电状态
* @param startChargeSeq 订单号
*/
public QueryChargeStatusVO queryChargeStatus(String startChargeSeq) {
String requestName = "query_equip_charge_status";
// 拼装参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
String jsonString = jsonObject.toJSONString();
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return null;
}
// 转换成 QueryChargeStatusVO 对象
QueryChargeStatusVO vo = JSON.parseObject(result, QueryChargeStatusVO.class);
return vo;
}
/**
* 接收华为所推送的设备充电状态
* @param dto
*/
public Map<String, String> receiveEquipChargeStatus(ReceiveEquipChargeStatusDTO dto) {
String startChargeSeq = dto.getStartChargeSeq(); // 订单号
String startTime = dto.getStartTime();
String endTime = dto.getEndTime();
// 计算时间间隔
String poorDays = DateUtils.getDatePoor(DateUtils.parseDate(endTime), DateUtils.parseDate(startTime));
// 通过订单号查询交易流水号
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(startChargeSeq);
if (orderBasicInfo == null) {
return null;
}
// 将源数据存储至缓存
String redisKey = "HUA_WEI_REAL_TIME_INFO_BY_ORDER_CODE:" + startChargeSeq;
String jsonMsg = JSONObject.toJSONString(dto);
// 在同一分钟内,只保留最后一条实时数据
redisCache.hset(redisKey, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00", new Date()), jsonMsg);
// 封装成实时数据对象
RealTimeMonitorData data = RealTimeMonitorData.builder()
.transactionCode(orderBasicInfo.getTransactionCode())
.pileSn(orderBasicInfo.getPileSn())
.connectorCode(orderBasicInfo.getConnectorCode())
.connectorStatus(String.valueOf(dto.getConnectorStatus()))
.pileConnectorCode(orderBasicInfo.getPileConnectorCode())
.outputVoltage(String.valueOf(dto.getVoltageA()))
.outputCurrent(String.valueOf(dto.getCurrentA()))
.SOC(String.valueOf(dto.getSoc()))
.sumChargingTime(poorDays)
.chargingDegree(String.valueOf(dto.getTotalPower()))
.chargingAmount(String.valueOf(dto.getTotalMoney()))
.build();
// 将实时数据信息保存至缓存
pileBasicInfoService.saveRealTimeMonitorData2Redis(data);
// 构建返回参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
jsonObject.put("SuccStat", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 请求停止充电
* @param startChargeSeq
*/
public QueryStartChargeVO queryStopCharge(String startChargeSeq) {
String requestName = "query_stop_charge";
// 通过订单号查询订单信息
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(startChargeSeq);
if(orderBasicInfo == null) {
return null;
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
jsonObject.put("ConnectorID", orderBasicInfo.getPileConnectorCode());
String jsonString = jsonObject.toJSONString();
// 向华为发送请求
// 获取令牌
String token = getHuaWeiToken();
// 发送请求
String result = sendMsg2HuaWei(jsonString, token, requestName);
if (result == null) {
return null;
}
// 转换成 QueryStartChargeVO 对象
QueryStartChargeVO vo = JSON.parseObject(result, QueryStartChargeVO.class);
return vo;
}
/**
* 接收华为所推送的停止充电结果
* @param vo
* @return
*/
public Map<String, String> receiveStopChargeResult(ReceiveStopChargeResultVO vo) {
String startChargeSeq = vo.getStartChargeSeq();
Integer startChargeSeqStat = vo.getStartChargeSeqStat();
Integer succStat = vo.getSuccStat();
Integer failReasonCode = vo.getFailReason();
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(startChargeSeq);
if (orderBasicInfo == null) {
return null;
}
if (succStat == Constants.zero) {
// 成功标识为 0-成功,修改订单状态为 2-待结算,具体的订单金额等详情金额,从所推送的订单信息中取
orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue());
}else {
// 若成功标识为失败,则将失败原因记录存库
String reason = StopFailedReasonEnum.getReasonByCode(failReasonCode);
orderBasicInfo.setReason(reason);
}
// 统一修改订单
orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo);
// 回复华为消息
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", "startChargeSeq");
jsonObject.put("SuccStat", 0);
jsonObject.put("FailReason", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 接收订单信息
* @param dto
* @return
*/
public Map<String, String> receiveOrderInfo(ReceiveOrderInfoDTO dto) {
String startChargeSeq = dto.getStartChargeSeq();
List<QueryChargeStatusVO.ChargeDetail> chargeDetails = dto.getChargeDetails();
String pileConnectorCode = dto.getConnectorID();
// 将源数据存缓存
String redisKey = "HUA_WEI_ORDER_INFO_BY_ORDER_CODE:" + startChargeSeq;
redisCache.setCacheObject(redisKey, dto);
// // 截取桩号
// String pileSn = StringUtils.substring(pileConnectorCode, 0, 14);
// // 查询该桩的站点id
// PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
// String stationId = String.valueOf(pileBasicInfo.getStationId());
// // 根据站点id查询正在使用的计费模板
// List<BillingPriceVO> billingPriceVOList = pileBillingTemplateService.queryBillingPrice(stationId);
// if (CollectionUtils.isEmpty(billingPriceVOList)) {
// return null;
// }
// 查出订单基本信息和详情
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(startChargeSeq);
OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(startChargeSeq);
orderBasicInfo.setChargeStartTime(DateUtils.parseDate(dto.getStartTime()));
orderBasicInfo.setChargeEndTime(DateUtils.parseDate(dto.getEndTime()));
orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); // 订单状态改为订单完成
orderBasicInfo.setReason(String.valueOf(dto.getStopReason())); // TODO 新建停止原因枚举
orderDetail.setTotalUsedElectricity(dto.getTotalPower());
orderDetail.setTotalElectricityAmount(dto.getTotalElecMoney());
orderDetail.setTotalServiceAmount(dto.getTotalSeviceMoney());
orderDetail.setTotalOrderAmount(dto.getTotalMoney());
// if (CollectionUtils.isNotEmpty(chargeDetails)) {
// for (BillingPriceVO billingPriceVO : billingPriceVOList) {
// for (QueryChargeStatusVO.ChargeDetail chargeDetail : chargeDetails) {
// if (StringUtils.equals(chargeDetail.getDetailStartTime(), billingPriceVO.getStartTime())) {
// // 开始时间相等,则为同一时间段,将该时段的消费金额、用电量存入数据库
//
//
// }
// }
// }
// }
// 通过事务修改订单信息
OrderTransactionDTO transactionDTO = OrderTransactionDTO.builder()
.orderBasicInfo(orderBasicInfo)
.orderDetail(orderDetail)
.build();
transactionService.doUpdateOrder(transactionDTO);
// 构建返回参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("StartChargeSeq", startChargeSeq);
jsonObject.put("ConnectorID", pileConnectorCode);
jsonObject.put("ConfirmResult", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* VIN启动充电
* @param dto
* @return
* @throws Exception
*/
public Map<String, String> vinStartCharge(VinStartChargeDTO dto) throws Exception {
ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(dto.getOperatorId());
if (configInfo == null) {
return null;
}
String vinCode = dto.getVin();
String pileConnectorCode = dto.getConnectorID();
// 截取桩号、枪口号
String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2);
String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length());
// 根据vin查询小程序平台用户信息
MemberPlateNumberRelation basicInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
if (basicInfo == null) {
// 该用户未注册
throw new BusinessException(ReturnCodeEnum.CODE_GENERATE_ORDER_ERROR);
}
// 生成订单,并启动充电
GenerateOrderDTO generateOrderDTO = new GenerateOrderDTO();
generateOrderDTO.setMemberPlateNumberRelation(basicInfo);
generateOrderDTO.setPileSn(pileSn);
generateOrderDTO.setConnectorCode(connectorCode);
generateOrderDTO.setStartMode(StartModeEnum.VIN_CODE.getValue());
generateOrderDTO.setMemberId(basicInfo.getMemberId());
generateOrderDTO.setStartSoc(String.valueOf(dto.getSoc()));
int succStat = Constants.one; // 操作结果
int failReason = Constants.one; // 失败原因
Map<String, Object> map = orderBasicInfoService.generateOrderByCard(generateOrderDTO);
if (map != null) {
// 鉴权成功
succStat = Constants.zero;
failReason = Constants.zero;
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("SuccStat", succStat);
jsonObject.put("FailReason", failReason);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 下发计费策略响应
* @param dto
* @return
*/
public Map<String, String> receiveDeliverEquipBusinessPolicyResult(DeliverBusinessPolicyResponseDTO dto) {
List<DeliverBusinessPolicyResponseDTO.ChargePolicyInfoRet> chargePolicyInfoRets = dto.getChargePolicyInfoRets();
// 将下发失败的进行筛选、收集
List<DeliverBusinessPolicyResponseDTO.ChargePolicyInfoRet> failedList = chargePolicyInfoRets.stream()
.filter(x -> x.getSuccStat() == Constants.one) // 1-失败
.collect(Collectors.toList());
for (DeliverBusinessPolicyResponseDTO.ChargePolicyInfoRet chargePolicyInfoRet : failedList) {
log.error("华为下发计费策略响应, 枪口:{} 下发计费策略失败, 失败原因:{}", chargePolicyInfoRet.getConnectorID(), chargePolicyInfoRet.getFailReason());
// TODO 重新下发
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("SuccStat", 0);
jsonObject.put("FailReason", 0);
Map<String, String> resultMap = getResultMap(jsonObject);
return resultMap;
}
/**
* 获取华为配置信息
* @return
*/
private ThirdPartySettingInfo getHuaWeiSettingInfo() {
// 通过华为的type查询出密钥配置
ThirdPartySettingInfo info = new ThirdPartySettingInfo();
info.setType(ThirdPlatformTypeEnum.HUA_WEI.getCode());
ThirdPartySettingInfo settingInfo = thirdPartySettingInfoService.selectSettingInfo(info);
return settingInfo;
}
/**
* 向华为发送请求
* @param jsonString 封装好的json请求参数
* @param token 从华为平台请求到的令牌
* @param requestName 请求接口名称
* @return 请求结果
*/
private String sendMsg2HuaWei(String jsonString, String token, String requestName) {
ThirdPartySettingInfo settingInfo = getHuaWeiSettingInfo();
if (settingInfo == null) {
return null;
}
//加密
byte[] encryptText = Cryptos.aesEncrypt(jsonString.getBytes(),
settingInfo.getDataSecret().getBytes(), settingInfo.getDataSecretIv().getBytes());
String encryptData = Encodes.encodeBase64(encryptText);
Map<String, String> params = Maps.newLinkedHashMap();
params.put("OperatorID", settingInfo.getOperatorId());
params.put("Data", encryptData);
params.put("TimeStamp", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date()));
params.put("Seq", "001");
String sign = GBSignUtils.sign(params, settingInfo.getSignSecret());
params.put("Sig", sign);
String postData = JSON.toJSONString(params);
// 请求url
String requestUrl = settingInfo.getUrlAddress() + requestName;
String hutoolRequest = HttpRequest.post(requestUrl)
.header("Authorization", "Bearer " + token)
.body(postData).execute().body();
log.info("华为发送请求 接收到返回数据:{}", hutoolRequest);
if (StringUtils.isBlank(hutoolRequest)) {
return null;
}
Map<String, Object> map = (Map<String, Object>) JSON.parse(hutoolRequest);
int ret = (int) map.get("Ret");
String resultMsg = (String) map.get("Msg");
if (ret != 0) {
// 表示请求有异常
log.error("华为发送请求 error:{}, 源数据:{}", resultMsg, jsonString);
return null;
}
String rData = (String) map.get("Data");
// 解密
byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
settingInfo.getDataSecret().getBytes(), settingInfo.getDataSecretIv().getBytes());
String plainData = new String(plainText, StandardCharsets.UTF_8);
return plainData;
}
/**
* 将需要发送至华为的返回参数加密返回
* @param jsonObject
* @return
*/
private Map<String, String> getResultMap(JSONObject jsonObject) {
String operatorId = ThirdPartyOperatorIdEnum.HUA_WEI.getOperatorId();
ThirdPartyPlatformConfig platformConfig = thirdPartyPlatformConfigService.getInfoByOperatorId(operatorId);
if (platformConfig == null) {
return null;
}
Map<String, String> resultMap = Maps.newLinkedHashMap();
// 加密数据
byte[] encryptText = Cryptos.aesEncrypt(jsonObject.toJSONString().getBytes(),
platformConfig.getDataSecret().getBytes(), platformConfig.getDataSecretIv().getBytes());
String encryptData = Encodes.encodeBase64(encryptText);
resultMap.put("Data", encryptData);
// 生成sig
String resultSign = GBSignUtils.sign(resultMap, platformConfig.getSignSecret());
resultMap.put("Sig", resultSign);
return resultMap;
}
/**
* 获取桩列表
* @param stationId
* @return
*/
private List<HWStationInfo.EquipmentLogicInfo> getPileList(String stationId) {
List<HWStationInfo
.EquipmentLogicInfo> equipmentLogicInfos = new ArrayList<>();
HWStationInfo
.EquipmentLogicInfo equipmentLogicInfo = null;
List<PileBasicInfo> pileBasicInfos = pileBasicInfoService.getPileListByStationId(stationId);
if (CollectionUtils.isEmpty(pileBasicInfos)) {
return new ArrayList<>();
}
for (PileBasicInfo pileBasicInfo : pileBasicInfos) {
String pileSn = pileBasicInfo.getSn();
equipmentLogicInfo = HWStationInfo.EquipmentLogicInfo.builder()
.equipmentId(pileSn)
// .equipmentType()
.chargeHostESN(pileSn)
.build();
// 获取枪口信息
List<HWStationInfo.EquipmentLogicInfo
.ConnectorInfo> connectorInfoList = getConnectorInfoList(pileSn);
if (CollectionUtils.isEmpty(connectorInfoList)) {
continue;
}
equipmentLogicInfo.setConnectorInfoNum(connectorInfoList.size());
equipmentLogicInfo.setConnectorInfos(connectorInfoList);
equipmentLogicInfos.add(equipmentLogicInfo);
}
return equipmentLogicInfos;
}
/**
* 获取枪口列表
* @param pileSn
* @return
*/
private List<HWStationInfo.EquipmentLogicInfo.ConnectorInfo> getConnectorInfoList(String pileSn) {
List<HWStationInfo.EquipmentLogicInfo
.ConnectorInfo> connectorInfoList = new ArrayList<>();
HWStationInfo.EquipmentLogicInfo
.ConnectorInfo connectorInfo = null;
List<PileConnectorInfo> pileConnectorInfos = pileConnectorInfoService.selectPileConnectorInfoList(pileSn);
if (CollectionUtils.isEmpty(pileConnectorInfos)) {
return new ArrayList<>();
}
for (PileConnectorInfo pileConnectorInfo : pileConnectorInfos) {
connectorInfo = HWStationInfo.EquipmentLogicInfo.ConnectorInfo.builder()
.connectorID(pileConnectorInfo.getPileConnectorCode())
.connectorNumber(pileConnectorInfo.getId())
.build();
connectorInfoList.add(connectorInfo);
}
return connectorInfoList;
}
}