update 南瑞平台相关接口

This commit is contained in:
Lemon
2023-10-12 16:35:53 +08:00
parent cf4a9bf72f
commit e37ad1e423
14 changed files with 586 additions and 80 deletions

View File

@@ -0,0 +1,23 @@
package com.jsowell.pile.dto.nanrui;
import com.jsowell.pile.dto.PushStationInfoDTO;
import lombok.Data;
/**
* 推送告警信息DTO
*
* @author Lemon
* @Date 2023/10/12 15:33
*/
@Data
public class PushAlarmInfoDTO extends PushStationInfoDTO {
/**
* 枪口号
*/
private String pileConnectorCode;
/**
* 枪口状态
*/
private String connectorStatus;
}

View File

@@ -7,6 +7,7 @@ import com.jsowell.pile.dto.*;
import com.jsowell.pile.dto.nanrui.NRQueryOrderDTO;
import com.jsowell.pile.vo.base.MerchantOrderInfoVO;
import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO;
import com.jsowell.pile.vo.nanrui.NROrderInfoVO;
import com.jsowell.pile.vo.uniapp.OrderVO;
import com.jsowell.pile.vo.uniapp.PersonPileConnectorSumInfoVO;
import com.jsowell.pile.vo.uniapp.SendMessageVO;
@@ -254,5 +255,5 @@ public interface OrderBasicInfoMapper {
* @param dto
* @return
*/
List<NROrderInfo> getNROrderInfoByOrderCode(@Param("dto") NRQueryOrderDTO dto);
List<NROrderInfoVO> getNROrderInfoByOrderCode(@Param("dto") NRQueryOrderDTO dto);
}

View File

@@ -14,6 +14,7 @@ import com.jsowell.pile.vo.base.MerchantOrderInfoVO;
import com.jsowell.pile.vo.base.OrderAmountDetailVO;
import com.jsowell.pile.vo.base.OrderPeriodAmountVO;
import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO;
import com.jsowell.pile.vo.nanrui.NROrderInfoVO;
import com.jsowell.pile.vo.uniapp.OrderVO;
import com.jsowell.pile.vo.uniapp.PersonPileConnectorSumInfoVO;
import com.jsowell.pile.vo.uniapp.SendMessageVO;
@@ -361,12 +362,12 @@ public interface IOrderBasicInfoService {
* @param orderCode
* @return
*/
NROrderInfo getNROrderInfoByOrderCode(String orderCode);
NROrderInfoVO getNROrderInfoByOrderCode(String orderCode);
/**
* 通过充电结束时间批量查询
* @param dto
* @return
*/
List<NROrderInfo> getNROrderInfos(NRQueryOrderDTO dto);
List<NROrderInfoVO> getNROrderInfos(NRQueryOrderDTO dto);
}

View File

@@ -49,6 +49,7 @@ import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.base.*;
import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO;
import com.jsowell.pile.vo.nanrui.NROrderInfoVO;
import com.jsowell.pile.vo.uniapp.*;
import com.jsowell.pile.vo.web.*;
import com.jsowell.wxpay.common.WeChatPayParameter;
@@ -1000,31 +1001,30 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService {
* @return
*/
@Override
public NROrderInfo getNROrderInfoByOrderCode(String orderCode) {
public NROrderInfoVO getNROrderInfoByOrderCode(String orderCode) {
NRQueryOrderDTO dto = new NRQueryOrderDTO();
dto.setOrderCode(orderCode);
List<NROrderInfo> nrOrderInfos = orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
List<NROrderInfoVO> nrOrderInfos = orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
if (CollectionUtils.isEmpty(nrOrderInfos)) {
return null;
}
// 此方法仅通过订单编号查,因此只有一条数据
NROrderInfo nrOrderInfo = nrOrderInfos.get(0);
// 将组织机构代码截取后九位
String organizationCode = nrOrderInfo.getOperatorId();
String operatorId = StringUtils.substring(organizationCode, organizationCode.length() - 9);
nrOrderInfo.setOperatorId(operatorId);
nrOrderInfo.setUserChargeType(1);
// TODO 获取电表总起、止值
// pileMsgRecordService.getPileFeedList()
nrOrderInfo.setMeterValueStart(BigDecimal.ZERO);
nrOrderInfo.setMeterValueEnd(BigDecimal.ZERO);
return nrOrderInfo;
NROrderInfoVO nrOrderInfoVO = nrOrderInfos.get(0);
return nrOrderInfoVO;
}
/**
* 通过充电结束时间批量查询
* @param dto
* @return
*/
@Override
public List<NROrderInfo> getNROrderInfos(NRQueryOrderDTO dto) {
return orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
public List<NROrderInfoVO> getNROrderInfos(NRQueryOrderDTO dto) {
List<NROrderInfoVO> nrOrderInfoVOList = orderBasicInfoMapper.getNROrderInfoByOrderCode(dto);
if (CollectionUtils.isEmpty(nrOrderInfoVOList)) {
return new ArrayList<>();
}
return nrOrderInfoVOList;
}
/**

View File

@@ -0,0 +1,15 @@
package com.jsowell.pile.vo.nanrui;
import com.jsowell.pile.domain.nanrui.NROrderInfo;
import lombok.Data;
/**
* TODO
*
* @author Lemon
* @Date 2023/10/12 15:57
*/
@Data
public class NROrderInfoVO extends NROrderInfo {
private String stationId;
}

View File

@@ -1167,7 +1167,7 @@
station_id = #{stationId,jdbcType=BIGINT}
</update>
<select id="getNROrderInfoByOrderCode" resultType="com.jsowell.pile.domain.nanrui.NROrderInfo">
<select id="getNROrderInfoByOrderCode" resultType="com.jsowell.pile.vo.nanrui.NROrderInfoVO">
SELECT
t1.merchant_id,
t3.organization_code AS operatorId,

View File

@@ -79,7 +79,8 @@ public interface LianLianService {
* @param operatorSecret
* @return
*/
String getToken(String urlAddress, String operatorId, String operatorSecret, String dataSecretIv, String signSecret, String dataSecret);
String getToken(String urlAddress, String operatorId, String operatorSecret,
String dataSecretIv, String signSecret, String dataSecret);
/**
* 推送联联平台 设备状态变化推送

View File

@@ -744,12 +744,13 @@ public class LianLianServiceImpl implements LianLianService {
* @return
*/
@Override
public String getToken(String urlAddress, String operatorId, String operatorSecret, String dataSecretIv, String signSecret, String dataSecret) {
public String getToken(String urlAddress, String operatorId, String operatorSecret,
String dataSecretIv, String signSecret, String dataSecret) {
// String operatorId = dto.getOperatorId();
// String operatorSecret = dto.getOperatorSecret();
String token = "";
try {
// 测试用请求地址
// 请求地址
String requestUrl = urlAddress + "query_token";
// 请求data

View File

@@ -155,4 +155,71 @@ public class HttpRequestUtil {
// System.out.println("解密数据:" + plainData);
return resultMsg;
}
/**
* 南瑞平台发送请求
*
* TODO和联联平台一样的方法若测试通过则统一更换成上面的方法
*
* @param token 南瑞平台令牌
* @param data 要传输的JsonString格式数据
* @param url 请求地址
* @param dataSecret 消息密钥
* @param dataSecretIV 消息密钥初始化向量
* @param operatorId 运营商id
* @param sigSecret 签名密钥
* @return
*/
public static String nrSendPost(String token, String data, String url, String dataSecret,
String dataSecretIV, String operatorId, String sigSecret){
log.info("南瑞平台发送请求 data:{}", data);
//加密
byte[] encryptText = Cryptos.aesEncrypt(data.getBytes(),
dataSecret.getBytes(), dataSecretIV.getBytes());
String encryptData = Encodes.encodeBase64(encryptText);
System.out.println("加密数据:" + encryptData);
Map<String, String> params = Maps.newLinkedHashMap();
params.put("OperatorID", operatorId);
params.put("Data", encryptData);
params.put("TimeStamp", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date()));
params.put("Seq", "001");
String sign = GBSignUtils.sign(params, sigSecret);
params.put("Sig", sign);
String postData = JSON.toJSONString(params);
log.info("南瑞平台发送请求 最终提交数据:{}", postData);
// System.out.println("最终提交数据:" + postData);
String hutoolRequest = HttpRequest.post(url).header("Authorization", "Bearer " + token).body(postData).execute().body();
log.info("南瑞平台发送请求 接收到返回数据:{}", hutoolRequest);
// System.out.println("接收到返回数据:" + hutoolRequest);
Map<String, Object> map = (Map<String, Object>) JSON.parse(hutoolRequest);
log.info("南瑞平台发送请求 返回数据map:{}", JSON.toJSONString(map));
int ret = (int) map.get("Ret");
String resultMsg = (String) map.get("Msg");
if (ret != 0) {
// 表示请求有异常
log.error("南瑞平台发送请求 error:{}, 源数据:{}", resultMsg, data);
return resultMsg;
}
String rData = (String) map.get("Data");
byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(rData),
dataSecret.getBytes(), dataSecretIV.getBytes());
String plainData = "";
try {
plainData = new String(plainText, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
log.info("南瑞平台发送请求 解密数据:{}", plainData);
// System.out.println("解密数据:" + plainData);
return resultMsg;
}
}

View File

@@ -2,11 +2,15 @@ package com.jsowell.thirdparty.nanrui.service;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.pile.domain.nanrui.NROrderInfo;
import com.jsowell.pile.dto.PushStationInfoDTO;
import com.jsowell.pile.dto.QueryOrderDTO;
import com.jsowell.pile.dto.QueryStationInfoDTO;
import com.jsowell.pile.dto.nanrui.NRQueryOrderDTO;
import com.jsowell.pile.dto.nanrui.PushAlarmInfoDTO;
import com.jsowell.thirdparty.lianlian.dto.CommonParamsDTO;
import com.jsowell.thirdparty.nanrui.domain.NRStationStatusInfo;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
@@ -19,13 +23,35 @@ import java.util.Map;
*/
public interface NRService {
/**
* 从南瑞平台获取令牌
* @param
* @return
*/
public String getToken(String urlAddress, String operatorId, String operatorSecret,
String dataSecretIv, String signSecret, String dataSecret);
/**
* 生成令牌
* @param dto
* @return
* @throws UnsupportedEncodingException
*/
Map<String, String> generateToken(CommonParamsDTO dto) throws UnsupportedEncodingException;
/**
* 校验签名
* @param dto
*/
Map<String, String> checkoutSign(CommonParamsDTO dto);
/**
* 推送充电站信息
* @param stationId
* @param dto
* @return
* @throws ParseException
*/
public String notification_stationInfo(String stationId) throws ParseException;
public String pushStationInfo(PushStationInfoDTO dto) throws ParseException;
/**
@@ -38,11 +64,10 @@ public interface NRService {
/**
* 推送告警信息
* 当充电接口发生异常告警或故障时,运营商企业平台应立即主动推送信息到省、市两级监管平台
* @param pileConnectorCode
* @param connectorStatus
* @param dto
* @return
*/
String notification_alarmInfo(String pileConnectorCode, String connectorStatus);
String pushAlarmInfo(PushAlarmInfoDTO dto);
/**
@@ -50,7 +75,7 @@ public interface NRService {
* 当充电枪由 闲置 转为 充电 等状态发生变化时,运营商平台应立即推送当前状态到省、市两级监管平台。
* 充电过程中运营商平台应 每分钟 上报充电包含电流、电压在内的监测数据。
*/
String notification_stationStatus(RealTimeMonitorData realTimeMonitorData);
String pushPileStatus(RealTimeMonitorData realTimeMonitorData);
/**
@@ -69,7 +94,7 @@ public interface NRService {
* @param orderCode
* @return
*/
String notification_orderInfo(String orderCode);
String pushOrderInfo(String orderCode);
/**
* 查询充电电量信息

View File

@@ -1,5 +1,9 @@
package com.jsowell.thirdparty.nanrui.service.impl;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.jsowell.common.constant.CacheConstants;
@@ -12,23 +16,37 @@ import com.jsowell.common.util.PageUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.domain.nanrui.NROrderInfo;
import com.jsowell.pile.dto.PushStationInfoDTO;
import com.jsowell.pile.dto.QueryConnectorListDTO;
import com.jsowell.pile.dto.QueryStationInfoDTO;
import com.jsowell.pile.dto.nanrui.NRQueryOrderDTO;
import com.jsowell.pile.dto.nanrui.PushAlarmInfoDTO;
import com.jsowell.pile.service.*;
import com.jsowell.pile.vo.base.ThirdPartyStationRelationVO;
import com.jsowell.pile.vo.nanrui.NROrderInfoVO;
import com.jsowell.pile.vo.uniapp.CurrentTimePriceDetails;
import com.jsowell.pile.vo.web.PileConnectorInfoVO;
import com.jsowell.pile.vo.web.PileModelInfoVO;
import com.jsowell.pile.vo.web.PileStationVO;
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 com.jsowell.thirdparty.lianlian.vo.LianLianResultVO;
import com.jsowell.thirdparty.nanrui.domain.*;
import com.jsowell.thirdparty.nanrui.service.NRService;
import com.jsowell.thirdparty.nanrui.util.QEncodeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -58,20 +76,73 @@ public class NRServiceImpl implements NRService {
@Autowired
private IOrderBasicInfoService orderBasicInfoService;
@Autowired
private IThirdPartyStationRelationService thirdPartyStationRelationService;
@Autowired
private LianLianService lianLianService;
@Autowired
private RedisCache redisCache;
/**
* 充电站信息变化推送
* @param stationId
* 从南瑞平台获取令牌
* @param urlAddress
* @param operatorId
* @param operatorSecret
* @param dataSecretIv
* @param signSecret
* @param dataSecret
* @return
*/
@Override
public String notification_stationInfo(String stationId) throws ParseException {
PileStationVO stationInfoVO = pileStationInfoService.getStationInfo(stationId);
public String getToken(String urlAddress, String operatorId, String operatorSecret,
String dataSecretIv, String signSecret, String dataSecret) {
return lianLianService.getToken(urlAddress, operatorId, operatorSecret,
dataSecretIv, signSecret, dataSecret);
}
@Override
public Map<String, String> generateToken(CommonParamsDTO dto) throws UnsupportedEncodingException {
return lianLianService.generateToken(dto);
}
@Override
public Map<String, String> checkoutSign(CommonParamsDTO dto) {
return lianLianService.checkoutSign(dto);
}
/**
* 推送充电站信息
* @param dto
* @return
*/
@Override
public String pushStationInfo(PushStationInfoDTO dto) throws ParseException {
PileStationVO stationInfoVO = pileStationInfoService.getStationInfo(String.valueOf(dto.getStationId()));
if (stationInfoVO == null) {
return null;
}
// 通过站点id查询相关配置信息
ThirdPartyStationRelation relation = new ThirdPartyStationRelation();
relation.setStationId(dto.getStationId());
ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
// ThirdPartySettingInfo settingInfo = thirdPartySettingInfoService.getInfoByStationId(dto.getStationId());
if (relationInfo == null) {
// 新增
relation.setThirdPartyType(dto.getThirdPartyType());
thirdPartyStationRelationService.insertThirdPartyStationRelation(relation);
relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
}
String operatorId = relationInfo.getOperatorId();
String operatorSecret = relationInfo.getOperatorSecret();
String signSecret = relationInfo.getSignSecret();
String dataSecret = relationInfo.getDataSecret();
String dataSecretIv = relationInfo.getDataSecretIv();
String urlAddress = relationInfo.getUrlAddress();
// 拼装南瑞平台所需参数
NRStationInfo nrStationInfo = NRStationInfo.builder()
.stationId("NR" + stationInfoVO.getId())
@@ -103,25 +174,39 @@ public class NRServiceImpl implements NRService {
nrStationInfo.setStationType(Integer.parseInt(stationType));
nrStationInfo.setConstruction(255);
List<NREquipmentInfo> nrEquipmentInfos = getEquipmentInfo(stationId);
List<NREquipmentInfo> nrEquipmentInfos = getEquipmentInfo(String.valueOf(dto.getStationId()));
nrStationInfo.setEquipmentInfos(nrEquipmentInfos);
// TODO 推送到平台
// 推送到平台
String url = urlAddress + "notification_stationInfo";
return null;
String jsonStr = JSONObject.toJSONString(nrStationInfo);
JSONObject data = new JSONObject();
data.put("StationInfo", jsonStr);
String jsonString = JSONObject.toJSONString(data);
System.out.println("jsonString : " + jsonString);
// 获取令牌
String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
String result = HttpRequestUtil.nrSendPost(token, jsonString, url, dataSecret
, dataSecretIv, operatorId, signSecret);
// System.out.println(result);
return result;
}
/**
* 获取充电站信息
* @param dto
* @return
*/
@Override
public Map<String, Object> query_stations_info(QueryStationInfoDTO dto) {
List<NRStationInfo> resultList = new ArrayList<>();
int pageNo = dto.getPageNo() == null ? 1 : dto.getPageNo();
int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize();
// 查询密钥等配置
// ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(dto.getOperatorId());
// if (configInfo == null) {
// return null;
// }
PageUtils.startPage(pageNo, pageSize);
List<PileStationInfo> stationInfos = pileStationInfoService.getStationInfosByThirdParty();
if (CollectionUtils.isEmpty(stationInfos)) {
@@ -194,24 +279,38 @@ public class NRServiceImpl implements NRService {
/**
* 推送告警信息
* @param pileConnectorCode
* @param connectorStatus
* @param dto
* @return
*/
@Override
public String notification_alarmInfo(String pileConnectorCode, String connectorStatus) {
public String pushAlarmInfo(PushAlarmInfoDTO dto) {
List<NRAlarmInfo> nrAlarmInfos = new ArrayList<>();
// 通过站点id查询相关配置信息
ThirdPartyStationRelation relation = new ThirdPartyStationRelation();
relation.setStationId(dto.getStationId());
ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
if (relationInfo == null) {
return null;
}
String operatorId = relationInfo.getOperatorId();
String operatorSecret = relationInfo.getOperatorSecret();
String signSecret = relationInfo.getSignSecret();
String dataSecret = relationInfo.getDataSecret();
String dataSecretIv = relationInfo.getDataSecretIv();
String urlAddress = relationInfo.getUrlAddress();
// 从缓存中获取故障原因
String redisKey = CacheConstants.PILE_HARDWARE_FAULT + pileConnectorCode;
String redisKey = CacheConstants.PILE_HARDWARE_FAULT + dto.getPileConnectorCode();
String faultReason = redisCache.getCacheObject(redisKey);
int status = 0;
if (StringUtils.equals(connectorStatus, "01")) {
if (StringUtils.equals(dto.getConnectorStatus(), "01")) {
// 故障
status = 1;
}
// 封装对象
NRAlarmInfo alarmInfo = NRAlarmInfo.builder()
.connectorId(pileConnectorCode)
.connectorId(dto.getPileConnectorCode())
.alertTime(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS))
.alertCode(120) // 120-预留
.describe(faultReason)
@@ -219,13 +318,24 @@ public class NRServiceImpl implements NRService {
.build();
nrAlarmInfos.add(alarmInfo);
Map<String, Object> map = new LinkedHashMap<>();
map.put("AlarmInfos", nrAlarmInfos);
// TODO 发送请求
// 发送请求
String url = urlAddress + "notification_alarmInfo";
String jsonStr = JSONObject.toJSONString(nrAlarmInfos);
JSONObject data = new JSONObject();
data.put("AlarmInfos", jsonStr);
return null;
String jsonString = JSONObject.toJSONString(data);
System.out.println("jsonString : " + jsonString);
// 获取令牌
String token = getToken(urlAddress, operatorId, operatorSecret,
dataSecretIv, signSecret, dataSecret);
String result = HttpRequestUtil.nrSendPost(token, jsonString, url, dataSecret
, dataSecretIv, operatorId, signSecret);
return result;
}
/**
@@ -234,10 +344,35 @@ public class NRServiceImpl implements NRService {
* @return
*/
@Override
public String notification_stationStatus(RealTimeMonitorData realTimeMonitorData) {
public String pushPileStatus(RealTimeMonitorData realTimeMonitorData) {
String pileConnectorCode = realTimeMonitorData.getPileSn() + realTimeMonitorData.getConnectorCode();
String connectorStatus = realTimeMonitorData.getConnectorStatus();
String transactionCode = realTimeMonitorData.getTransactionCode();
// 查出该桩所属哪个站点
String pileSn = StringUtils.substring(pileConnectorCode, 0, 14);
PileStationVO stationVO = pileStationInfoService.getStationInfoByPileSn(pileSn);
// 通过站点id查询相关配置信息
ThirdPartyStationRelation relation = new ThirdPartyStationRelation();
relation.setStationId(Long.parseLong(stationVO.getId()));
ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
if (relationInfo == null) {
return null;
}
String operatorId = relationInfo.getOperatorId();
String operatorSecret = relationInfo.getOperatorSecret();
String signSecret = relationInfo.getSignSecret();
String dataSecret = relationInfo.getDataSecret();
String dataSecretIv = relationInfo.getDataSecretIv();
String urlAddress = relationInfo.getUrlAddress();
String url = urlAddress + "notification_stationStatus";
// 获取令牌
String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
if (StringUtils.isBlank(token)) {
return null;
}
// 根据交易流水号查询订单信息
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode);
// 封装对象
@@ -256,14 +391,22 @@ public class NRServiceImpl implements NRService {
nrConnectorStatusInfo.setSoc(new BigDecimal(realTimeMonitorData.getSOC()).setScale(1, BigDecimal.ROUND_HALF_UP));
}
Map<String, Object> map = new LinkedHashMap<>();
map.put("ConnectorStatusInfo", nrConnectorStatusInfo);
// 发送请求
JSONObject json = new JSONObject();
json.put("ConnectorStatusInfo", nrConnectorStatusInfo);
String jsonString = JSONObject.toJSONString(json);
// TODO 发送请求
return null;
String result = HttpRequestUtil.nrSendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
return result;
}
/**
* 查询设备接口状态
* 此接口用于批量查询设备实时状态
* 由充电运营商方实现此接口,省、市两级监管平台调用。
* @param stationIds
* @return
*/
@Override
public Map<String, Object> query_station_status(List<String> stationIds) {
List<NRStationStatusInfo> resultList = new ArrayList<>();
@@ -329,31 +472,97 @@ public class NRServiceImpl implements NRService {
return map;
}
/**
* 充电电量信息推送
* 当运营商平台完成一次充电时,将充电电量信息推送至省、市两级监管平台
* @param orderCode
* @return
*/
@Override
public String notification_orderInfo(String orderCode) {
public String pushOrderInfo(String orderCode) {
// 根据订单号查询订单信息
NROrderInfo nrOrderInfo = orderBasicInfoService.getNROrderInfoByOrderCode(orderCode);
// TODO 发送请求
Map<String, Object> map = new LinkedHashMap<>();
map.put("OrderInfo", nrOrderInfo);
NROrderInfoVO nrOrderInfoVO = orderBasicInfoService.getNROrderInfoByOrderCode(orderCode);
NROrderInfo nrOrderInfo = formatNROrderInfo((nrOrderInfoVO));
return null;
// 通过站点id查询相关配置信息
ThirdPartyStationRelation relation = new ThirdPartyStationRelation();
relation.setStationId(Long.parseLong(nrOrderInfoVO.getStationId()));
ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation);
if (relationInfo == null) {
return null;
}
String operatorId = relationInfo.getOperatorId();
String operatorSecret = relationInfo.getOperatorSecret();
String signSecret = relationInfo.getSignSecret();
String dataSecret = relationInfo.getDataSecret();
String dataSecretIv = relationInfo.getDataSecretIv();
String urlAddress = relationInfo.getUrlAddress();
String url = urlAddress + "notification_orderInfo";
// 获取令牌
String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
if (StringUtils.isBlank(token)) {
return null;
}
// 发送请求
JSONObject jsonObject = new JSONObject();
jsonObject.put("OrderInfo", nrOrderInfo);
String jsonString = JSONObject.toJSONString(jsonObject);
String result = HttpRequestUtil.nrSendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
return result;
}
@Override
public List<NROrderInfo> query_order_info(NRQueryOrderDTO dto) {
List<NROrderInfo> nrOrderInfos = orderBasicInfoService.getNROrderInfos(dto);
List<NROrderInfo> resultList = new ArrayList<>();
List<NROrderInfoVO> nrOrderInfos = orderBasicInfoService.getNROrderInfos(dto);
if (CollectionUtils.isEmpty(nrOrderInfos)) {
return new ArrayList<>();
}
// 将组织机构代码只取后9位数
for (NROrderInfo nrOrderInfo : nrOrderInfos) {
String operatorId = nrOrderInfo.getOperatorId();
if (StringUtils.isNotBlank(operatorId)) {
nrOrderInfo.setOperatorId(StringUtils.substring(operatorId, operatorId.length() - 9));
}
for (NROrderInfoVO nrOrderInfoVO : nrOrderInfos) {
NROrderInfo nrOrderInfo = formatNROrderInfo(nrOrderInfoVO);
resultList.add(nrOrderInfo);
}
return nrOrderInfos;
return resultList;
}
/**
* 格式化南瑞平台订单对象
* @param nrOrderInfoVO
* @return
*/
private NROrderInfo formatNROrderInfo(NROrderInfoVO nrOrderInfoVO) {
// 将组织机构代码截取后九位
String organizationCode = nrOrderInfoVO.getOperatorId();
if (StringUtils.isBlank(organizationCode)) {
return null;
}
String operatorId = StringUtils.substring(organizationCode, organizationCode.length() - 9);
NROrderInfo nrOrderInfo = NROrderInfo.builder()
.operatorId(operatorId)
.connectorId(nrOrderInfoVO.getConnectorId())
.startChargeSeq(nrOrderInfoVO.getStartChargeSeq())
.userChargeType(1)
.elect(nrOrderInfoVO.getElect())
.cuspElect(nrOrderInfoVO.getCuspElect())
.peakElect(nrOrderInfoVO.getPeakElect())
.flatElect(nrOrderInfoVO.getFlatElect())
.valleyElect(nrOrderInfoVO.getValleyElect())
.startTime(nrOrderInfoVO.getStartTime())
.endTime(nrOrderInfoVO.getEndTime())
.build();
// TODO 获取电表总起、止值
// pileMsgRecordService.getPileFeedList()
nrOrderInfo.setMeterValueStart(BigDecimal.ZERO);
nrOrderInfo.setMeterValueEnd(BigDecimal.ZERO);
return nrOrderInfo;
}
public static void main(String[] args) {

View File

@@ -0,0 +1,98 @@
package com.jsowell.thirdparty.nanrui.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* TODO
*
* @author Lemon
* @Date 2023/10/12 13:42
*/
public class NRMD5Util {
public static void main(String[] args) {
String sigSecret = "yyyyyyyyyyyyyyyy";
String dataSecret = "DDDDDDD";
String dataSecretIv = "XXXXXXXX";
String operatorId = "MA002TMQX";
String data = "{'EquipAuthSeq':'MA002TMQX202004090925368255','ConnectorID':'MA01H3BQ1_1306060015204'}";
String retData = QEncodeUtil.encrypt(data, dataSecret, dataSecretIv);
String timeStamp = "20200409000000";
String seq = "0001";
String sig = getHmacMd5Str(sigSecret, operatorId + retData + timeStamp + seq);
}
public static String getHmacMd5Str(String key, String data) {
String result = "";
try {
byte[] keyByte = key.getBytes("UTF-8");
byte[] dataByte = data.getBytes("UTF-8");
byte[] hmacMd5Byte = getHmacMd5Bytes(keyByte, dataByte);
StringBuffer md5StrBuff = new StringBuffer();
for (byte b : hmacMd5Byte) {
if (Integer.toHexString(0xFF & b).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & b));
else md5StrBuff.append(Integer.toHexString(0xFF & b));
}
result = md5StrBuff.toString().toUpperCase();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static byte[] getHmacMd5Bytes(byte[] key, byte[] data) throws NoSuchAlgorithmException {
/**
* HmacMd5 calculation formula: H(K XOR opad, H(K XOR ipad, text))
* HmacMd5 计算公式H(K XOR opad, H(K XOR ipad, text))
* H 代表 hash 算法,本类中使用 MD5 算法K 代表密钥text 代表要加密的数据 ipad 为 0x36opad 为 0x5C。
*/
int length = 64;
byte[] ipad = new byte[length];
byte[] opad = new byte[length];
for (int i = 0; i < 64; i++) {
ipad[i] = 0x36;
opad[i] = 0x5C;
}
byte[] actualKey = key;
// Actual key.
byte[] keyArr = new byte[length];
// 如果密钥长度,大于 64 字节,就使用哈希算法,计算其摘要,作为真正的密钥。
if (key.length > length) {
actualKey = md5(key);
}
// append zeros to K 如果密钥长度不足 64 字节,就使用 0x00 补齐到 64 字节。
System.arraycopy(actualKey, 0, keyArr, 0, actualKey.length);
if (actualKey.length < length) {
for (int i = actualKey.length; i < keyArr.length; i++) keyArr[i] = 0x00;
}
// calc K XOR ipad 使用密钥和 ipad 进行异或运算。
byte[] kIpadXorResult = new byte[length];
for (int i = 0; i < length; i++) {
kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
}
// append "text" to the end of "K XOR ipad" 将待加密数据追加到 K XOR ipad 计算结果后面。
byte[] firstAppendResult = new byte[kIpadXorResult.length + data.length];
System.arraycopy(kIpadXorResult, 0, firstAppendResult, 0, kIpadXorResult.length);
// calc H(K XOR ipad, text) 使用哈希算法计算上面结果的摘要
System.arraycopy(data, 0, firstAppendResult, keyArr.length, data.length);
// calc K XOR opad 使用密钥和 opad 进行异或运算。
byte[] firstHashResult = md5(firstAppendResult);
byte[] kOpadXorResult = new byte[length];
for (int i = 0; i < length; i++) {
kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
}
// 将 H(K XOR * ipad, text)结果追加到 K XOR opad 结果后面
byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length]; //
System.arraycopy(kOpadXorResult, 0, secondAppendResult, 0, kOpadXorResult.length);
// 对上面的数据进行哈希运算。
System.arraycopy(firstHashResult, 0, secondAppendResult, keyArr.length, firstHashResult.length);
return md5(secondAppendResult);
}
private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str);
return md.digest();
}
}

View File

@@ -0,0 +1,73 @@
package com.jsowell.thirdparty.nanrui.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* TODO
*
* @author Lemon
* @Date 2023/10/12 13:54
*/
public class QEncodeUtil {
public static String encrypt(String sSrc, String sKey, String datasecretiv) {
try {
if (sKey == null) {
return null;
}
// 判断 Key 是否为 16 位
if (sKey.length() != 16) {
return null;
}
byte[] raw = sKey.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
IvParameterSpec iv = new IvParameterSpec(datasecretiv.getBytes());//使用 CBC 模式,需要一个向量 iv可增加加密算法的强度 1234567890123456
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(sSrc.getBytes());
String str = new BASE64Encoder().encode(encrypted); // 此处使用 BASE64 做转码功能,同时能起到 2 次加密的作用。
str = str.replaceAll("\r", "");
str = str.replaceAll("\n", "");
return str;
} catch (Exception ex) {
return null;
}
}
// 解密
public static String decrypt(String sSrc, String sKey, String datasecretiv) {
try {
// 判断 Key 是否正确
if (sKey == null) {
System.out.print("Key 为空 null");
return null;
}
// 判断 Key 是否为 16 位
if (sKey.length() != 16) {
System.out.print("Key 长度不是 16 位");
return null;
}
byte[] raw = sKey.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(datasecretiv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);
//先用 base64 解密
try {
byte[] original = cipher.doFinal(encrypted1);
return new String(original, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
return null;
}
} catch (Exception ex) {
return null;
}
}
}

View File

@@ -2,13 +2,8 @@ package com.jsowell.thirdparty.zhongdianlian.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.enums.lianlian.LianLianPileStatusEnum;
import com.jsowell.common.enums.lianlian.StationPaymentEnum;
import com.jsowell.common.enums.ykc.PileStatusEnum;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.PageUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.*;
@@ -17,9 +12,6 @@ import com.jsowell.pile.dto.QueryStationInfoDTO;
import com.jsowell.pile.service.*;
import com.jsowell.pile.vo.base.ThirdPartyStationRelationVO;
import com.jsowell.pile.vo.web.PileModelInfoVO;
import com.jsowell.thirdparty.lianlian.domain.ConnectorInfo;
import com.jsowell.thirdparty.lianlian.domain.EquipmentInfo;
import com.jsowell.thirdparty.lianlian.domain.StationInfo;
import com.jsowell.thirdparty.lianlian.dto.CommonParamsDTO;
import com.jsowell.thirdparty.lianlian.service.LianLianService;
import com.jsowell.thirdparty.lianlian.util.Cryptos;