From e9573b3ef2689bfb59a61264b600d4262de8f2d4 Mon Sep 17 00:00:00 2001 From: Lemon Date: Mon, 16 Jun 2025 15:59:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=200xA1=E5=B9=B6=E5=85=85?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/ykc/YKCFrameTypeCode.java | 2 + .../common/enums/ykc/OrderTypeEnum.java | 37 +++++ .../common/enums/ykc/ReturnCodeEnum.java | 2 + .../PileApplyMergeChargeHandler.java | 145 ++++++++++++++++++ .../jsowell/pile/domain/OrderBasicInfo.java | 15 ++ .../jsowell/pile/dto/GenerateOrderDTO.java | 20 +++ .../pile/dto/VerifyMergeChargeOrderDTO.java | 47 ++++++ .../pile/service/OrderBasicInfoService.java | 7 + .../impl/OrderBasicInfoServiceImpl.java | 63 ++++++++ .../mapper/pile/MemberWalletInfoMapper.xml | 5 +- .../mapper/pile/OrderBasicInfoMapper.xml | 114 +++++++++++++- 11 files changed, 452 insertions(+), 5 deletions(-) create mode 100644 jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderTypeEnum.java create mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/PileApplyMergeChargeHandler.java create mode 100644 jsowell-pile/src/main/java/com/jsowell/pile/dto/VerifyMergeChargeOrderDTO.java diff --git a/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/YKCFrameTypeCode.java b/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/YKCFrameTypeCode.java index 0c4d2dd29..d5e5b8a2d 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/YKCFrameTypeCode.java +++ b/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/YKCFrameTypeCode.java @@ -104,6 +104,8 @@ public enum YKCFrameTypeCode { UPLOAD_PILE_FAULT_RECORD_CODE(0xDB, "上传桩端故障记录"), + PILE_APPLY_MERGE_CHARGE_CODE(0xA1, "充电桩主动申请并充充电"), + // 自定义FrameType PILE_LOG_OUT(9999, "充电桩退出"), diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderTypeEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderTypeEnum.java new file mode 100644 index 000000000..aeecc47be --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/OrderTypeEnum.java @@ -0,0 +1,37 @@ +package com.jsowell.common.enums.ykc; + +/** + * 订单类型enum + * + * @author Lemon + * @Date 2025/6/16 13:59:20 + */ +public enum OrderTypeEnum { + NORMAL_ORDER("1", "普通订单"), + MERGE_CHARGE_ORDER("2", "并充订单"), + ; + private String value; + + private String lable; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getLable() { + return lable; + } + + public void setLable(String lable) { + this.lable = lable; + } + + OrderTypeEnum(String value, String lable) { + this.value = value; + this.lable = lable; + } +} diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/ReturnCodeEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/ReturnCodeEnum.java index e09c83d96..e50545b62 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/ReturnCodeEnum.java +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/ReturnCodeEnum.java @@ -226,6 +226,8 @@ public enum ReturnCodeEnum { CODE_SELECT_INFO_IS_NULL("00700001", "查询信息为空!"), CODE_THIS_VIN_HAS_BEEN_BINDING("00700002", "该vin已被绑定,请检查!"), + + CODE_THIS_VIN_INFO_IS_NULL("007000003", "未查到该vin信息!"), ; private String value; diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/PileApplyMergeChargeHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/PileApplyMergeChargeHandler.java new file mode 100644 index 000000000..fe172ea31 --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/PileApplyMergeChargeHandler.java @@ -0,0 +1,145 @@ +package com.jsowell.netty.handler.yunkuaichong; + +import com.google.common.primitives.Bytes; +import com.jsowell.common.core.domain.ykc.YKCDataProtocol; +import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.YKCUtils; +import com.jsowell.netty.factory.YKCOperateFactory; +import com.jsowell.pile.dto.VerifyMergeChargeOrderDTO; +import com.jsowell.pile.service.OrderBasicInfoService; +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.Map; + +/** + * 0xA1 充电桩主动申请并充充电 + * + * @author Lemon + * @Date 2025/6/12 11:37:36 + */ +@Slf4j +@Component +public class PileApplyMergeChargeHandler extends AbstractYkcHandler{ + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.PILE_APPLY_MERGE_CHARGE_CODE.getBytes()); + + @Autowired + private OrderBasicInfoService orderBasicInfoService; + + + @Override + public void afterPropertiesSet() throws Exception { + YKCOperateFactory.register(type, this); + } + + @Override + public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { + + // 获取消息体 + byte[] msgBody = ykcDataProtocol.getMsgBody(); + + int startIndex = 0; + int length = 7; + + // 桩编号 + byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.binary(pileSnByteArr, 16); + + // 保存时间 + saveLastTimeAndCheckChannel(pileSn, channel); + + // 枪号 + startIndex += length; + length = 1; + byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(connectorNumByteArr); + + // 启动方式 + // 0x01 表示通过刷卡启动充电 + // 0x02 表求通过帐号启动充电 (暂不支持) + // 0x03 表示vin码启动充电 + startIndex += length; + byte[] startModeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String startMode = BytesUtil.bcd2Str(startModeByteArr); + + // 是否需要密码 0x00 不需要 0x01 需要 + startIndex += length; + byte[] needPasswordFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String needPasswordFlag = BytesUtil.bcd2Str(needPasswordFlagByteArr); + + // 物理卡号 不足 8 位补 0 + startIndex += length; + length = 8; + byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String physicsCard = BytesUtil.binary(cardNumByteArr, 16); + + // 输入密码 对用户输入的密码进行16 位MD5 加密,采用小写上传 + startIndex += length; + length = 16; + byte[] inputPasswordByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String inputPasswordHexStr = BytesUtil.bin2HexStr(inputPasswordByteArr); + + // VIN码 + startIndex += length; + length = 17; + byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String vinCode = BytesUtil.ascii2StrLittle(vinCodeByteArr); + + // 主辅枪标记 + // 0x00 主枪 + // 0x01 辅枪 + startIndex += length; + length = 1; + byte[] connectorMarkByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorMark = BytesUtil.bcd2Str(connectorMarkByteArr); + + // 并充序号 + // 由桩生成:年月日时分秒,多个枪并充时上送并充序号一致,表示为同一次并充操作 + startIndex += length; + length = 6; + byte[] mergeChargeNumberByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String mergeChargeNumber = BytesUtil.bcd2Str(mergeChargeNumberByteArr); + + // 鉴权方法(返回交易流水号、账户余额、鉴权成功标识) + String pileConnectorCode = pileSn + connectorCode; + VerifyMergeChargeOrderDTO dto = VerifyMergeChargeOrderDTO.builder() + .pileSn(pileSn) + .connectorCode(connectorCode) + .pileConnectorCode(pileConnectorCode) + .startMode(startMode) + .physicsCard(physicsCard) + .vinCode(vinCode) + .connectorMark(connectorMark) + .mergeChargeNumber(mergeChargeNumber) + .build(); + + try { + Map map = orderBasicInfoService.verifyMergeChargeOrder(dto); + + } catch (Exception e) { + log.error("桩号:{}, 并充订单鉴权失败, ", pileSn, e); + } + + String transactionCode = ""; + String accountAmount = ""; + String verifyFlag = ""; + + // 应答 + // 交易流水号 + // 桩编号 + // 枪号 + // 逻辑卡号 + // 账户余额 + // 鉴权成功标志 + // 失败原因 + // 并充序号 + byte[] msgBodyByteArr = Bytes.concat(BytesUtil.str2Bcd(transactionCode), pileSnByteArr, connectorNumByteArr, cardNumByteArr, + BytesUtil.str2Bcd(accountAmount), BytesUtil.str2Bcd(verifyFlag), mergeChargeNumberByteArr); + + + return getResult(ykcDataProtocol, msgBodyByteArr); + } +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java index 6ab778acf..654e1ce0f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java @@ -35,6 +35,21 @@ public class OrderBasicInfo { */ private String orderStatus; + /** + * 订单类型(1-普通订单;2-并充订单) + */ + private String orderType; + + /** + * 并充订单序号 + */ + private String mergeChargeNumber; + + /** + * 主枪枪编号 + */ + private String mainConnectorCode; + /** * 会员id */ diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java index 21c50f5fa..83041f79e 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java @@ -88,6 +88,26 @@ public class GenerateOrderDTO extends BasicPileDTO{ */ private MemberPlateNumberRelation MemberPlateNumberRelation; + /** + * 鉴权成功标识 + */ + private boolean verifyFlag; + + /** + * 订单类型(1-普通订单;2-并充订单) + */ + private String orderType; + + /** + * 并充序号(并充启动时有值) + */ + private String mergeChargeNumber; + + /** + * 主枪枪编码(并充启动时有值) + */ + private String mainConnectorCode; + /** * 车牌号码 */ diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/VerifyMergeChargeOrderDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/VerifyMergeChargeOrderDTO.java new file mode 100644 index 000000000..194f31edf --- /dev/null +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/VerifyMergeChargeOrderDTO.java @@ -0,0 +1,47 @@ +package com.jsowell.pile.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 鉴权并充订单DTO + * + * @author Lemon + * @Date 2025/6/12 14:32:38 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VerifyMergeChargeOrderDTO { + // 桩编号 + private String pileSn; + + // 枪号 + private String connectorCode; + + // 枪口编号 + private String pileConnectorCode; + + // 启动方式 + // 0x01 表示通过刷卡启动充电 + // 0x03 表示vin码启动充电 + private String startMode; + + // 物理卡号 + private String physicsCard; + + // vin + private String vinCode; + + // 主辅枪标记 + // 0x00 主枪 + // 0x01 辅枪 + private String connectorMark; + + // 并充序号 + // 由桩生成:年月日时分秒,多个枪并充时上送并充序号一致,表示为同一次并充操作 + private String mergeChargeNumber; +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java index 74dad65f5..ae7f93b07 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java @@ -566,4 +566,11 @@ public interface OrderBasicInfoService{ * @param dto */ void setOrderSupplementAmount(OrderSupplementAmountDTO dto); + + /** + * 鉴权并充订单 + * @param dto + * @return + */ + Map verifyMergeChargeOrder(VerifyMergeChargeOrderDTO dto) throws Exception; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 28d210d10..8164a74c8 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -4542,6 +4542,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { .orderCode(orderCode) .transactionCode(transactionCode) .orderStatus(OrderStatusEnum.NOT_START.getValue()) + .orderType(OrderTypeEnum.NORMAL_ORDER.getValue()) // 订单类型(1-普通订单;2-并充订单) .memberId(dto.getMemberId()) .stationId(stationId) .merchantId(merchantId) @@ -4558,6 +4559,18 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { .settleAmount(BigDecimal.ZERO) .startType(dto.getStartType()) .build(); + if (StringUtils.equals(OrderTypeEnum.MERGE_CHARGE_ORDER.getValue(), dto.getOrderType())) { + // 并充订单 + orderBasicInfo.setOrderType(dto.getOrderType()); + if (StringUtils.isNotBlank(dto.getMergeChargeNumber())) { + // 并充订单序号 + orderBasicInfo.setMergeChargeNumber(dto.getMergeChargeNumber()); + } + if (StringUtils.isNotBlank(dto.getMainConnectorCode())) { + // 主枪枪编号 + orderBasicInfo.setMainConnectorCode(dto.getMainConnectorCode()); + } + } if (StringUtils.equals(dto.getStartMode(), StartModeEnum.AUTH_CARD.getValue())) { // 鉴权卡启动 orderBasicInfo.setLogicCard(dto.getPileAuthCardInfo().getLogicCard()); @@ -5122,5 +5135,55 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { logger.info("设置订单待补缴金额, orderCode:{}, supplementAmount:{}, 备注:{}", dto.getOrderCode(), dto.getSupplementAmount(), dto.getRemark()); } + /** + * 鉴权并充订单 + * @param dto + * @return + */ + @Override + public Map verifyMergeChargeOrder(VerifyMergeChargeOrderDTO dto) throws Exception { + Map map = new LinkedHashMap<>(); + + GenerateOrderDTO generateOrderDTO = new GenerateOrderDTO(); + generateOrderDTO.setPileSn(dto.getPileSn()); + generateOrderDTO.setConnectorCode(dto.getConnectorCode()); + generateOrderDTO.setMergeChargeNumber(dto.getMergeChargeNumber()); + + // 判断是否为主枪 + if (StringUtils.equals(Constants.DOUBLE_ZERO, dto.getConnectorMark())) { + // 主枪 + generateOrderDTO.setMainConnectorCode(dto.getPileConnectorCode()); + } + // 区分是卡还是vin充电 + String startMode = dto.getStartMode(); + if (StringUtils.equals(Constants.ZERO_ONE, startMode)) { + // 刷卡鉴权 + // 根据卡号查询用户信息 + String physicsCard = dto.getPhysicsCard(); + PileAuthCard pileAuthCardInfo = pileAuthCardService.selectCardInfoByLogicCard(physicsCard); + if (pileAuthCardInfo == null) { + // 未查到此卡信息 + throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO); + } + generateOrderDTO.setPileAuthCardInfo(pileAuthCardInfo); + generateOrderDTO.setStartMode(StartModeEnum.AUTH_CARD.getValue()); + generateOrderDTO.setMemberId(pileAuthCardInfo.getMemberId()); + }else if (StringUtils.equals(Constants.ZERO_THREE, startMode)) { + // vin鉴权 + // 根据vin查询绑定用户信息 + String vinCode = dto.getVinCode(); + MemberPlateNumberRelation memberInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode); + if (memberInfo == null) { + throw new BusinessException(ReturnCodeEnum.CODE_THIS_VIN_INFO_IS_NULL); + } + generateOrderDTO.setMemberPlateNumberRelation(memberInfo); + generateOrderDTO.setStartMode(StartModeEnum.VIN_CODE.getValue()); + generateOrderDTO.setMemberId(memberInfo.getMemberId()); + } + // 鉴权通过,生成订单启动充电 + map = generateOrderByCard(generateOrderDTO); + + return map; + } } diff --git a/jsowell-pile/src/main/resources/mapper/pile/MemberWalletInfoMapper.xml b/jsowell-pile/src/main/resources/mapper/pile/MemberWalletInfoMapper.xml index 374a621dd..b0944611e 100644 --- a/jsowell-pile/src/main/resources/mapper/pile/MemberWalletInfoMapper.xml +++ b/jsowell-pile/src/main/resources/mapper/pile/MemberWalletInfoMapper.xml @@ -182,7 +182,10 @@ from member_wallet_info where del_flag = '0' and member_id = #{memberId,jdbcType=INTEGER} - and merchant_id = #{merchantId,jdbcType=VARCHAR} + + and merchant_id = #{merchantId,jdbcType=VARCHAR} + +