ISO8583报文协议介绍--简单的8583框架Simple8583

  最近在做中国银行的一个快捷支付渠道,使用的是ISO8583协议,一开始用的是JPOS框架,但是感觉框架比较臃肿,而且文档也比较少。在等待银行专线的过程中,自己闭门造车做了一个简单的8583报文解析框架(Simple8583),将程序重写了一遍,渠道中的代码量少了不少,这几天中行的接口在测试环境终于调试完成了。抽空分享一下这段时间自己学到的知识。

    首先,8583协议只是一种报文格式,定义了每个字段域的编码格式和长度,比如下面的这段报文(每两位一个字节,用16进制表示)

        00D5(报文头213,经验证正确)          6000360000(TPDU,5)          0100(Version,2)         0220(MTI,2)         7124058104F18005(BitMap,选中域为2,3,4,8,11,14,22,24,25,32,38,41,42,43,44,48,49,62,64)         164096665528659482(数据域2,卡号,8,1字节头部长度)         270000(数据域3,处理码,3)         000000000001(数据域4,金额,6)         2020202020202020202020(数据域8,终端号,11个空格)         369797(数据域11,流水号,3)         1607(数据域14,卡有效期YYMM,2)         0012(数据域22,输入方式码,2,n3)         0025(数据域24,NII,固定值025,2,n3)         08(数据域25,服务条件码,1)         2001(数据域32,接入机构代码,2)         343830343832(数据域38,授权码,6)         3331303130303030(数据域41,终端号,8)         313034333130313533313131303131(数据域42,商户号,15)         C9CFBAA3D0C2C0CBD6A7B8B620202020202020202020202020202020202020202020202020202020(数据域43,一级商户名,40)         203230303132303134303730393238343935353139(数据域44,交易订单号,LLVAR,1+20字节)         000739323033313533(数据域48,附加数据9203153,LLLVAR,2+7)         0156(数据域49,货币代码,2,n3)         00443032303037313537313932303134303730393134333935313230303132303134303730393238343935353139(数据域62,原始交易信息,包含几个子域)             (0044(长度)                 30323030(原MTI,0220,4字节)                 373135373139(原交易流水,715719,6字节)                 3230313430373039313433393531(原交易日期+时间,20140709143951,14字节)                 3230303132303134303730393238343935353139(原交易流水号:20012014070928495519,20字节))         D0087FDAAFBFA281(数据域64,MAC,8) 

二、数据类型与编码格式:

    根据接触到的数据类型将数据分为如下几种类型:

                CHAR(asc编码,直接使用字符串的getBytes(ENCODING)方法获取字节数组),

                BINARY(二进制编码,在打包时将8位01值组装为一个字节),

                NUMERIC(BCD编码,即8421码),

                LLVAR(变长域,采用ASC编码,每个LLVAR类型的域前会有1字节的域字节长度,表示长度的字节用BCD编码表示)

                LLLVAR(变长域,与LLVAR域类似,不同之处在于每个LLLVAR域前会有2字节的域字节长度,长度同样以BCD编码表示)

                LLVAR_NUMERIC(变长域,采用BCD编码,前有1字节的长度,长度为域值的长度,而非字节长,如域值为123456,编码后长度为3字节,但是表示域长的字节值为6)

                如果用到其它数据类型可以在IsoType中进行添加,并在IsoField中添加处理操作

三、BitMap:

                BitMap是ISO8583报文的精髓所在,ISO8583报文支持64域和128域两种,但是并非每次请求都会将所有域都请求过去,BItMap就起到了标识哪些域是有效的请求域,接收方也会根据BitMap中约定的值对域进行解析。

                那么BitMap又是如何工作的呢?

                首先,BItMap分为8字节和16字节两种情况,分别表示支持64域和128域,其第一位值为1,表示BitMap为16字节,否则为8字节。

                其次,BitMap中的每一位对应数据域的第几域,有效域会置为1,比如01001000表示第二域和第5域为有效位。

                在Simple8583中具体的实现是通过BitMap类实现的,具体可参考源码

四、mti:

            mti即 message type identifier消息类型标识,为4位bcd编码的数字标识符,用于描述信息的类型。

           同一个mti可以用于标识多个不同的交易,比如一般常用的0200可以用来表示消费交易,消费撤销,分期付款消费和分期付款撤销,但是对于同一个mti标识的数据域类型定义是类似的。

           具体的实现,我将Simple8583的xml文件设置为了两部分,一部分为公用的报文头,如msgLength,tpdu,bitmap等,另外一部分分按照mti的不同分为多个package体。

五、粗略的实现流程:

          1)组装请求的Map<String,String>数据(只组装需要的数据域,key值为对应的数据域或包头的值)

          2)请求数据进入SimpleClient代理,SimpleClient根据传入的值解析xml文件(jaxb实现,做了缓存)

          3)根据传入值的mti寻找对应的IsoPackage类,对找到的IsoPackage类进行clone(避免污染),对clone值中的域进行值处理和格式化

          4)生成BitMap,计算Mac值(如有)

          5)使用ByteArrayOutputStream将组装成的IsoPackage域值进行拼装成为一个大的byte数组,在byte前拼装两个字节的长度

          6)通过Socket将数据发送并接受响应(读取前两个字节长度,根据长度获取其剩余报文),根据IsoPackage解析报文域,解析得到BitMap后根据BitMap对数据域进行解析,并将值都放入到对应的field中

          7)将数据都放在Map中返回,并进行MAC校验(如有)

 

六、放一副图,自吹一下:

ISO8583报文协议介绍--简单的8583框架Simple8583_第1张图片



你可能感兴趣的:(ISO8583报文协议介绍--简单的8583框架Simple8583)