2023-03-04 16:29:55 +08:00
|
|
|
package com.jsowell.netty.handler;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
|
|
import com.google.common.primitives.Bytes;
|
|
|
|
|
import com.jsowell.common.constant.Constants;
|
2023-10-12 13:34:32 +08:00
|
|
|
import com.jsowell.common.core.domain.ykc.ConfirmStartChargingData;
|
2023-03-04 16:29:55 +08:00
|
|
|
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
|
|
|
|
|
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
|
2023-04-06 10:29:47 +08:00
|
|
|
import com.jsowell.common.enums.ykc.CardStatusEnum;
|
2023-03-18 10:59:02 +08:00
|
|
|
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
|
2023-06-07 15:14:03 +08:00
|
|
|
import com.jsowell.common.enums.ykc.StartModeEnum;
|
2023-03-18 10:59:02 +08:00
|
|
|
import com.jsowell.common.exception.BusinessException;
|
2023-03-04 16:29:55 +08:00
|
|
|
import com.jsowell.common.util.BytesUtil;
|
2023-03-18 10:59:02 +08:00
|
|
|
import com.jsowell.common.util.StringUtils;
|
2023-03-04 16:29:55 +08:00
|
|
|
import com.jsowell.common.util.YKCUtils;
|
|
|
|
|
import com.jsowell.netty.factory.YKCOperateFactory;
|
2023-06-09 18:44:06 +08:00
|
|
|
import com.jsowell.pile.domain.MemberPlateNumberRelation;
|
2023-03-18 10:59:02 +08:00
|
|
|
import com.jsowell.pile.domain.PileAuthCard;
|
2023-03-30 15:35:14 +08:00
|
|
|
import com.jsowell.pile.dto.GenerateOrderDTO;
|
2024-01-06 15:20:28 +08:00
|
|
|
import com.jsowell.pile.service.MemberPlateNumberRelationService;
|
|
|
|
|
import com.jsowell.pile.service.PileMsgRecordService;
|
2024-01-06 15:13:50 +08:00
|
|
|
import com.jsowell.pile.service.OrderBasicInfoService;
|
2023-12-01 13:29:35 +08:00
|
|
|
import com.jsowell.pile.service.PileAuthCardService;
|
2023-03-04 16:29:55 +08:00
|
|
|
import io.netty.channel.Channel;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
2023-03-30 15:35:14 +08:00
|
|
|
import java.util.Map;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 充电桩主动申请启动充电 0x31
|
|
|
|
|
*
|
|
|
|
|
* 启动充电鉴权结果
|
|
|
|
|
* @author JS-ZZA
|
|
|
|
|
* @date 2022/9/19 14:29
|
|
|
|
|
*/
|
|
|
|
|
@Slf4j
|
|
|
|
|
@Component
|
|
|
|
|
public class ConfirmStartChargingRequestHandler extends AbstractHandler{
|
|
|
|
|
private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REQUEST_START_CHARGING_CODE.getBytes());
|
|
|
|
|
|
2023-03-18 10:59:02 +08:00
|
|
|
@Autowired
|
2023-12-01 13:29:35 +08:00
|
|
|
private PileAuthCardService pileAuthCardService;
|
2023-03-18 10:59:02 +08:00
|
|
|
|
2023-03-30 15:35:14 +08:00
|
|
|
@Autowired
|
2024-01-06 15:13:50 +08:00
|
|
|
private OrderBasicInfoService orderBasicInfoService;
|
2023-03-30 15:35:14 +08:00
|
|
|
|
2023-06-09 18:44:06 +08:00
|
|
|
@Autowired
|
2024-01-06 15:20:28 +08:00
|
|
|
private MemberPlateNumberRelationService memberPlateNumberRelationService;
|
2023-06-09 18:44:06 +08:00
|
|
|
|
2023-10-12 13:34:32 +08:00
|
|
|
@Autowired
|
2024-01-06 15:20:28 +08:00
|
|
|
private PileMsgRecordService pileMsgRecordService;
|
2023-10-12 13:34:32 +08:00
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
@Override
|
|
|
|
|
public void afterPropertiesSet() throws Exception {
|
|
|
|
|
YKCOperateFactory.register(type, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) {
|
2023-11-14 11:29:55 +08:00
|
|
|
// log.info("[===充电桩主动申请启动充电===] param:{}, channel:{}", JSONObject.toJSONString(ykcDataProtocol), channel.toString());
|
2023-03-04 16:29:55 +08:00
|
|
|
// 获取消息体
|
|
|
|
|
byte[] msgBody = ykcDataProtocol.getMsgBody();
|
|
|
|
|
|
|
|
|
|
int startIndex = 0;
|
2023-03-18 10:59:02 +08:00
|
|
|
int length = 7;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 桩编码
|
|
|
|
|
byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-03-18 10:59:02 +08:00
|
|
|
String pileSn = BytesUtil.binary(pileSnByteArr, 16);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 保存时间
|
2023-12-07 16:19:47 +08:00
|
|
|
saveLastTimeAndCheckChannel(pileSn, channel);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 枪号
|
|
|
|
|
startIndex += length;
|
|
|
|
|
length = 1;
|
2023-03-18 10:59:02 +08:00
|
|
|
byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
|
|
|
|
String connectorCode = BytesUtil.bcd2Str(connectorNumByteArr);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 启动方式
|
|
|
|
|
// 0x01 表示通过刷卡启动充电
|
|
|
|
|
// 0x02 表求通过帐号启动充电 (暂不支持)
|
|
|
|
|
// 0x03 表示vin码启动充电
|
|
|
|
|
startIndex += length;
|
|
|
|
|
byte[] startModeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-03-18 10:59:02 +08:00
|
|
|
String startMode = BytesUtil.bcd2Str(startModeByteArr);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 是否需要密码 0x00 不需要 0x01 需要
|
|
|
|
|
startIndex += length;
|
|
|
|
|
byte[] needPasswordFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-03-18 10:59:02 +08:00
|
|
|
String needPasswordFlag = BytesUtil.bcd2Str(needPasswordFlagByteArr);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 物理卡号 不足 8 位补 0
|
|
|
|
|
startIndex += length;
|
|
|
|
|
length = 8;
|
|
|
|
|
byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-03-18 10:59:02 +08:00
|
|
|
String physicsCard = BytesUtil.binary(cardNumByteArr, 16);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 输入密码 对用户输入的密码进行16 位MD5 加密,采用小写上传
|
|
|
|
|
startIndex += length;
|
|
|
|
|
length = 16;
|
|
|
|
|
byte[] inputPasswordByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-10-12 13:34:32 +08:00
|
|
|
String inputPasswordHexStr = BytesUtil.bin2HexStr(inputPasswordByteArr);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// VIN码
|
|
|
|
|
startIndex += length;
|
|
|
|
|
length = 17;
|
|
|
|
|
byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
2023-06-07 15:14:03 +08:00
|
|
|
String vinCode = BytesUtil.ascii2Str(vinCodeByteArr);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
2023-10-12 13:34:32 +08:00
|
|
|
ConfirmStartChargingData confirmStartChargingData = ConfirmStartChargingData.builder()
|
|
|
|
|
.pileSn(pileSn)
|
|
|
|
|
.connectorCode(connectorCode)
|
|
|
|
|
.startMode(startMode)
|
|
|
|
|
.needPasswordFlag(needPasswordFlag)
|
|
|
|
|
.inputPasswordByteArr(inputPasswordHexStr)
|
|
|
|
|
.physicsCard(physicsCard)
|
|
|
|
|
.vinCode(vinCode)
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
2023-06-06 08:57:30 +08:00
|
|
|
/**
|
|
|
|
|
* 刷卡启动充电
|
|
|
|
|
*/
|
2023-03-18 10:59:02 +08:00
|
|
|
String logicCard = "";
|
2023-06-07 15:14:03 +08:00
|
|
|
byte[] authenticationFlagByteArr = Constants.zeroByteArray; // 鉴权成功标识
|
|
|
|
|
byte[] accountBalanceByteArr = Constants.zeroByteArray; // 账户余额
|
2023-03-30 10:30:43 +08:00
|
|
|
String transactionCode = "";
|
2023-03-18 10:59:02 +08:00
|
|
|
try {
|
|
|
|
|
if (StringUtils.equals("01", startMode)) {
|
2023-11-02 15:50:29 +08:00
|
|
|
log.info("桩号:{}, 申请充电物理卡号:{}", pileSn, physicsCard);
|
2023-03-30 15:35:14 +08:00
|
|
|
// 查询卡信息 根据传过来的物理卡号查询数据库中此卡信息
|
2023-03-30 10:54:02 +08:00
|
|
|
PileAuthCard pileAuthCardInfo = pileAuthCardService.selectCardInfoByLogicCard(physicsCard);
|
2023-03-18 10:59:02 +08:00
|
|
|
if (pileAuthCardInfo == null) {
|
|
|
|
|
// 未查到此卡信息
|
|
|
|
|
throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO);
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(pileAuthCardInfo.getMemberId())) {
|
|
|
|
|
// 卡未绑定用户
|
|
|
|
|
throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_NOT_BIND_USER);
|
|
|
|
|
}
|
2023-03-30 15:35:14 +08:00
|
|
|
// 判断卡状态
|
2023-04-06 10:29:47 +08:00
|
|
|
if (!StringUtils.equals(CardStatusEnum.NORMAL.getCode(), pileAuthCardInfo.getStatus())) {
|
2023-03-30 10:30:43 +08:00
|
|
|
return null;
|
2023-03-18 16:55:15 +08:00
|
|
|
}
|
2023-03-30 15:35:14 +08:00
|
|
|
|
|
|
|
|
// 刷卡生成订单 刷卡启动充电
|
|
|
|
|
GenerateOrderDTO dto = new GenerateOrderDTO();
|
|
|
|
|
dto.setPileAuthCardInfo(pileAuthCardInfo);
|
|
|
|
|
dto.setPileSn(pileSn);
|
|
|
|
|
dto.setConnectorCode(connectorCode);
|
2023-06-07 15:14:03 +08:00
|
|
|
dto.setStartMode(StartModeEnum.AUTH_CARD.getValue());
|
2023-07-08 11:03:43 +08:00
|
|
|
dto.setMemberId(pileAuthCardInfo.getMemberId());
|
2023-03-30 15:35:14 +08:00
|
|
|
Map<String, Object> map = orderBasicInfoService.generateOrderByCard(dto);
|
|
|
|
|
if (map != null) {
|
|
|
|
|
transactionCode = (String) map.get("transactionCode");
|
|
|
|
|
accountBalanceByteArr = YKCUtils.getPriceByte(String.valueOf(map.get("accountBalance")), 2);
|
|
|
|
|
// 鉴权成功标识 0x00 失败 0x01 成功
|
|
|
|
|
authenticationFlagByteArr = Constants.oneByteArray;
|
2023-06-13 09:32:31 +08:00
|
|
|
}else {
|
|
|
|
|
throw new BusinessException("", "生成刷卡订单失败");
|
2023-03-30 15:35:14 +08:00
|
|
|
}
|
2023-03-18 10:59:02 +08:00
|
|
|
}
|
|
|
|
|
} catch (BusinessException e){
|
2023-07-07 15:55:44 +08:00
|
|
|
transactionCode = Constants.ILLEGAL_TRANSACTION_CODE;
|
2023-06-13 09:32:31 +08:00
|
|
|
accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
|
|
|
|
|
authenticationFlagByteArr = Constants.zeroByteArray;
|
2023-03-18 10:59:02 +08:00
|
|
|
log.error("刷卡启动充电鉴权 error:{}, {}", e.getCode(), e.getMessage());
|
2023-10-10 09:32:30 +08:00
|
|
|
} catch (Exception e){
|
2023-07-07 15:55:44 +08:00
|
|
|
transactionCode = Constants.ILLEGAL_TRANSACTION_CODE;
|
2023-06-13 09:32:31 +08:00
|
|
|
accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
|
|
|
|
|
authenticationFlagByteArr = Constants.zeroByteArray;
|
2023-03-18 10:59:02 +08:00
|
|
|
log.error("刷卡启动充电鉴权 error", e);
|
|
|
|
|
}
|
2023-03-04 16:29:55 +08:00
|
|
|
|
2023-06-12 15:34:24 +08:00
|
|
|
try {
|
|
|
|
|
/**
|
2023-06-12 17:38:16 +08:00
|
|
|
* VIN码启动充电
|
2023-06-12 15:34:24 +08:00
|
|
|
*/
|
|
|
|
|
if (StringUtils.equals("03", startMode)) {
|
2023-11-02 15:43:32 +08:00
|
|
|
log.info("桩号:{}, 申请充电VIN码:{}", pileSn, vinCode);
|
2023-06-12 15:34:24 +08:00
|
|
|
// 通过vin码查询数据库绑定用户信息
|
|
|
|
|
MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
|
|
|
|
|
if (plateInfo == null) {
|
2023-11-01 21:20:57 +08:00
|
|
|
throw new BusinessException("", vinCode + "未查到绑定用户信息");
|
2023-06-12 15:34:24 +08:00
|
|
|
}
|
|
|
|
|
if (!StringUtils.equals("1", plateInfo.getVinStatus())) {
|
|
|
|
|
// 1- 正常使用
|
2023-11-01 21:20:57 +08:00
|
|
|
throw new BusinessException("", vinCode + "vin状态不正确");
|
2023-06-12 15:34:24 +08:00
|
|
|
}
|
|
|
|
|
// vin码生成订单 vin启动充电
|
|
|
|
|
GenerateOrderDTO dto = new GenerateOrderDTO();
|
|
|
|
|
dto.setMemberPlateNumberRelation(plateInfo);
|
|
|
|
|
dto.setPileSn(pileSn);
|
|
|
|
|
dto.setConnectorCode(connectorCode);
|
|
|
|
|
dto.setStartMode(StartModeEnum.VIN_CODE.getValue());
|
2023-07-08 11:03:43 +08:00
|
|
|
dto.setMemberId(plateInfo.getMemberId());
|
2023-06-12 15:34:24 +08:00
|
|
|
Map<String, Object> map = orderBasicInfoService.generateOrderByCard(dto);
|
|
|
|
|
if (map != null) {
|
|
|
|
|
transactionCode = (String) map.get("transactionCode");
|
|
|
|
|
accountBalanceByteArr = YKCUtils.getPriceByte(String.valueOf(map.get("accountBalance")), 2);
|
|
|
|
|
// 鉴权成功标识 0x00 失败 0x01 成功
|
|
|
|
|
authenticationFlagByteArr = Constants.oneByteArray;
|
2023-06-13 09:32:31 +08:00
|
|
|
}else {
|
|
|
|
|
throw new BusinessException("", "生成vin订单失败");
|
2023-06-12 15:34:24 +08:00
|
|
|
}
|
2023-06-07 15:14:03 +08:00
|
|
|
}
|
2023-06-12 15:34:24 +08:00
|
|
|
}catch (BusinessException e){
|
2023-07-07 15:55:44 +08:00
|
|
|
transactionCode = Constants.ILLEGAL_TRANSACTION_CODE;
|
2023-06-13 09:32:31 +08:00
|
|
|
accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
|
|
|
|
|
authenticationFlagByteArr = Constants.zeroByteArray;
|
|
|
|
|
|
2023-06-12 15:34:24 +08:00
|
|
|
log.error("VIN码启动充电鉴权 error:{}, {}", e.getCode(), e.getMessage());
|
|
|
|
|
}catch (Exception e) {
|
2023-07-07 15:55:44 +08:00
|
|
|
transactionCode = Constants.ILLEGAL_TRANSACTION_CODE;
|
2023-06-13 09:32:31 +08:00
|
|
|
accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
|
|
|
|
|
authenticationFlagByteArr = Constants.zeroByteArray;
|
|
|
|
|
|
2023-06-12 15:34:24 +08:00
|
|
|
log.error("VIN码启动充电鉴权 error", e);
|
2023-06-07 15:14:03 +08:00
|
|
|
}
|
2023-06-06 08:57:30 +08:00
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
// 应答
|
|
|
|
|
// 交易流水号
|
2023-03-23 15:08:53 +08:00
|
|
|
// String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode);
|
2023-03-18 10:59:02 +08:00
|
|
|
byte[] serialNumByteArr = BytesUtil.str2Bcd(transactionCode);
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 逻辑卡号
|
2023-03-18 10:59:02 +08:00
|
|
|
// String logicCardNum = "00000000";
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 账户余额 保留两位小数
|
2023-03-18 10:59:02 +08:00
|
|
|
// MemberVO memberVO = memberBasicInfoService.selectInfoByPhysicsCard(physicsCard);
|
|
|
|
|
// BigDecimal principalBalance = memberVO.getPrincipalBalance(); // 本金金额
|
|
|
|
|
// double accountBalance = principalBalance.add(memberVO.getGiftBalance()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
|
|
|
|
// byte[] accountBalanceByteArr = BytesUtil.str2Bcd(String.valueOf(accountBalance));
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
// 鉴权成功标识 0x00 失败 0x01 成功
|
2023-03-18 10:59:02 +08:00
|
|
|
// byte[] authenticationFlagByteArr = Constants.oneByteArray;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 失败原因
|
|
|
|
|
* 0x01 账户不存在
|
|
|
|
|
* 0x02 账户冻结
|
|
|
|
|
* 0x03 账户余额不足
|
|
|
|
|
* 0x04 该卡存在未结账记录
|
|
|
|
|
* 0x05 桩停用
|
|
|
|
|
* 0x06 该账户不能在此桩上充电
|
|
|
|
|
* 0x07 密码错误
|
|
|
|
|
* 0x08 电站电容不足
|
|
|
|
|
* 0x09 系统中vin 码不存在
|
|
|
|
|
* 0x0A 该桩存在未结账记录
|
|
|
|
|
* 0x0B 该桩不支持刷卡
|
|
|
|
|
*/
|
|
|
|
|
byte[] defeatReasonByteArr = Constants.zeroByteArray;
|
|
|
|
|
|
2023-06-12 17:38:16 +08:00
|
|
|
// 不足位数的值补零
|
2023-06-13 09:32:31 +08:00
|
|
|
// cardNumByteArr = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16);
|
|
|
|
|
// serialNumByteArr = BytesUtil.checkLengthAndBehindAppendZero(serialNumByteArr, 32);
|
|
|
|
|
// pileSnByteArr = BytesUtil.checkLengthAndBehindAppendZero(pileSnByteArr, 14);
|
|
|
|
|
// accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
|
2023-06-12 17:38:16 +08:00
|
|
|
|
2023-10-12 13:34:32 +08:00
|
|
|
// 保存报文
|
|
|
|
|
String jsonMsg = JSONObject.toJSONString(confirmStartChargingData);
|
|
|
|
|
pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString());
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
// 拼装消息体
|
2023-03-18 10:59:02 +08:00
|
|
|
byte[] msgBodyByteArr = Bytes.concat(serialNumByteArr, pileSnByteArr, connectorNumByteArr, cardNumByteArr, accountBalanceByteArr,
|
2023-03-04 16:29:55 +08:00
|
|
|
authenticationFlagByteArr, defeatReasonByteArr);
|
|
|
|
|
|
|
|
|
|
return getResult(ykcDataProtocol, msgBodyByteArr);
|
|
|
|
|
}
|
|
|
|
|
}
|