Andorid开发之银联ISO8583报文格式、组包和解包过程、TPDU、位图计算过程
来源:互联网 发布:linux所有命令 编辑:程序博客网 时间:2024/06/04 22:30
8583:
8583协议是基于ISO8583报文国际标准的包格式的通讯协议,8583包最多由128个字段域组成,每个域都有统一的规定,并有定长与变长之分。8583包前面一段为位图,它是打包解包确定字段域的关键代替。8583协议多在POS机的开发上使用。
TDDU:
TPDU,全称Transport Protocol Data Unit,是指传送协议数据单元。代表从一个传输实体发送至另一个传输实体的消息。
位图:
一个用来表明需要那些域的8字节数据
例如:位图:20 00 38 00 00 00 00 34
你把它解开,
排列一下
20 = 0010 0000
00 = 0000 0000
38 = 0011 1000
依次类推,得到一串数字,总共64位
0010 0000
0000 0000
0011 1000
0000 0000
0000 0000
0000 0000
0000 0000
0011 0100
以上数据有多少个1表明需要多少个域的数据,而1的位置表明需要那个域的数据,
以上数据需要3、5、6、44、45、46、62域的数据,以此类推
8583组包格式:
报文长度(2字节)+TPDU(5字节)+报文头(6字节)+域数据(指令码(0域 2字节)+位图(8字节)+其他域数据)
报文长度:从TPDU-报文结尾
一个域数据对象可以包括:
域长度类型:FIX_LEN(0-9)、LLVAR_LEN(0-99)、LLLVAR_LEN(0-999)
域长度:0-999
域编码类型:BCD、ASCII 、BINARY
其他域数据: 如果 域长度类型是FIX_LEN(0-9)则其他域数据为:域数据
如果 域长度类型是LLVAR_LEN(0-99)则其他域数据为:计算的1字节域数据长度+域数据
如果 域长度类型是LLLVAR_LEN(0-999)则其他域数据为:计算的2字节域数据长度+域数据
8583组包过程:
1.创建一个ByteArrayOutputStream output = new ByteArrayOutputStream();来写入数据域的数据
2.将指令码以拆分成2个字节的二进制数据写入output ;
3.计算出8个字节的位图,然后写入output
4.将其他域数据写入output,前面已经说过其他数据域可能包含数据长度,所以要判断数据域的长度类型,其中域长度有不定长和定长之分,首先判断数据长度类型是定长FIX_LEN直接将数据写入output,如果是不定长,不定长分为:LLVAR_LEN和LLLVAR_LEN,如果是LLVAR_LEN表示数据长度为1个字节,首先将数据长度计算出来1个字节大小,然后将数据长度1各字节写入output,然后写入该域数据,如果是LLLVAR_LEN表示数据长度为2个字节,首先将数据长度计算出来2个字节大小,然后将数据长度2各字节写入output,然后写入该域数据
5.判断域数据的编码格式,将数据转换成对应的编码格式写入output
6.通过以上6步我们已经把域数据写入成功,现在得到标准的8583格式域数据长度output.toByteArray().length,然后+11字节的TPDU和报文头
7.通过该计算
byte[] lengthRes = { (byte) ((resultLen >> 8) & 0xFF),
(byte) ((resultLen) & 0xFF) };
得到2字节的数据长度8.新建ByteArrayOutputStream result= new ByteArrayOutputStream()
9.将计算的2字节长度写入result
10.写入TPDU和报文头到result
11.将output写入result
12.通过socket将result.toByteArray()发送到平台
8583解包过程:
因为平台发送过来的数据和我们组包过去的数据是一回事,所以我们只要按照我们发送的方式进行解包就行
1.Socket将组包的数据发送过去之后,立即读取平台返回的数据byte data[]然后截取数据域的数据,也就是将报文长度和APDU和报文的13个字节去除,得到域数据
2.创建ByteArrayInputStream datas = new ByteArrayInputStream(data);其中data是1中得到域数据数组
3.创建装载位图数组byte[] bitmapArray = new byte[8];
4.使用datas.read(bitmapArray, 0, 2);首先将2个字节的命令码读取出来
关于 int read(byte[] b,int off,int len)
b 将读取的len-off个数据缓存到b
最多读取len个字节的命令码,此read方法是一直往下读取
并且如果再次read会覆盖之前的数据
如果读取的数据长度小于b的长度,以0填充5.使用datas.read(bitmapArray, 0, 8);读取位图数据,因为read是一直读下去的,所以读完命令码之后就开始读取位图数据,并且read方法又是覆盖式的,所以将命令码数据覆盖掉了,最后bitmapArray 中就是我们的位图数据
6.使用位图的对象BitArray bitmap = new BitArray(64, bitmapArray);将位图数据传入,并用.get(i),判断返回是否会返回该域数据,如果会返回再进行域数据解包
7.如果使用位图对象判断返回了该域数据,首先判断域数据的长度类型,如果是FIX_LEN则直接将标准的域长度处理:
if (entity.getCodeType() == CodeType.L_BCD || entity.getCodeType() == CodeType.R_BCD) { if (len % 2 != 0) { len = len + 1; } len = len / 2; }
如果是LLVAR_LEN类型,则首先读取1字节的域数据长度装载在数组里面,然后转换成int
然后再:if (entity.getCodeType() == CodeType.L_BCD || entity.getCodeType() == CodeType.R_BCD) { if (len % 2 != 0) { len = len + 1; } len = len / 2; }
如果是LLLVAR_LEN类型,则首先读取2字节的域数据长度装载在数组里面,然后转换成int
然后再:if (entity.getCodeType() == CodeType.L_BCD || entity.getCodeType() == CodeType.R_BCD) { if (len % 2 != 0) { len = len + 1; } len = len / 2;
8.创建byte[] contextByte = new byte[len];用来装载域的数据,不包括域数据长度,len为经以上7计算的len,
9.读取域数据datas.read(contextByte, 0, len);此时的contextByte就是平台穿过来的域数据,不包括域长度
10.根据域编码类型对contextByte进行解码
11.创建Map集合,map.put(i + 1, contextStr);
因为集合是从0开始的,+1后,例如:使用get(43)得到的就是43域的数据
- Andorid开发之银联ISO8583报文格式、组包和解包过程、TPDU、位图计算过程
- 中国银联8583报文(JAVA)封包/解包/位图 相关操作源代码
- 短信模块开发 tpdu格式
- 短信模块开发 tpdu格式
- ISO8583包简介
- ISO8583包[详细说明]
- ISO8583包[详细说明]
- ISO8583包详细资料
- iso8583 包原理
- IPSec传输模式/隧道模式下ESP报文的装包与拆包过程
- 描述在IPSec传输模式下ESP报文装包和拆包过程
- IPSec 传输模式下 ESP 报文的装包与拆包过程
- IPSec 传输模式下 ESP 报文的装包与拆包过程
- jenkins插件开发过程中log4j包冲突问题解决过程
- pl/sq之过程,函数,包,触发器
- pl/sq之过程,函数,包,触发器
- 求知过程之maven包过滤
- Oralce存储过程之包内调用其他过程
- Tensorflow学习笔记(2)
- QA工程师职业发展的三个细分方向
- 转载《Linux实现VLAN功能》
- MaskedEdit
- 利用js实现 禁用浏览器后退
- Andorid开发之银联ISO8583报文格式、组包和解包过程、TPDU、位图计算过程
- sql语句删除数据库中所有表
- CH6--正则匹配,p112,练习二,
- 分治法_二分查找法
- flume扇入扇出
- 让你10行代码写完列表类的界面——YzsBaseListActivity
- 【ife】任务八 : 响应式网格(栅格化)布局
- USB协议架构及驱动架构
- 学习Caffe(三)——Caffe源码阅读