修正物理卡号为BIN码
This commit is contained in:
三丙
2025-10-16 20:15:46 +08:00
parent 8da6d2eaf5
commit 32334b6ba7
14 changed files with 79 additions and 63 deletions

View File

@@ -114,9 +114,41 @@ public class AbstractYunKuaiChongCmdExe {
}
/**
* 编码卡号为BCD格式
* 云快充协议卡号为8字节16位BCD码需要做长度校验和补0操作
* 编码逻辑卡号为BCD格式
* 云快充协议逻辑卡号为8字节16位BCD码需要做长度校验和补0操作
*/
protected static byte[] encodeLogicalCardNo(String cardNo) {
if (StringUtils.length(cardNo) > 16) {
throw new IllegalArgumentException("云快充可接受最大逻辑卡号为16位");
}
String cardNoStr = StringUtils.leftPad(cardNo, 16, '0');
return BCDUtil.toBytes(cardNoStr);
}
/**
* 编码物理卡号为8字节long值
* 根据云快充协议文档物理卡号为8字节BIN码直接使用long值
*/
protected static long encodePhysicalCardNo(String cardNo) {
if (StringUtils.isEmpty(cardNo)) {
return 0L;
}
try {
return Long.parseLong(cardNo);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("物理卡号必须是数字: " + cardNo, e);
}
}
/**
* 编码卡号为BCD格式保持向后兼容
* 云快充协议卡号为8字节16位BCD码需要做长度校验和补0操作
* @deprecated 请使用 encodeLogicalCardNo 或 encodePhysicalCardNo 方法
*/
@Deprecated
protected static byte[] encodeCardNo(String cardNo) {
if (StringUtils.length(cardNo) > 16) {
throw new IllegalArgumentException("云快充可接受最大卡号为16位");

View File

@@ -44,7 +44,7 @@ public class YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd extends YunKua
OfflineCardBalanceUpdateRequest request = message.getMsg().getOfflineCardBalanceUpdateRequest();
msgBody.writeBytes(encodePileCode(request.getPileCode()));
msgBody.writeBytes(encodeGunCode(request.getGunNo()));
msgBody.writeBytes(encodeCardNo(request.getCardNo()));
msgBody.writeLongLE(encodePhysicalCardNo(request.getCardNo()));
msgBody.writeIntLE(new BigDecimal(request.getLimitYuan()).movePointRight(2).intValue());
super.encodeAndWriteFlush(OFFLINE_CARD_BALANCE_UPDATE_REQUEST, msgBody, tcpSession);

View File

@@ -55,12 +55,11 @@ public class YunKuaiChongV150OfflineCardBalanceUpdateResponseULCmd extends YunKu
byteBuf.readBytes(pileCodeBytes);
String pileCode = BCDUtil.toString(pileCodeBytes);
// 物理卡号
// 物理卡号 8字节long值小端序
String cardNo = CharSequenceUtil.EMPTY;
if(byteBuf.readableBytes() >= 8) {
byte[] cardNoBytes = new byte[8];
byteBuf.readBytes(cardNoBytes);
cardNo = BCDUtil.toString(cardNoBytes);
long physicalCardNoLong = byteBuf.readLongLE();
cardNo = String.valueOf(physicalCardNoLong);
}
// 修改结果 0x00-修改成功 0x01-设备编号错误 0x02-卡号错误

View File

@@ -6,11 +6,6 @@
*/
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_CLEAR_REQUEST;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
@@ -21,6 +16,9 @@ import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage;
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_CLEAR_REQUEST;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.*;
/**
@@ -51,7 +49,7 @@ public class YunKuaiChongV150OfflineCardClearRequestDLCmd extends YunKuaiChongDo
ByteBuf msgBody = Unpooled.buffer(bufferInitialCapacity(request));
msgBody.writeBytes(encodePileCode(request.getPileCode()));
msgBody.writeIntLE(request.getTotal());
request.getCardNoList().forEach(cardNo -> msgBody.writeBytes(encodeCardNo(cardNo)));
request.getCardNoList().forEach(cardNo -> msgBody.writeLongLE(encodePhysicalCardNo(cardNo)));
super.encodeAndWriteFlush(OFFLINE_CARD_CLEAR_REQUEST, msgBody, tcpSession);
}

View File

@@ -7,15 +7,7 @@
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
@@ -27,6 +19,11 @@ import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage;
import java.util.List;
import java.util.Map;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.*;
/**
* 云快充1.5.0 离线卡数据清除应答
*
@@ -59,10 +56,9 @@ public class YunKuaiChongV150OfflineCardClearResponseULCmd extends YunKuaiChongU
// 清除结果集合
List<UplinkProto.ClearResult> clearResultList = Lists.newArrayList();
while (byteBuf.readableBytes() >= 10) {
byte[] cardNoBytes = new byte[8];
// 离线卡物理卡号
byteBuf.readBytes(cardNoBytes);
String cardNo = BCDUtil.toString(cardNoBytes);
// 离线卡物理卡号 8字节long值小端序
long physicalCardNoLong = byteBuf.readLongLE();
String cardNo = String.valueOf(physicalCardNoLong);
// 清除标记 0x00 清除失败 0x01 清除成功
byte clearFlag = byteBuf.readByte();
// 失败原因 0x01 卡号格式错误 0x02 清除成功

View File

@@ -6,11 +6,6 @@
*/
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_QUERY_REQUEST;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
@@ -21,6 +16,9 @@ import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage;
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_QUERY_REQUEST;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.*;
/**
* 云快充1.5.0 离线卡数据查询
@@ -50,7 +48,7 @@ public class YunKuaiChongV150OfflineCardQueryRequestDLCmd extends YunKuaiChongDo
ByteBuf msgBody = Unpooled.buffer(bufferInitialCapacity(request));
msgBody.writeIntLE(request.getTotal());
msgBody.writeBytes(encodePileCode(request.getPileCode()));
request.getCardNoList().forEach(cardNo -> msgBody.writeBytes(encodeCardNo(cardNo)));
request.getCardNoList().forEach(cardNo -> msgBody.writeLongLE(encodePhysicalCardNo(cardNo)));
super.encodeAndWriteFlush(OFFLINE_CARD_QUERY_REQUEST, msgBody, tcpSession);
}

View File

@@ -7,14 +7,7 @@
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170;
import java.util.List;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
@@ -26,6 +19,10 @@ import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage;
import java.util.List;
import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.*;
/**
* 云快充1.5.0 离线卡数据查询应答
@@ -50,10 +47,9 @@ public class YunKuaiChongV150OfflineCardQueryResponseULCmd extends YunKuaiChongU
// 清除结果集合
List<UplinkProto.QueryResult> queryResultList = Lists.newArrayList();
while (byteBuf.readableBytes() >= 9) {
byte[] cardNoBytes = new byte[8];
// 离线卡物理卡号
byteBuf.readBytes(cardNoBytes);
String cardNo = BCDUtil.toString(cardNoBytes);
// 离线卡物理卡号 8字节long值小端序
long physicalCardNoLong = byteBuf.readLongLE();
String cardNo = String.valueOf(physicalCardNoLong);
// 查询结果 0x00 不存在 0x01 存在
byte queryResultByte = byteBuf.readByte();
// clearResult

View File

@@ -49,8 +49,8 @@ public class YunKuaiChongV150OfflineCardSyncRequestDLCmd extends YunKuaiChongDow
msgBody.writeBytes(encodePileCode(request.getPileCode()));
msgBody.writeIntLE(request.getTotal());
request.getCardInfoList().forEach(cardInfo -> {
msgBody.writeBytes(encodeCardNo(cardInfo.getLogicCardNo()));
msgBody.writeBytes(encodeCardNo(cardInfo.getCardNo()));
msgBody.writeBytes(encodeLogicalCardNo(cardInfo.getLogicCardNo()));
msgBody.writeLongLE(encodePhysicalCardNo(cardInfo.getCardNo()));
});
super.encodeAndWriteFlush(OFFLINE_CARD_SYNC_REQUEST, msgBody, tcpSession);

View File

@@ -58,9 +58,9 @@ public class YunKuaiChongV150RemoteStartDLCmd extends YunKuaiChongDownlinkCmdExe
// 枪号
msgBody.writeBytes(encodeGunCode(gunCode));
// 逻辑卡号 BCD码
msgBody.writeBytes(encodeCardNo(logicalCardNo));
// 物理卡号
msgBody.writeBytes(encodeCardNo(physicalCardNo));
msgBody.writeBytes(encodeLogicalCardNo(logicalCardNo));
// 物理卡号 8字节long值小端序
msgBody.writeLongLE(encodePhysicalCardNo(physicalCardNo));
// 账户余额
msgBody.writeIntLE(new BigDecimal(limitYuan).multiply(new BigDecimal("100")).intValue());

View File

@@ -61,7 +61,7 @@ public class YunKuaiChongV150StartChargeAckDLCmd extends YunKuaiChongDownlinkCmd
// 枪号
msgBody.writeBytes(encodeGunCode(gunCode));
// 逻辑卡号
msgBody.writeBytes(encodeCardNo(logicalCardNo));
msgBody.writeBytes(encodeLogicalCardNo(logicalCardNo));
// 账户余额
msgBody.writeIntLE(new BigDecimal(limitYuan).multiply(new BigDecimal("100")).intValue());
// 鉴权成功标志

View File

@@ -65,10 +65,9 @@ public class YunKuaiChongV150StartChargeULCmd extends YunKuaiChongUplinkCmdExe {
int needPasswordCode = byteBuf.readUnsignedByte();
boolean needPassword = YunKuaiChongPasswordRequiredEnum.isPasswordRequired(needPasswordCode);
// 物理卡号
byte[] cardNoBytes = new byte[8];
byteBuf.readBytes(cardNoBytes);
String cardNo = BCDUtil.toString(cardNoBytes);
// 物理卡号 8字节long值小端序
long physicalCardNoLong = byteBuf.readLongLE();
String cardNo = String.valueOf(physicalCardNoLong);
// 密码
byte[] passwordBytes = new byte[16];

View File

@@ -150,10 +150,9 @@ public class YunKuaiChongV150TransactionRecordULCmd extends YunKuaiChongUplinkCm
byte stopReasonByte = byteBuf.readByte();
String stopReason = mapStopReason(stopReasonByte);
//31 物理卡号
byte[] cardNoBytes = new byte[8];
byteBuf.readBytes(cardNoBytes);
String cardNo = BCDUtil.toString(cardNoBytes);
//31 物理卡号 8字节long值小端序
long physicalCardNoLong = byteBuf.readLongLE();
String cardNo = String.valueOf(physicalCardNoLong);
additionalInfo.put("物理卡号", cardNo);
// 构建峰谷电量明细

View File

@@ -65,9 +65,9 @@ public class YunKuaiChongV160RemoteParallelStartDLCmd extends YunKuaiChongDownli
// 枪号
msgBody.writeBytes(encodeGunCode(gunCode));
// 逻辑卡号 BCD码
msgBody.writeBytes(encodeCardNo(logicalCardNo));
// 物理卡号
msgBody.writeBytes(encodeCardNo(physicalCardNo));
msgBody.writeBytes(encodeLogicalCardNo(logicalCardNo));
// 物理卡号 8字节long值小端序
msgBody.writeLongLE(encodePhysicalCardNo(physicalCardNo));
// 账户余额
msgBody.writeIntLE(new BigDecimal(limitYuan).intValue());
// 并充序号

View File

@@ -174,10 +174,9 @@ public class YunKuaiChongV170TransactionRecordULCmd extends YunKuaiChongUplinkCm
byte stopReasonByte = byteBuf.readByte();
String stopReason = mapStopReason(stopReasonByte);
// 35. 物理卡号
byte[] cardNoBytes = new byte[8];
byteBuf.readBytes(cardNoBytes);
String cardNo = BCDUtil.toString(cardNoBytes);
// 35. 物理卡号 8字节long值小端序
long physicalCardNoLong = byteBuf.readLongLE();
String cardNo = String.valueOf(physicalCardNoLong);
additionalInfo.put("物理卡号", cardNo);
// 构建峰谷电量明细