前言
最近在做8583报文这块解析,也遇到一些坑。下面将会介绍自己学习和了解8583报文这块的经验,希望可以帮到那些刚刚接触8583报文的同学们。
入门
首先我们需要知道的是我们的8583报文是基于POS(销售终端的)
还是基于银联银行卡交换系统
的报文。网上有很多关于POS终端系统8583解析相关的文章,但是关于银联银行卡交换系统的报文很少。所以本文介绍的是基于银行银联卡交换系统
8583报文解析的。阅读这篇博客之前,需要读者阅读这篇博客 8583报文基础知识 。
报文的结构
银联银行卡的报文结构包括4个部分,它们分别是报文头
、报文类型标志符
、位图
、报文域
,其结构图如下所示:
-
报文头
报文头的组成如下所示:
报文头一共占46个字节,且这些域为必填域。 -
报文类型标志符
报文类型标志符是有4个定长数字字符组成,这4个定长数字字符表示的是该报文的一个类型,例如0200表示金融请求报文,0210表示金融响应报文。
- 位图
报文中使用位图来标识报文中有哪些域而没有哪些域,一个报文可以有一个位图或者两个位图。
第一个位图
:通常又被称做主位图,每一个报文都有主位图。它是由64个二进制位(即8个字节)组成。位于报文类型标识符之后。8583报文都是16进制数据的报文,所以需要将8个字节的16进制数据转换成二进制数据。转换后除了第一位,每一位和一个域相对应,即和域2到域64相对应。如果一个位为0表示与之对应的域不出现在报文中,反之为1表示与之对应的域出现在报文中。需要注意的是主位图的第一位用来指明在主位图后是否还有第二个位图,第二个位图同样也是64个二进制位(即8个字节)组成。
这里举一个例子加深我们对位图的理解,假设有一个报文的位图数据为F2 3E 40 81 8A C0 80 10 00 00 00 00 10 00 00 C1
。解析之前需要知道1 byte = 8 个比特位 ,1字节=2个16
进制数。所以主位图的数据8个字节=8对16进制数即F2 3E 40 81 8A C0 80 10
,分别转化8位二进制数据为:11110010 00111110 01000000 10000001 10001010 11000000 10000000 00010000
。通过上面我们知道主位图第一位标识是否有第二个位图。这里第一个位为1,故这个报文有2个位图。从主位图第一位后,每一位与一个域对应1表示该域存在,0表示不存在。所以上面二进制数据从2,3,4,7,11,12,13,14,15,18,25,32,33,37,39,41,42,49,60位置都是1,表明与之对应对域对象存在。第二个位图同理可得100,121,122,128位置域都存在。
- 报文域
通过上面的位图,可以知道报文存在那些域。此时就可以很方便对报文进行解析。可以参考百度对于各个域的介绍百度8583报文域说明,也可以下载银联银行卡交换系统技术规范获取更多关于8583报文域名的信息。
响应报文的解析
解析报文之前,我们需要了解一下ACILL编码对照表因为后面解析会用得着,其编码表如下图所示:
下面是一个响应的8583报文,这里响应报文是没有报文头的。
30323130F23E40818AC0801000000000100000C13136363232343234323330303030303036393031303030303030303030303130303030303037313730393435343034383037353230393435343030363237313930313037323236303130303030383134333733303230303831343337333032303030303030303438303735323030303130303038202030313030303820202020202020202031353630333030303030303530303036303030303030303030303430313130303030303030383932303130303030303433353143533232303030303034353033313030303030202020303030303030303030303030303030303030303030333030303632303442303539
需要注意的是响应报文组成部分是没有报文头的,解析步骤如下:
- 获取报文类型标志符
报文标志符号是4位的定长数字字符(这4位都是ASCII字符),4个定长数字字符(ASCII字符)= 4对16进制数,所以前四对16进制数据分别为:30 32 31 30
,通过查询ASCII码表可知,其分别代表0210
。 - 解析位图
主位图数据为F2 3E 40 81 8A C0 80 10
,其转化8位二进制数据为:11110010 00111110 01000000 10000001 10001010 11000000 10000000 00010000
。这里第一个位为1,故这个报文有2个位图,00 00 00 00 10 00 00 C1
是第二个位图数据。从主位图第一位后,每一位与一个域对应1表示该域存在,0表示不存在。所以上面二进制从2,3,4,7,11,12,13,14,15,18,25,32,33,37,39,41,42,49,60位置都是1,表明与之对应对域对象存在。第二个位图同理可得100,121,122,128位置域都存在。 - 解析相关的域
依照上面的位图信息查阅8583的128的域属性,整体报文域解析如下所示:
30 32 31 30 (报文类型标志符)
F2 3E 40 81 8A C0 80 10 00 00 00 00 10 00 00 C1 (2个位图)
3136(变长长度为16) 36323234323432333030303030303639 域2
32 31 30 30 30 30 域3
30 30 30 30 30 30 31 30 30 30 30 30 域4
30 37 31 37 30 39 34 36 35 30 域7
34 38 30 37 35 35 域11
30 39 34 36 35 30 域12
30 36 32 37 域13
31 39 30 31 域14
30 37 32 32 域15
36 30 31 30 域18
30 30 域25
3038(变长长度为08) 31 34 33 37 33 30 32 30 域32
3038(变长长度为08) 31 34 33 37 33 30 32 30 域33
30 30 30 30 30 30 34 38 30 37 35 35 域37
30 30 域39
30 31 30 30 30 38 20 20 域41
30 31 30 30 30 38 20 20 20 20 20 20 20 20 20 域42
31 35 36 域49
30 33 30(变长长度为30) 30 30 30 30 30 35 30 30 30 36 30 30 30 30 30 30 30 30 30 30 34 30 31 31 30 30 30 30 30 30 域60
30 38(变长长度为08) 39 32 30 31 30 30 30 30 域100
30 34 33(变长长度为43) 35 31 43 53 32 32 30 30 30 30 30 34 35 30 33 31 30 30 30 30 30 20 20 20 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 域121
30 31 33(变长长度为13) 31 32 33 31 32 33 31 32 33 31 32 33 31 域122
解析除了128位mac校验码之外(需要获取项目的密钥和加密算法进行解析)其他域解析如下所示。
// fld: 域 [000] 表示0域,[004]表示长度,[0210]表示解析出来的内容。需要注意的是报文没有0域,这里0域名
// 指的是报文的类型标志符
fld[000][004]=[0210]
fld[002][016]=[6224242300000069]
fld[003][006]=[010000]
fld[004][012]=[000000100000]
fld[007][010]=[0717094540]
fld[011][006]=[480752]
fld[012][006]=[094540]
fld[013][004]=[0627]
fld[014][004]=[1901]
fld[015][004]=[0722]
fld[018][004]=[6010]
fld[025][002]=[00]
fld[032][008]=[14373020]
fld[033][008]=[14373020]
fld[037][012]=[000000480752]
fld[039][002]=[00]
fld[041][008]=[010008 ]
fld[042][015]=[010008 ]
fld[049][003]=[156]
fld[060][030]=[000005000600000000004011000000]
fld[100][008]=[92010000]
fld[121][043]=[51CS22000004503100000 0000000000000000000]
fld[122][003]=[000]
请求报文解析
现有一个请求报文如下图所示(请求是有报文头,报文头长度46个字节):
2E 02 30 33 30 34 30 30 30 31 30 30 30 30 20 20
20 34 38 30 31 30 30 30 30 20 20 20 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32
30 30 F2 38 44 81 A8 E0 80 10 00 00 00 00 00 00
00 01 31 36 36 32 32 35 30 30 30 30 30 30 30 30
30 30 31 34 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 39 30 31 30 31 34 31 31 34 34 34 36
33 34 38 35 30 37 31 31 34 34 34 36 31 30 31 34
37 35 33 31 30 32 32 30 30 30 38 34 38 30 31 31
30 30 30 30 38 34 38 30 31 30 30 30 30 32 39 36
32 32 35 30 30 30 30 30 30 30 30 30 30 31 34 3D
33 30 31 30 32 30 31 30 30 30 30 30 31 30 31 34
30 30 30 30 34 39 34 31 30 30 30 30 30 31 39 31
38 30 31 31 31 30 30 37 35 33 31 30 30 30 31 B2
E2 CA D4 C9 CC BB A7 5A 30 30 30 31 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 31 35 36 30 32 37 30 30 30
30 30 32 30 30 30 33 30 30 30 30 30 30 30 30 30
30 30 30 31 31 30 30 30 43 46 41 46 46 31 43 36
- 报文头 46个字节=46对16进制数
2E 02 30 33 30 34 30 30 30 31 30 30 30 30 20 20
20 34 38 30 31 30 30 30 30 20 20 20 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30
- 报文类型标志符 4字节=4对16进制数
30 32 30 30
- 位图
F2 38 44 81 A8 E0 80 10 00 00 00 00 00 00 00 01
这里可以将上面16进制数据转化为2进制,就如同上面响应报文那样,还有一种简单的方式就是通过使用位图工具解析域,如下图所示:
- 根据位图结合域的详细说明来解析结果如下:
fld[000][004]=[0200]
fld[002][016]=[6225000000000014]
fld[003][006]=[000000]
fld[004][012]=[000000000090]
fld[007][010]=[1014114446]
fld[011][006]=[348507]
fld[012][006]=[114446]
fld[013][004]=[1014]
fld[018][004]=[7531]
fld[022][003]=[022]
fld[025][002]=[00]
fld[032][008]=[48011000]
fld[033][008]=[48010000]
fld[035][029]=[6225000000000014=301020100000]
fld[037][012]=[101400004941]
fld[041][008]=[00000191]
fld[042][015]=[801110075310001]
fld[043][040]=[测试商户Z0001 ]
fld[049][003]=[156]
fld[060][027]=[000002000300000000000011000]
fld[128][008]=[CFAFF1C6]