如何向POS设备发送ECR金额消息?设备无响应求助
POS设备金额命令发送无响应排查方案
问题概况
要给POS设备发送「金额」命令启动信用卡验证,设备要求使用类数据报协议的消息,示例十六进制报文如下:
00 1A 30 30 30 30 30 30 30 30 30 30 30 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C
报文前2个字节为消息长度头。
使用以下Pascal代码发送后,设备无任何响应:
s := #$00#$1A#$30#$30#$30#$30#$30#$30#$30#$30#$30#$30#$30#$1C#$1C#$1C#$1C#$1C#$1C#$1C#$1C#$1C#$1C#$1C; IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_8Bit; IdTCPClient1.IOHandler.ReadTimeout := 3000; IdTCPClient1.IOHandler.Write(s);
参考协议示例可查看:
排查方向与解决建议
- 核对长度头与报文长度:示例里的
00 1A是十六进制,转十进制为26。需先明确长度头的定义:是包含自身的总报文长度,还是仅后续数据的长度。如果是后者,后续数据需为26字节,加上2字节头总长度为28,但当前代码的s仅24字节,明显不匹配。对照截图里的协议说明,算准报文长度后再调整。 - 改用字节数组发送:用字符串拼接字节可能因编码隐性转换出问题,换成
WriteBytes直接发送原始字节数组更可靠:var MsgBytes: TIdBytes; begin SetLength(MsgBytes, 24); // 先按示例长度定义,后续根据协议调整 MsgBytes[0] := $00; MsgBytes[1] := $1A; FillChar(MsgBytes[2], 11, $30); // 填充11个$30字符 FillChar(MsgBytes[13], 11, $1C); // 填充11个$1C字符 IdTCPClient1.IOHandler.WriteBytes(MsgBytes, Length(MsgBytes)); end; - 主动读取设备响应:部分POS设备要求发送方读取响应后才会继续交互,即使不需要响应内容,也要尝试读取避免通信阻塞。发送后可添加读取代码:
var RespBytes: TIdBytes; begin // 先执行发送代码 try IdTCPClient1.IOHandler.ReadBytes(RespBytes, -1, False); // 读取所有响应字节 // 可打印RespBytes内容辅助排查 except on E: EIdReadTimeout do // 处理超时情况 end; end; - 确认连接状态:发送前检查客户端是否已成功连接,避免在断开状态下发消息:
if not IdTCPClient1.Connected then IdTCPClient1.Connect; - 检查协议细节:对照截图里的协议内容,确认是否遗漏了结束符、校验位(如LRC、CRC),或者字节序(大端/小端)是否符合设备要求。这类细节往往是设备无响应的常见原因。
内容的提问来源于stack exchange,提问作者Boris Nihil
相关产品推荐
相关产品推荐

