From 8c273e5a3940ddc5254578e1c02a3af31cefbce2 Mon Sep 17 00:00:00 2001 From: Guoqs <123@jsowell.com> Date: Thu, 5 Sep 2024 15:51:51 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E7=94=B5=E5=8D=95=E8=BD=A6=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ykc/EBikeChargingStopReasonEnum.java | 91 +++++++++++++++++++ .../SettlementUploadHandler.java | 89 ++++++++++++++++++ .../ebike/deviceupload/EBikeMessageCmd03.java | 36 ++++---- .../programlogic/AbstractProgramLogic.java | 8 ++ .../DelayMerchantProgramLogic.java | 6 ++ .../NotDelayMerchantProgramLogic.java | 6 ++ 6 files changed, 218 insertions(+), 18 deletions(-) create mode 100644 jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java new file mode 100644 index 000000000..168992cc6 --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java @@ -0,0 +1,91 @@ +package com.jsowell.common.enums.ykc; + +import com.jsowell.common.util.BytesUtil; + +/** + * 云快充充电停止原因enum + * + * @author JS-ZZA + * @date 2022/11/4 16:46 + */ +public enum EBikeChargingStopReasonEnum { + + FULL_AUTO_STOP(0x01, "充满自停"), + TIME_AUTO_STOP(0x02, "达到最大充电时间"), + PRESET_TIME_AUTO_STOP(0x03, "达到预设时间"), + PRESET_ELECTRICITY_AUTO_STOP(0x04, "达到预设电量"), + USER_PULL_OUT(0x05, "用户拔出"), + LOAD_TOO_LARGE(0x06, "负载过大"), + SERVER_FORCE_STOP(0x07, "服务器控制停止"), + DYNAMIC_OVERLOAD(0x08, "动态过载"), + POWER_TOO_SMALL(0x09, "功率过小"), + ENVIRONMENT_TEMPERATURE_TOO_HIGH(0x0A, "环境温度过高"), + PORT_TEMPERATURE_TOO_HIGH(0x0B, "端口温度过高"), + OVER_CURRENT(0x0C, "过流"), + USER_PULL_OUT_1(0x0D, "用户拔出-1,可能是插座弹片卡住"), + NO_CONTACT(0x0E, "无功率停止,可能是接触不良或保险丝烧断故障"), + RELAY_BAD(0x0F, "预检-继电器坏或保险丝断"), + WATER_INTRUSION(0x10, "水浸断电"), + FIRE_SETTLEMENT_LOCAL_PORT(0x11, "灭火结算(本端口)"), + FIRE_SETTLEMENT_NON_LOCAL_PORT(0x12, "灭火结算(非本端口)"), + USER_PASSWORD_OPEN_DOOR_SHUTDOWN(0x13, "用户密码开柜断电"), + NOT_CLOSE_DOOR(0x14, "未关好柜门"), + USER_OPERATION_STOP(0x15, "外部操作停止"), + SWIPE_OPERATION_STOP(0x16, "刷卡操作停止"), + SERVER_FORCE_STOP_2(0x17, "服务器强制停止(主要用于充电柜强制开柜门)"), + FIRE_SYSTEM_TRIGGER_STOP(0x18, "消防系统触发停止"), + STORAGE_ERROR(0x19, "存储器错误"), + OVER_VOLTAGE(0x1A, "过压"), + UNDER_VOLTAGE(0x1B, "欠压"), + + ; + + private int code; + private String msg; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + EBikeChargingStopReasonEnum(int code, String msg) { + this.code = code; + this.msg = msg; + } + + /** + * 根据code获取停止原因描述 + * + * @param code 编码 + * @return 停止原因描述 + */ + public static String getMsgByCode(int code) { + for (EBikeChargingStopReasonEnum item : EBikeChargingStopReasonEnum.values()) { + if (item.getCode() == code) { + return item.getMsg(); + } + } + return null; + } + + public static void main(String[] args) { + String stopReason = "6B"; + byte[] stopReasonByteArr = new byte[]{0x6B}; + String s = BytesUtil.bin2HexStr(stopReasonByteArr); + + int i = Integer.parseInt(stopReason, 16); + String stopReasonMsg = EBikeChargingStopReasonEnum.getMsgByCode(i); + System.out.println(stopReasonMsg); + } +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java index 80529755b..856ba9521 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java @@ -3,15 +3,30 @@ package com.jsowell.netty.handler.electricbicycles; import com.alibaba.fastjson2.JSON; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; +import com.jsowell.common.core.redis.RedisCache; +import com.jsowell.common.enums.ykc.OrderStatusEnum; +import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.YKCUtils; +import com.jsowell.common.util.id.IdUtils; import com.jsowell.netty.factory.EBikeOperateFactory; +import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; +import com.jsowell.pile.service.OrderBasicInfoService; +import com.jsowell.pile.service.PersonalChargingRecordService; +import com.jsowell.pile.service.PileBasicInfoService; +import com.jsowell.pile.service.PileMerchantInfoService; +import com.jsowell.pile.service.programlogic.AbstractProgramLogic; +import com.jsowell.pile.service.programlogic.ProgramLogicFactory; +import com.jsowell.thirdparty.common.CommonService; import io.netty.channel.ChannelHandlerContext; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Date; + /** * 结算消费信息上传 */ @@ -21,6 +36,24 @@ public class SettlementUploadHandler extends AbstractEBikeHandler { // private final String type = EBikeCommandEnum.SETTLEMENT_UPLOAD.getCode(); private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.SETTLEMENT_UPLOAD.getBytes()); + @Autowired + private RedisCache redisCache; + + @Autowired + private OrderBasicInfoService orderBasicInfoService; + + @Autowired + private PileMerchantInfoService pileMerchantInfoService; + + @Autowired + private CommonService commonService; + + @Autowired + private PileBasicInfoService pileBasicInfoService; + + @Autowired + private PersonalChargingRecordService personalChargingRecordService; + @Override public void afterPropertiesSet() throws Exception { EBikeOperateFactory.register(type, this); @@ -42,8 +75,64 @@ public class SettlementUploadHandler extends AbstractEBikeHandler { EBikeMessageCmd03.SettlementInfo settlementInfo = message.getSettlementInfo(); log.info("结算消费信息上传:{}", JSON.toJSONString(message)); + String transactionCode = settlementInfo.getOrderNumber(); + // 处理订单加锁/结算电单车订单 + String lockKey = "settle_order_" + transactionCode; + String uuid = IdUtils.fastUUID(); + try { + // redis锁 + Boolean isLock = redisCache.lock(lockKey, uuid, 1500); + if (isLock) { + processOrder(message); + } + } catch (Exception e) { + log.error("处理订单transactionCode:{}, 发生异常", transactionCode, e); + } finally { + if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) { + redisCache.unLock(lockKey); + } + } + // 返回结果 return getResult(dataProtocol, Constants.zeroByteArray); } + /** + * 收到交易记录 处理订单 + */ + private void processOrder(EBikeMessageCmd03 message) { + EBikeMessageCmd03.SettlementInfo settlementInfo = message.getSettlementInfo(); + String transactionCode = settlementInfo.getOrderNumber(); + // 根据交易流水号查询订单信息 + OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); + if (orderBasicInfo != null) { + // 平台存在订单 + String stopReason = settlementInfo.getStopReason(); + // orderBasicInfo.setReason(data.getStopReasonMsg()); + // 如果订单状态为 异常,则改为 待结算 + if (StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), orderBasicInfo.getOrderStatus())) { + orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); + } + + // 校验结束时间 + if (orderBasicInfo.getChargeEndTime().before(orderBasicInfo.getChargeStartTime())) { + orderBasicInfo.setChargeEndTime(new Date()); + } + + orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); + + // 重新查询订单信息 + orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); + + // 结算订单操作 + try { + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); + orderLogic.settleOrderForEBike(message, orderBasicInfo); + } catch (Exception e) { + log.error("结算订单发生异常 orderCode:{}", orderBasicInfo.getOrderCode(), e); + } + } + } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java index 351f0d836..8b7d40a3a 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java @@ -34,28 +34,28 @@ public class EBikeMessageCmd03 extends AbsEBikeMessage { @Data public static class SettlementInfo { - private String chargingDuration; // 充电时长, 单位:"秒" - private String maxPower; // 最大功率, 单位:"0.1W" - private String consumedEnergy; // 耗电量, 单位:"0.01度" - private String portNumber; // 端口号 - private String startMode; // 在线/离线启动/验证码 - private String cardNumberOrVerificationCode; // 卡号/验证码 - private String stopReason; // 停止原因 - private String orderNumber; // 订单编号 - private String secondMaxPower; // 第二最大功率 + private int chargingDuration; // 充电时长, 单位:"秒" + private int maxPower; // 最大功率, 单位:"0.1W" + private int consumedEnergy; // 耗电量, 单位:"0.01度" + private int portNumber; // 端口号 + private int startMode; // 在线/离线启动/验证码 + private int cardNumberOrVerificationCode; // 卡号/验证码 + private int stopReason; // 停止原因 + private int orderNumber; // 订单编号 + private int secondMaxPower; // 第二最大功率 // private String timestamp; // 时间戳 上发指令当时的时间,有时候不准确,该字段属于调试使用,服务器无需关心此字段 // private String placeholderDuration; // 占位时长 充电柜专用,其他设备忽略此字段 表示充满后占用设备的时长,单位为分钟 public SettlementInfo(byte[] dataBytes) { - this.chargingDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) + ""; - this.maxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 4)) + ""; - this.consumedEnergy = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 4, 6)) + ""; - this.portNumber = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[6]}); - this.startMode = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[7]}); - this.cardNumberOrVerificationCode = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 8, 12)); - this.stopReason = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[12]}); - this.orderNumber = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 13, 29)); - this.secondMaxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 29, 31)) + ""; + this.chargingDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)); + this.maxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 4)); + this.consumedEnergy = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 4, 6)); + this.portNumber = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[6]}); + this.startMode = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[7]}); + this.cardNumberOrVerificationCode = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 8, 12)); + this.stopReason = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[12]}); + this.orderNumber = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 13, 29)); + this.secondMaxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 29, 31)); // this.timestamp = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 31, 35)) + ""; // this.placeholderDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 35, 37)) + ""; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java index 4d211b0b9..ac6305ba7 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java @@ -14,6 +14,7 @@ import com.jsowell.common.enums.ykc.*; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.service.TransactionService; @@ -141,6 +142,13 @@ public abstract class AbstractProgramLogic implements InitializingBean { */ public abstract void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo); + /** + * 电单车结算逻辑 + * @param message + * @param orderBasicInfo + */ + public abstract void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo); + /** * 第三方平台结算订单(目前给华为用) * diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java index 8474cf333..98beccce2 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java @@ -27,6 +27,7 @@ import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.customer.MemberVO; @@ -470,6 +471,11 @@ public class DelayMerchantProgramLogic extends AbstractProgramLogic { orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode(), JSON.toJSONString(dto)); } + @Override + public void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo) { + + } + /** * 第三方平台结算订单(目前给华为用) * @param data diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java index 6b822ad65..6a5f4e0bb 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java @@ -27,6 +27,7 @@ import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.customer.MemberVO; @@ -417,6 +418,11 @@ public class NotDelayMerchantProgramLogic extends AbstractProgramLogic { logger.info("结算订单end:{} OrderTransactionDTO:{}", orderBasicInfo.getOrderCode(), JSON.toJSONString(dto)); } + @Override + public void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo) { + + } + /** * 第三方平台结算订单(目前给华为用) * @param data