最近在做一个项目,用到了8583协议。踩了许多坑,项目已经上线了,写一篇博客记录一下最近使用的一些方法总结。
(一)主要介绍8583协议,(二)总结使用Java两种方式来实现8583.
需要代码的请直接看(二),不过建议你还是先看看(一),多了解了解总没有坏处的。
1.8583 简介
8583协议是基于ISO8583报文国际标准的包格式的通讯协议,8583包最多由128个字段域组成,每个域都有统一的规定,并有定长与变长之分。8583包前面一段为位图,它是打包解包确定字段域的关键代替。8583协议多在POS机的开发上使用。(摘自百度百科解释)8583报文里,采用了以域的形式进行传输。与普通json不同是,json是key=value的形式,而8583是双方约定好,每个域是什么意思,然后再域里面进行填值。8583的格式一般由三部分组成,头部信息、位图和域。
2.8583 结构介绍
8583的结构:报文长度(4个字节,可以根据协议自己定)+报文头(可以是TPDU+消息标识等等,一般4个字节,如果加上TPDU那么10个字节以上了,根据协议自己定)+位图(8字节,如果是128域表示,这个域占16字节)+实际数据data,一般数据都采用16进制表示法。注意,这里只是通常表示是这样的,根据实际情况会有所不同。8583最多有128个域,每个域都有统一的规定,并有定长与变长之分。什么是定长,什么是变长呢?说白了就是定长是固定长度,变长是可变长度。每个域是定长还是变长,都会在域中有说明。说明一下,有很多公司使用了8583协议,其实是伪8583协议,意思就是采用了8583协议,但是他们里面域的用法与实际8583有很大区别,所以大家请注意了。
3.8583 内容介绍
下图是对于8583报文结构样例表格说明,请记住,这是样例,不同的项目可能会有细小差别,请勿照搬照用,对于下图的字母所代表的含义,后面有讲到。
报文长度 |
TPDU |
报文头 |
应用数据 |
||||||
ISO8583 Msg |
|||||||||
|
ID |
目的 地址 |
源地址 |
应用类别定义 |
软件 版本号 |
终端 状态 |
处理 要求 |
保留 使用 |
交易数据 |
H4 |
60H |
NN NN |
NN NN |
N2 |
N2 |
N1 |
ANS1 |
N6 |
不定长度 |
- 报文长度,这个一般是等后面除长度部分拼好以后计算出来的,这个长度也就是报文头+位图+ 实际数据的长度,在这里就是4+8(16)+data.length()/2。注意,如果是16进制表示,那么就是两个字节表示一位,后面我们详细举例。假设我们计算长度是42,那么4个字节是0042,16进制表示法是30 30 34 32。这里我使用到的是0042.
- TPDU,全称Transport Protocol Data Unit,是指传送协议数据单元,这里不做过多的解释,有兴趣自行百度。
- 报文头部分,一般来讲都是固定部分,假设是只用4个字节表示消息类型,比如用1000表示交易类型的报文,1200表示退款类型的报文等等,那么实际表示应该是31 30 30 30 30、31 32 30 30。
- 应用数据,这里就不太一致了,我这的项目是共64域,之前还遇到过128域的情况。其实域多少不用在意,原理都是一样的。
4.域中格式说明
在8583接口文档中,大概能看到如下常用符号定义:
—— M 强制域(Mandatory),此域在该消息中必须出现否则将被认为消息格式出错。
—— C 条件域(Conditional),此域在一定条件下出现在该消息中,具体的条件请参考备注说明。
—— O 选用域(Optional),此域在该消息中由发送方自选。。
—— Space 此域在该种消息中不出现。
—— A 字母a-z
—— n 数字0-9
—— s 特殊字符
—— an 字母和数字字符
—— ans 字母、数字和特殊字符
—— MM 月
—— DD 日
—— YY 年
—— hh 小时
—— mm 分
—— ss 秒
—— LL 允许的最大长度为99
—— LLL 允许的最大长度为999
—— VAR 可变长度域
—— b 数据的二进制表示,后跟数字表示位(bit)的个数
—— B 用于表示变长的二进制数,后跟数字表示二进制数据所占字节(Byte)的个数
—— z 按GB/T 15120和GB/T 17552的2、3磁道编码
—— cn BCD压缩编码数值,右补F
举个例子:
位 |
域名定义 |
属性 |
格式 |
类型 |
请求 |
响应 |
备注 |
|
类型 |
n4 |
|
BCD |
1234 |
2234 |
TYPE |
|
位元表 |
b64 |
|
BINARY |
M |
M |
BIT MAP |
2 |
XXX |
n..19 |
LLVAR |
BCD |
C |
M |
XXXXXXXXXXXXXXXXXXXX |
- 首先从以上表格中,我们能看到在数据域里面,前四位固定长度是类型,请求使用1234,成功响应回来是2234,
- 其次跟在后面的是位元表,共64位,由16位明文数字构成,代表哪个域里有值,哪个域没值。这里我简单介绍一下,位元表怎么使用。
假设位元表是:7020008000C00053。
7的二进制是0111,这就代表了1域是空,2,3,4域有值;
0的二进制是0000,5,6,7,8全是空。
数字16位,二进制64位,则可以看出,这个报文里面,哪些域是有值,哪些没值的。
- 2域,数字19位,左靠BCD补0。这是什么意思呢?假设我有19位数字“1234567891234567891”,那么在拼接报文中,就是“1912345678912345678910”,前面19代表域的长度是19
5.8583 如何发送
当我们组装好了报文,如何发送给目标服务器呢?使用socket发送。
如果不清楚socket的,可以自行百度一下,这里不做过多的讲述。这里推荐使用socket连接池、tcp连接池的方式发送,连接池的好吃这里不做过多讲述。如果需要代码,请看ISO 8583使用总结(附Java部分源码)(二)(暂时还没写呢)。