diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java index c48c067e6..320887462 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java @@ -59,556 +59,555 @@ import java.util.Objects; @Slf4j @Component public class TransactionRecordsRequestHandler extends AbstractHandler { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes()); - private final String oldVersionType = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_OLD_VERSION_CODE.getBytes()); + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes()); + private final String oldVersionType = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_OLD_VERSION_CODE.getBytes()); - @Override - public void afterPropertiesSet() throws Exception { - YKCOperateFactory.register(type, this); - YKCOperateFactory.register(oldVersionType, this); - } + @Override + public void afterPropertiesSet() throws Exception { + YKCOperateFactory.register(type, this); + YKCOperateFactory.register(oldVersionType, this); + } - @Autowired - private RedisCache redisCache; + @Autowired + private RedisCache redisCache; - @Autowired - private IPileMsgRecordService pileMsgRecordService; + @Autowired + private IPileMsgRecordService pileMsgRecordService; - @Autowired - private IOrderBasicInfoService orderBasicInfoService; + @Autowired + private IOrderBasicInfoService orderBasicInfoService; - @Autowired - private IPileMerchantInfoService pileMerchantInfoService; + @Autowired + private IPileMerchantInfoService pileMerchantInfoService; - @Autowired - private LianLianService lianLianService; + @Autowired + private LianLianService lianLianService; - @Autowired - private ZDLService zdlService; + @Autowired + private ZDLService zdlService; - @Autowired - private NRService nrService; + @Autowired + private NRService nrService; - @Autowired - private YCBCService ycbcService; + @Autowired + private YCBCService ycbcService; - @Autowired - private IThirdPartyStationRelationService thirdPartyStationRelationService; + @Autowired + private IThirdPartyStationRelationService thirdPartyStationRelationService; + + @Autowired + private IPileStationInfoService pileStationInfoService; - @Autowired - private IPileStationInfoService pileStationInfoService; + @Autowired + private LTYTService ltytService; - @Autowired - private LTYTService ltytService; - - @Autowired - private RJService rjService; - - @Autowired - private IThirdPartyParkingConfigService thirdPartyParkingConfigService; - - public static void main(String[] args) { - BigDecimal totalElectricity = new BigDecimal("23.73"); - if (totalElectricity.compareTo(BigDecimal.TEN) > 0 ) { - // 充电度数大于10度 - System.out.println("123"); - } - - - - // 获取消息体 - String msg = "000000000000000000000000000000008823000000030601a08c2e0d0404170000380d0404170000000000000000000000000000000000000000000000000000000000000000400d0300ee250000ee250000c84b000000000000000000000000000000000000e0bb040000cee1040000ee250000ee250000c84b00000000000000000000000000000000000000010000380d04041745a511101970000000"; - byte[] msgBody = BytesUtil.str2Bcd(msg); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - - // 开始时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String binary = BytesUtil.binary(startTimeByteArr, 16); - Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); - String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); - - - // 结束时间 CP56Time2a 格式 - startIndex += length; - byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); - String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); - - // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) - startIndex += length; - length = 4; - byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); - - // 尖电量 精确到小数点后四位 - startIndex += length; - length = 4; - byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); - - // 计损尖电量 - startIndex += length; - byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); - - // 尖金额 - startIndex += length; - byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); - - // 峰单价 精确到小数点后五位(峰电费+峰服务费) - startIndex += length; - byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); - - // 峰电量 - startIndex += length; - byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); - - // 计损峰电量 - startIndex += length; - byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); - - // 峰金额 - startIndex += length; - byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); - - // 平单价 精确到小数点后五位(平电费+平服务费) - startIndex += length; - byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); - - // 平电量 - startIndex += length; - byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); - - // 计损平电量 - startIndex += length; - byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); - - // 平金额 - startIndex += length; - byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); - - // 谷单价 精确到小数点后五位(谷电费+谷 服务费) - startIndex += length; - byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); - - // 谷电量 - startIndex += length; - byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); - - // 计损谷电量 - startIndex += length; - byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); - - // 谷金额 - startIndex += length; - byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); - - // 电表总起值 - startIndex += length; - length = 5; - byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); - - // 电表总止值 - startIndex += length; - byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); - - // 总电量 - startIndex += length; - length = 4; - byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); - - // 计损总电量 - startIndex += length; - byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); - - // 消费金额 精确到小数点后四位,包含电费、 服务费 - startIndex += length; - byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); - - // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = BytesUtil.ascii2Str(vinCodeByteArr); - - /** - * 交易标识 - * 0x01: app 启动 - * 0x02:卡启动 - * 0x04:离线卡启动 - * 0x05: vin 码启动充电 - */ - startIndex += length; - length = 1; - byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); - - // 交易时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); - String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); - - // 停止原因 - startIndex += length; - length = 1; - byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); - String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16)); - - // 物理卡号 不足 8 位补 0 - startIndex += length; - length = 8; - byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16); - String logicCard = BytesUtil.binary(cardNumByteArr, 16); - log.info("桩号:{}发送交易记录物理卡号:{}", pileSn, logicCard); - - log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + - "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + - "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + - "电动汽车唯一标识:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", - transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, - peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, - valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, - consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); - - // 交易记录封装到对象里 - TransactionRecordsData data = TransactionRecordsData.builder() - // .orderCode(transactionCode) - .transactionCode(transactionCode) - .pileSn(pileSn) - .connectorCode(connectorCode) - .startTime(startTime) - .endTime(endTime) - .sharpPrice(sharpPrice) - .sharpUsedElectricity(sharpUsedElectricity) - .sharpPlanLossElectricity(sharpPlanLossElectricity) - .sharpAmount(sharpAmount) - .peakPrice(peakPrice) - .peakUsedElectricity(peakUsedElectricity) - .peakPlanLossElectricity(peakPlanLossElectricity) - .peakAmount(peakAmount) - .flatPrice(flatPrice) - .flatUsedElectricity(flatUsedElectricity) - .flatPlanLossElectricity(flatPlanLossElectricity) - .flatAmount(flatAmount) - .valleyPrice(valleyPrice) - .valleyUsedElectricity(valleyUsedElectricity) - .valleyPlanLossElectricity(valleyPlanLossElectricity) - .valleyAmount(valleyAmount) - .ammeterTotalStart(ammeterTotalStart) - .ammeterTotalEnd(ammeterTotalEnd) - // .totalElectricity(totalElectricity) - .planLossTotalElectricity(planLossTotalElectricity) - .consumptionAmount(consumptionAmount) - .vinCode(vinCode) - .transactionIdentifier(transactionIdentifier) - .transactionTime(transactionTime) - .stopReasonMsg(stopReasonMsg) - .logicCard(logicCard) - .build(); - - boolean flag = !StringUtils.equals("0000000000000000", "a511101970000000"); - System.out.println(flag); - - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) { - // log.info("[===交易记录===] param:{}, channel:{}", JSONObject.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - - // 开始时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String binary = BytesUtil.binary(startTimeByteArr, 16); - Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); - String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); - - - // 结束时间 CP56Time2a 格式 - startIndex += length; - byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); - String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); - - // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) - startIndex += length; - length = 4; - byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); - - // 尖电量 精确到小数点后四位 - startIndex += length; - length = 4; - byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); - - // 计损尖电量 - startIndex += length; - byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); - - // 尖金额 - startIndex += length; - byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); - - // 峰单价 精确到小数点后五位(峰电费+峰服务费) - startIndex += length; - byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); - - // 峰电量 - startIndex += length; - byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); - - // 计损峰电量 - startIndex += length; - byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); - - // 峰金额 - startIndex += length; - byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); - - // 平单价 精确到小数点后五位(平电费+平服务费) - startIndex += length; - byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); - - // 平电量 - startIndex += length; - byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); - - // 计损平电量 - startIndex += length; - byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); - - // 平金额 - startIndex += length; - byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); - - // 谷单价 精确到小数点后五位(谷电费+谷 服务费) - startIndex += length; - byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); - - // 谷电量 - startIndex += length; - byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); - - // 计损谷电量 - startIndex += length; - byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); - - // 谷金额 - startIndex += length; - byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); - - // 电表总起值 - startIndex += length; - length = 5; - byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); - - // 电表总止值 - startIndex += length; - byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); - - // 总电量 - startIndex += length; - length = 4; - byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); - - // 计损总电量 - startIndex += length; - byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); - - // 消费金额 精确到小数点后四位,包含电费、 服务费 - startIndex += length; - byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); - - // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = BytesUtil.ascii2Str(vinCodeByteArr); - - /** - * 交易标识 - * 0x01: app 启动 - * 0x02:卡启动 - * 0x04:离线卡启动 - * 0x05: vin 码启动充电 - */ - startIndex += length; - length = 1; - byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); - - // 交易时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); - String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); - - // 停止原因 - startIndex += length; - length = 1; - byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); - String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16)); - - // 物理卡号 不足 8 位补 0 - startIndex += length; - length = 8; - byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16); - String logicCard = BytesUtil.binary(cardNumByteArr, 16); - log.info("桩号:{}发送交易记录物理卡号:{}", pileSn, logicCard); - - log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + - "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + - "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + - "vin码:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", - transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, - peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, - valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, - consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); - - // 交易记录封装到对象里 - TransactionRecordsData data = TransactionRecordsData.builder() - // .orderCode(transactionCode) - .transactionCode(transactionCode) - .pileSn(pileSn) - .connectorCode(connectorCode) - .startTime(startTime) - .endTime(endTime) - .sharpPrice(sharpPrice) - .sharpUsedElectricity(sharpUsedElectricity) - .sharpPlanLossElectricity(sharpPlanLossElectricity) - .sharpAmount(sharpAmount) - .peakPrice(peakPrice) - .peakUsedElectricity(peakUsedElectricity) - .peakPlanLossElectricity(peakPlanLossElectricity) - .peakAmount(peakAmount) - .flatPrice(flatPrice) - .flatUsedElectricity(flatUsedElectricity) - .flatPlanLossElectricity(flatPlanLossElectricity) - .flatAmount(flatAmount) - .valleyPrice(valleyPrice) - .valleyUsedElectricity(valleyUsedElectricity) - .valleyPlanLossElectricity(valleyPlanLossElectricity) - .valleyAmount(valleyAmount) - .ammeterTotalStart(ammeterTotalStart) - .ammeterTotalEnd(ammeterTotalEnd) - .totalElectricity(totalElectricity) - .planLossTotalElectricity(planLossTotalElectricity) - .consumptionAmount(consumptionAmount) - .vinCode(vinCode) - .transactionIdentifier(transactionIdentifier) - .transactionTime(transactionTime) - .stopReasonMsg(stopReasonMsg) - .logicCard(logicCard) - .build(); - - // 保存报文 - String jsonMsg = JSONObject.toJSONString(data); - pileMsgRecordService.save(pileSn, pileSn + connectorCode, type, jsonMsg, ykcDataProtocol.getHEXString()); - - // 处理订单加锁 - String lockKey = "settle_order_" + transactionCode; - String uuid = IdUtils.fastUUID(); - try { - // redis锁 - Boolean isLock = redisCache.lock(lockKey, uuid, 1500); - if (isLock) { - processOrder(data); - } - } catch (Exception e) { - log.error("处理订单发生异常", e); - } finally { - if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) { - redisCache.unLock(lockKey); - } - } + @Autowired + private RJService rjService; + + @Autowired + private IThirdPartyParkingConfigService thirdPartyParkingConfigService; + + public static void main(String[] args) { + BigDecimal totalElectricity = new BigDecimal("23.73"); + if (totalElectricity.compareTo(BigDecimal.TEN) > 0) { + // 充电度数大于10度 + System.out.println("123"); + } + + + // 获取消息体 + String msg = "000000000000000000000000000000008823000000030601a08c2e0d0404170000380d0404170000000000000000000000000000000000000000000000000000000000000000400d0300ee250000ee250000c84b000000000000000000000000000000000000e0bb040000cee1040000ee250000ee250000c84b00000000000000000000000000000000000000010000380d04041745a511101970000000"; + byte[] msgBody = BytesUtil.str2Bcd(msg); + + int startIndex = 0; + int length = 16; + + // 交易流水号 + byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); + + // 桩编码 + startIndex += length; + length = 7; + byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.bcd2Str(pileSnByteArr); + + // 枪号 + startIndex += length; + length = 1; + byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); + + + // 开始时间 CP56Time2a 格式 + startIndex += length; + length = 7; + byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // String binary = BytesUtil.binary(startTimeByteArr, 16); + Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); + String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); + + + // 结束时间 CP56Time2a 格式 + startIndex += length; + byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); + String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); + + // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) + startIndex += length; + length = 4; + byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); + + // 尖电量 精确到小数点后四位 + startIndex += length; + length = 4; + byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); + + // 计损尖电量 + startIndex += length; + byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); + + // 尖金额 + startIndex += length; + byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); + + // 峰单价 精确到小数点后五位(峰电费+峰服务费) + startIndex += length; + byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); + + // 峰电量 + startIndex += length; + byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); + + // 计损峰电量 + startIndex += length; + byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); + + // 峰金额 + startIndex += length; + byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); + + // 平单价 精确到小数点后五位(平电费+平服务费) + startIndex += length; + byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); + + // 平电量 + startIndex += length; + byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); + + // 计损平电量 + startIndex += length; + byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); + + // 平金额 + startIndex += length; + byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); + + // 谷单价 精确到小数点后五位(谷电费+谷 服务费) + startIndex += length; + byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); + + // 谷电量 + startIndex += length; + byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); + + // 计损谷电量 + startIndex += length; + byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); + + // 谷金额 + startIndex += length; + byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); + + // 电表总起值 + startIndex += length; + length = 5; + byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); + + // 电表总止值 + startIndex += length; + byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); + + // 总电量 + startIndex += length; + length = 4; + byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); + + // 计损总电量 + startIndex += length; + byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); + + // 消费金额 精确到小数点后四位,包含电费、 服务费 + startIndex += length; + byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); + + // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 + startIndex += length; + length = 17; + byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String vinCode = BytesUtil.ascii2Str(vinCodeByteArr); + + /** + * 交易标识 + * 0x01: app 启动 + * 0x02:卡启动 + * 0x04:离线卡启动 + * 0x05: vin 码启动充电 + */ + startIndex += length; + length = 1; + byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); + + // 交易时间 CP56Time2a 格式 + startIndex += length; + length = 7; + byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); + String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); + + // 停止原因 + startIndex += length; + length = 1; + byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); + String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16)); + + // 物理卡号 不足 8 位补 0 + startIndex += length; + length = 8; + byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16); + String logicCard = BytesUtil.binary(cardNumByteArr, 16); + log.info("桩号:{}, 发送交易记录物理卡号:{}", pileSn, logicCard); + + log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + + "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + + "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + + "电动汽车唯一标识:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", + transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, + peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, + valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, + consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); + + // 交易记录封装到对象里 + TransactionRecordsData data = TransactionRecordsData.builder() + // .orderCode(transactionCode) + .transactionCode(transactionCode) + .pileSn(pileSn) + .connectorCode(connectorCode) + .startTime(startTime) + .endTime(endTime) + .sharpPrice(sharpPrice) + .sharpUsedElectricity(sharpUsedElectricity) + .sharpPlanLossElectricity(sharpPlanLossElectricity) + .sharpAmount(sharpAmount) + .peakPrice(peakPrice) + .peakUsedElectricity(peakUsedElectricity) + .peakPlanLossElectricity(peakPlanLossElectricity) + .peakAmount(peakAmount) + .flatPrice(flatPrice) + .flatUsedElectricity(flatUsedElectricity) + .flatPlanLossElectricity(flatPlanLossElectricity) + .flatAmount(flatAmount) + .valleyPrice(valleyPrice) + .valleyUsedElectricity(valleyUsedElectricity) + .valleyPlanLossElectricity(valleyPlanLossElectricity) + .valleyAmount(valleyAmount) + .ammeterTotalStart(ammeterTotalStart) + .ammeterTotalEnd(ammeterTotalEnd) + // .totalElectricity(totalElectricity) + .planLossTotalElectricity(planLossTotalElectricity) + .consumptionAmount(consumptionAmount) + .vinCode(vinCode) + .transactionIdentifier(transactionIdentifier) + .transactionTime(transactionTime) + .stopReasonMsg(stopReasonMsg) + .logicCard(logicCard) + .build(); + + boolean flag = !StringUtils.equals("0000000000000000", "a511101970000000"); + System.out.println(flag); + + } + + @Override + public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) { + // log.info("[===交易记录===] param:{}, channel:{}", JSONObject.toJSONString(ykcDataProtocol), channel.toString()); + // 获取消息体 + byte[] msgBody = ykcDataProtocol.getMsgBody(); + + int startIndex = 0; + int length = 16; + + // 交易流水号 + byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); + + // 桩编码 + startIndex += length; + length = 7; + byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.bcd2Str(pileSnByteArr); + + // 枪号 + startIndex += length; + length = 1; + byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); + + + // 开始时间 CP56Time2a 格式 + startIndex += length; + length = 7; + byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // String binary = BytesUtil.binary(startTimeByteArr, 16); + Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); + String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); + + + // 结束时间 CP56Time2a 格式 + startIndex += length; + byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); + String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); + + // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) + startIndex += length; + length = 4; + byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); + + // 尖电量 精确到小数点后四位 + startIndex += length; + length = 4; + byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); + + // 计损尖电量 + startIndex += length; + byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); + + // 尖金额 + startIndex += length; + byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); + + // 峰单价 精确到小数点后五位(峰电费+峰服务费) + startIndex += length; + byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); + + // 峰电量 + startIndex += length; + byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); + + // 计损峰电量 + startIndex += length; + byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); + + // 峰金额 + startIndex += length; + byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); + + // 平单价 精确到小数点后五位(平电费+平服务费) + startIndex += length; + byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); + + // 平电量 + startIndex += length; + byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); + + // 计损平电量 + startIndex += length; + byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); + + // 平金额 + startIndex += length; + byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); + + // 谷单价 精确到小数点后五位(谷电费+谷 服务费) + startIndex += length; + byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); + + // 谷电量 + startIndex += length; + byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); + + // 计损谷电量 + startIndex += length; + byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); + + // 谷金额 + startIndex += length; + byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); + + // 电表总起值 + startIndex += length; + length = 5; + byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); + + // 电表总止值 + startIndex += length; + byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); + + // 总电量 + startIndex += length; + length = 4; + byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); + + // 计损总电量 + startIndex += length; + byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); + + // 消费金额 精确到小数点后四位,包含电费、 服务费 + startIndex += length; + byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); + + // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 + startIndex += length; + length = 17; + byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String vinCode = BytesUtil.ascii2Str(vinCodeByteArr); + + /** + * 交易标识 + * 0x01: app 启动 + * 0x02:卡启动 + * 0x04:离线卡启动 + * 0x05: vin 码启动充电 + */ + startIndex += length; + length = 1; + byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); + + // 交易时间 CP56Time2a 格式 + startIndex += length; + length = 7; + byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); + String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); + + // 停止原因 + startIndex += length; + length = 1; + byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); + String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16)); + + // 物理卡号 不足 8 位补 0 + startIndex += length; + length = 8; + byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16); + String logicCard = BytesUtil.binary(cardNumByteArr, 16); + log.info("桩号:{}, 发送交易记录物理卡号:{}", pileSn, logicCard); + + log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + + "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + + "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + + "vin码:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", + transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, + peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, + valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, + consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); + + // 交易记录封装到对象里 + TransactionRecordsData data = TransactionRecordsData.builder() + // .orderCode(transactionCode) + .transactionCode(transactionCode) + .pileSn(pileSn) + .connectorCode(connectorCode) + .startTime(startTime) + .endTime(endTime) + .sharpPrice(sharpPrice) + .sharpUsedElectricity(sharpUsedElectricity) + .sharpPlanLossElectricity(sharpPlanLossElectricity) + .sharpAmount(sharpAmount) + .peakPrice(peakPrice) + .peakUsedElectricity(peakUsedElectricity) + .peakPlanLossElectricity(peakPlanLossElectricity) + .peakAmount(peakAmount) + .flatPrice(flatPrice) + .flatUsedElectricity(flatUsedElectricity) + .flatPlanLossElectricity(flatPlanLossElectricity) + .flatAmount(flatAmount) + .valleyPrice(valleyPrice) + .valleyUsedElectricity(valleyUsedElectricity) + .valleyPlanLossElectricity(valleyPlanLossElectricity) + .valleyAmount(valleyAmount) + .ammeterTotalStart(ammeterTotalStart) + .ammeterTotalEnd(ammeterTotalEnd) + .totalElectricity(totalElectricity) + .planLossTotalElectricity(planLossTotalElectricity) + .consumptionAmount(consumptionAmount) + .vinCode(vinCode) + .transactionIdentifier(transactionIdentifier) + .transactionTime(transactionTime) + .stopReasonMsg(stopReasonMsg) + .logicCard(logicCard) + .build(); + + // 保存报文 + String jsonMsg = JSONObject.toJSONString(data); + pileMsgRecordService.save(pileSn, pileSn + connectorCode, type, jsonMsg, ykcDataProtocol.getHEXString()); + + // 处理订单加锁 + String lockKey = "settle_order_" + transactionCode; + String uuid = IdUtils.fastUUID(); + try { + // redis锁 + Boolean isLock = redisCache.lock(lockKey, uuid, 1500); + if (isLock) { + processOrder(data); + } + } catch (Exception e) { + log.error("处理订单发生异常", e); + } finally { + if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) { + redisCache.unLock(lockKey); + } + } @@ -617,159 +616,161 @@ public class TransactionRecordsRequestHandler extends AbstractHandler { 确认结果 0x00 上传成功 0x01 非法账单 2022年12月15日11点28分发现返回 01非法账单,充电桩会持续上传交易记录,后面产生的交易记录被阻塞 */ - byte[] confirmResultBytes = Constants.zeroByteArray; - byte[] concatMsgBody = Bytes.concat(orderCodeByteArr, confirmResultBytes); + byte[] confirmResultBytes = Constants.zeroByteArray; + byte[] concatMsgBody = Bytes.concat(orderCodeByteArr, confirmResultBytes); - return getResult(ykcDataProtocol, concatMsgBody); - } + return getResult(ykcDataProtocol, concatMsgBody); + } - /** - * 收到交易记录 处理订单 - * @param data - */ - private void processOrder(TransactionRecordsData data) { - String transactionCode = data.getTransactionCode(); - // 根据交易流水号查询订单信息 - OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (orderBasicInfo != null) { - // 平台存在订单 - orderBasicInfo.setReason(data.getStopReasonMsg()); - // 如果订单状态为 异常,则改为 待结算 - if (StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), orderBasicInfo.getOrderStatus())) { - orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); - } - // 校验一下开始时间和结束时间,防止充电中桩离线,时间不准确 - if (Objects.isNull(orderBasicInfo.getChargeStartTime())) { // 开始时间 - orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime())); - } - if (Objects.isNull(orderBasicInfo.getChargeEndTime())) { // 结束时间 - orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime())); - } + /** + * 收到交易记录 处理订单 + * + * @param data + */ + private void processOrder(TransactionRecordsData data) { + String transactionCode = data.getTransactionCode(); + // 根据交易流水号查询订单信息 + OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); + if (orderBasicInfo != null) { + // 平台存在订单 + orderBasicInfo.setReason(data.getStopReasonMsg()); + // 如果订单状态为 异常,则改为 待结算 + if (StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), orderBasicInfo.getOrderStatus())) { + orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); + } + // 校验一下开始时间和结束时间,防止充电中桩离线,时间不准确 + if (Objects.isNull(orderBasicInfo.getChargeStartTime())) { // 开始时间 + orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime())); + } + if (Objects.isNull(orderBasicInfo.getChargeEndTime())) { // 结束时间 + orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime())); + } - // 校验结束时间 - if (orderBasicInfo.getChargeEndTime().before(orderBasicInfo.getChargeStartTime())) { - orderBasicInfo.setChargeEndTime(new Date()); - } + // 校验结束时间 + if (orderBasicInfo.getChargeEndTime().before(orderBasicInfo.getChargeStartTime())) { + orderBasicInfo.setChargeEndTime(new Date()); + } - orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); + orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); - // 结算订单操作 - try { - // orderBasicInfoService.settleOrder(data, orderBasicInfo); - // 新逻辑 - String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); - AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); - orderLogic.settleOrder(data, orderBasicInfo); - } catch (Exception e) { - log.error("结算订单发生异常", e); - } + // 结算订单操作 + try { + // orderBasicInfoService.settleOrder(data, orderBasicInfo); + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); + orderLogic.settleOrder(data, orderBasicInfo); + } catch (Exception e) { + log.error("结算订单发生异常", e); + } - // 给车辆绑定优惠券 - try { - BigDecimal totalElectricity = new BigDecimal(data.getTotalElectricity()); - if (totalElectricity.compareTo(BigDecimal.TEN) > 0 ) { - // 充电度数大于10度 - String bindResult = bindCoupon(orderBasicInfo); - log.info("绑定优惠券 订单信息:{}, result:{}", orderBasicInfo, bindResult); - } - }catch (BusinessException e) { - log.error("绑定优惠券 error, code:{}, msg:{}", e.getCode(), e.getMessage()); - } catch (Exception e) { - log.error("绑定优惠券 error,", e); - } + // 给车辆绑定优惠券 + try { + BigDecimal totalElectricity = new BigDecimal(data.getTotalElectricity()); + if (totalElectricity.compareTo(BigDecimal.TEN) > 0) { + // 充电度数大于10度 + String bindResult = bindCoupon(orderBasicInfo); + log.info("绑定优惠券 订单信息:{}, result:{}", orderBasicInfo, bindResult); + } + } catch (BusinessException e) { + log.error("绑定优惠券 error, code:{}, msg:{}", e.getCode(), e.getMessage()); + } catch (Exception e) { + log.error("绑定优惠券 error,", e); + } - // 联联平台 推送订单信息 notification_orderInfo - try { - // 查询该站点是否推送第三方平台 - ThirdPartyStationRelation relation = new ThirdPartyStationRelation(); - relation.setStationId(Long.parseLong(orderBasicInfo.getStationId())); - ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation); - // ThirdPartySettingInfo infoByStationId = thirdPartySettingInfoService.getInfoByStationId(Long.parseLong(stationId)); - if (Objects.isNull(relationInfo)) { - return; - } - String thirdPartyType = relationInfo.getThirdPartyType(); - if (StringUtils.equals(ThirdPlatformTypeEnum.LIAN_LIAN_PLATFORM.getCode(), thirdPartyType)) { - // 联联平台 - // 推送订单信息 - lianLianService.pushOrderInfo(orderBasicInfo.getOrderCode()); - // 推送充电订单信息 - lianLianService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); - } - if (StringUtils.equals(ThirdPlatformTypeEnum.ZHONG_DIAN_LIAN_PLATFORM.getCode(), thirdPartyType)) { - // 中电联 - zdlService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); - } - if (StringUtils.equals(ThirdPlatformTypeEnum.JIANG_SU_PLATFORM.getCode(), thirdPartyType)) { - // 江苏平台 - // 推送订单信息 - nrService.pushOrderInfo(orderBasicInfo.getOrderCode()); - } - if (StringUtils.equals(ThirdPlatformTypeEnum.YONG_CHENG_BO_CHE.getCode(), thirdPartyType)) { - if (StringUtils.equals(orderBasicInfo.getStartMode(), StartModeEnum.THIRD_PARTY_PLATFORM.getValue())) { - // 甬城泊车 - log.info("甬城泊车平台 推送充电订单信息 param:{}", orderBasicInfo.getOrderCode()); - String result = ycbcService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); - log.info("甬城泊车平台 推送充电订单信息 result:{}", result); - } - } - // 调用相关接口 - } catch (Exception e) { - log.error("第三方平台 推送订单信息发生异常", e); - } - } else { - // 平台没有查到订单 - orderBasicInfoService.saveAbnormalOrder(data); - log.warn("充电桩传来的交易记录,根据交易流水号:{}查询不到订单,判定为可疑账单", transactionCode); - } + // 联联平台 推送订单信息 notification_orderInfo + try { + // 查询该站点是否推送第三方平台 + ThirdPartyStationRelation relation = new ThirdPartyStationRelation(); + relation.setStationId(Long.parseLong(orderBasicInfo.getStationId())); + ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(relation); + // ThirdPartySettingInfo infoByStationId = thirdPartySettingInfoService.getInfoByStationId(Long.parseLong(stationId)); + if (Objects.isNull(relationInfo)) { + return; + } + String thirdPartyType = relationInfo.getThirdPartyType(); + if (StringUtils.equals(ThirdPlatformTypeEnum.LIAN_LIAN_PLATFORM.getCode(), thirdPartyType)) { + // 联联平台 + // 推送订单信息 + lianLianService.pushOrderInfo(orderBasicInfo.getOrderCode()); + // 推送充电订单信息 + lianLianService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); + } + if (StringUtils.equals(ThirdPlatformTypeEnum.ZHONG_DIAN_LIAN_PLATFORM.getCode(), thirdPartyType)) { + // 中电联 + zdlService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); + } + if (StringUtils.equals(ThirdPlatformTypeEnum.JIANG_SU_PLATFORM.getCode(), thirdPartyType)) { + // 江苏平台 + // 推送订单信息 + nrService.pushOrderInfo(orderBasicInfo.getOrderCode()); + } + if (StringUtils.equals(ThirdPlatformTypeEnum.YONG_CHENG_BO_CHE.getCode(), thirdPartyType)) { + if (StringUtils.equals(orderBasicInfo.getStartMode(), StartModeEnum.THIRD_PARTY_PLATFORM.getValue())) { + // 甬城泊车 + log.info("甬城泊车平台 推送充电订单信息 param:{}", orderBasicInfo.getOrderCode()); + String result = ycbcService.pushChargeOrderInfo(orderBasicInfo.getOrderCode()); + log.info("甬城泊车平台 推送充电订单信息 result:{}", result); + } + } + // 调用相关接口 + } catch (Exception e) { + log.error("第三方平台 推送订单信息发生异常", e); + } + } else { + // 平台没有查到订单 + orderBasicInfoService.saveAbnormalOrder(data); + log.warn("充电桩传来的交易记录,根据交易流水号:{}查询不到订单,判定为可疑账单", transactionCode); + } - } + } - /** - * 绑定优惠券 - * @param orderBasicInfo - * @return - * @throws UnsupportedEncodingException - */ - private String bindCoupon(OrderBasicInfo orderBasicInfo) throws UnsupportedEncodingException { - if (orderBasicInfo == null) { - return null; - } - // 如果该站点的停车场优惠券信息配置不为空,则需绑定一张优惠券 - String stationId = orderBasicInfo.getStationId(); - PileStationVO stationInfo = pileStationInfoService.getStationInfo(stationId); - if (StringUtils.isBlank(stationInfo.getParkingId())) { - return orderBasicInfo.getOrderCode() + " 该订单无需绑定优惠券"; - } - if (StringUtils.equals(ParkingEnum.LU_TONG_YUN_TING_PLATFORM.getCode(), stationInfo.getParkingId())) { - // 路通云停 - // 查询密钥等配置 - ThirdpartyParkingConfig parkingInfo = thirdPartyParkingConfigService.selectByPrimaryKey(Integer.parseInt(stationInfo.getParkingId())); - if (parkingInfo == null) { - throw new BusinessException(ReturnCodeEnum.CODE_QUERY_PARKING_INFO_IS_NULL); - } - BindCouponDTO dto = BindCouponDTO.builder() - .appId(parkingInfo.getAppId()) - .merchantId(parkingInfo.getParkingMerchantId()) - .couponId(parkingInfo.getCouponId()) - .secretKey(parkingInfo.getSecretKey()) - .plateNumber(orderBasicInfo.getPlateNumber()) - .plateColor(5) // 5-绿牌车 - .build(); - // 绑定优惠券 - return ltytService.bindCoupon(dto); - } else if (StringUtils.equals(ParkingEnum.RUAN_JIE_PLATFORM.getCode(), stationInfo.getParkingId())) { - // 软杰 - UseCouponDTO dto = UseCouponDTO.builder() - .fCouponCode(orderBasicInfo.getOrderCode()) // 优惠券编号(使用订单编号) - .fCouponType("2") // 优惠类型 2-时长 - .fCouponValue("120") // 优惠券面额 单位:分钟 - .fPlateCode(orderBasicInfo.getPlateNumber()) // 车牌号 - .build(); - return rjService.useCoupon(dto); - } - return null; - } + /** + * 绑定优惠券 + * + * @param orderBasicInfo + * @return + * @throws UnsupportedEncodingException + */ + private String bindCoupon(OrderBasicInfo orderBasicInfo) throws UnsupportedEncodingException { + if (orderBasicInfo == null) { + return null; + } + // 如果该站点的停车场优惠券信息配置不为空,则需绑定一张优惠券 + String stationId = orderBasicInfo.getStationId(); + PileStationVO stationInfo = pileStationInfoService.getStationInfo(stationId); + if (StringUtils.isBlank(stationInfo.getParkingId())) { + return orderBasicInfo.getOrderCode() + " 该订单无需绑定优惠券"; + } + if (StringUtils.equals(ParkingEnum.LU_TONG_YUN_TING_PLATFORM.getCode(), stationInfo.getParkingId())) { + // 路通云停 + // 查询密钥等配置 + ThirdpartyParkingConfig parkingInfo = thirdPartyParkingConfigService.selectByPrimaryKey(Integer.parseInt(stationInfo.getParkingId())); + if (parkingInfo == null) { + throw new BusinessException(ReturnCodeEnum.CODE_QUERY_PARKING_INFO_IS_NULL); + } + BindCouponDTO dto = BindCouponDTO.builder() + .appId(parkingInfo.getAppId()) + .merchantId(parkingInfo.getParkingMerchantId()) + .couponId(parkingInfo.getCouponId()) + .secretKey(parkingInfo.getSecretKey()) + .plateNumber(orderBasicInfo.getPlateNumber()) + .plateColor(5) // 5-绿牌车 + .build(); + // 绑定优惠券 + return ltytService.bindCoupon(dto); + } else if (StringUtils.equals(ParkingEnum.RUAN_JIE_PLATFORM.getCode(), stationInfo.getParkingId())) { + // 软杰 + UseCouponDTO dto = UseCouponDTO.builder() + .fCouponCode(orderBasicInfo.getOrderCode()) // 优惠券编号(使用订单编号) + .fCouponType("2") // 优惠类型 2-时长 + .fCouponValue("120") // 优惠券面额 单位:分钟 + .fPlateCode(orderBasicInfo.getPlateNumber()) // 车牌号 + .build(); + return rjService.useCoupon(dto); + } + return null; + } }