ISO8583 message protocol

In fact, the data content involved in the financial industry is not tens of thousands and cannot be counted. On the contrary, it is relatively small. We can all count in our hearts, such as transaction type, account number, account type, password, transaction amount, transaction fee, date and time, merchant code, 2-magnetic-3-magnetic data, transaction serial number, etc. All sum up to about 100 data. Then we can simply design ISO8583 first, define 128 fields, and arrange all the financial data types that can be considered, such as the "account number" mentioned above, in an order, corresponding to one of the 128 fields. Each data type occupies a fixed length, and the order and length are defined in advance. This is very simple. To send a message, connect the 128 fields in sequence, and then send the entire string of data packets connected.

    After any financial software receives the ISO8583 package, it can be unpacked directly according to the specification we defined, because which one of the 128 fields of the entire message represents what, everyone knows, as long as you know that your data package is The ISO8583 package is enough, we have already defined it. For example, the first field is "transaction type", the length is 4 digits, the second field is "account number", which is 19 digits and so on. The receiver can take 4 bits first, then take the next 19 bits, and so on, until all 128 fields of the entire data packet are solved.

 In fact, this approach is really simple and straightforward, and basically it can meet the needs. But we have a few questions to think about:
1. How do I know the data type of each field, is it a number or a character?
2. Each transmitted message transmits all 128 fields, and the network bandwidth can bear it. Sometimes I may only need 5 fields, and as a result, 123 useless fields are received.

3. What if the length of some of my fields is not fixed and it is variable length, because you are now unpacking as if each field of the data packet is fixed, and when unpacking in C language, you directly rely on the pointer to take a fixed length String characters as a field.

  Let's solve these problems one by one.

    The first question is simple. When I define ISO8583, in addition to defining what each field represents, I also stipulate that its content is a number or a character. Consider the possible types but there are the following: letters, numbers, special characters, time such as year, month, day, and binary data. For example, I define the length of the "merchant type" field in the 128 fields as 15, and define its type as letters. To be more precise, what if the data in "merchant type" includes both numbers and letters? Then we can define its type as a letter or a number, that is, a field can belong to multiple types at the same time.

    The second question is a little more complicated. The essence is that if I only pass 5 fields of the 128 fields, how does the receiver know which fields I have passed to it. What if we fill all the remaining 123 with 0 or other special identifiers, indicating that this field does not need to be used? This processing method is useless and does not solve the essential problem of network bandwidth, so 128 fields need to be passed.

    In another way, I add a header in front of the message, and the information contained in the header can let others know that only 5 fields are passed. How to design this header, we can use 16 bytes, that is, 128 bits (one byte is equal to 8 bits) to indicate whether a field in the 128 fields exists. Each bit is either 1 or 0 in the binary of the computer. If it is 1, it means that the corresponding field exists in this message. If it is 0, it does not exist. That's good, if someone else receives an ISO8583 message, they can first know which fields are in the message immediately after the header based on the header of the message, and which fields are missing. For example, if I want to send 5 fields, which belong to the 2nd, 3rd, 6th, 8th, and 9th fields of the 128 fields, I can fill in the 128-bit packet header as 011001011000000000......, a total of 128 bits , followed by all 0s. Note that the 2nd, 3rd, 6th, 8th, and 9th bits are 1, and the others are 0.

    有了这个128bit的报文头,我们就可以只发送需要的5个字段了。怎样组织报文?先放上这128bit,即16个字节的头,然后在头后面放2、3、6、8、9字段,这些字段紧挨在一起,3和6之间也不需要填上4、5这两个字段了。接收方收到这个报文,它会根据128bit的报文头来解包,它自然知道把第3个字段取出后,就直接在第3字段的后面取第6个字段,每个字段的长度在ISO8583里面都定义好了,很轻松就把数据包解出来了。

    这下好了,为了解决上面的第二问题,我们只是在报文中增加了16个字节的数据,就轻松搞定了,我们把这16个字节称为bit map,即位图,用来表示某个位是否存在。不过我们再稍微优化一下,考虑到很多时候报文不需要128个字段这么多,其一半64个字段都不一定能够用完。那我可以将报文头由128bit减到64bit,只有在需要的时候才把剩下的64bit放到报文里面,这样报文长度不又少了8个字节吗?

    是个好主意。我们把ISO8583的128个字段中最常见的都放到前64个字段中,那我们可以将处理缩小一倍。这样我一般发送报文时只需发送64bit,即8个字节的报文头,再加上需要的几个字段就可以了。如果有些报文用到64到128之间的字段呢?这个也好办,我把64bit报文头的第一位bit用来代表特殊含义,如果该bit为1,则表示64bit后面跟了剩下的64bit报文头;如果第一位bit为0,则表示64bit后面没有跟剩下的64bit报文头,直接是128个字段中的报文了。那们,接收方会判断一下报头的第一个bit是1还是0,从而知道报文头是64bit还是128bit了,就可以做相应处理。因为报文头第二个64bit属于有时候有,所以我们叫它Extended bit map扩展位图,相应的报文头最开始的64bit我们叫它Primary bit map主位图。我们直接把扩展位图固定放到128个字段的第一个字段,而主位图每个数据包都有,就强制性放在所有128个字段的前面,并不归入128个字段中去。

    第三个问题可以考虑这样解决。比如第2个字段是“帐号”,是不定长的,可能有的银行帐号是19位,有的是17位等。我们定ISO8583规范时可以规定第2个字段是25位,这下足够将19和17的情况都包含进来,但是如果以后出现了30位的怎么办?那我们现在将字段定为100位。以后超过100位怎么办,况且如果你只有19位的帐号,我们定义了100位,那81位的数据不是浪费了网络的带宽。看来预先定义一个我们认为比较大的位数是不太好的。
  
    我们这样,对于第2个字段“帐号”,在字段的开头加上“帐号”的长度。比如帐号是0123456789,一共10位,我们变成100123456789,注意前面多了个10,表示后面的10位为帐号。如果你接触过COM里面的BSTR,应该对这种处理比较熟悉了。接收方收到该字段后,它知道ISO8583规定第2个字段“帐号”是变长的,所以会先取前面的2位出来,获取其值,此时为长度,然后根据该长度值知道应该拷贝该字段后面哪几位数据,才是真正的帐号。如果你觉得长度如果只有两位最多只能表示99位长,不太够,我们也定义可以允许前面3位都为长度的变长字段,这样就有999位长,应该够了吧。在规范里面如果我定义某个字段的属性是“LLVAR”,你注意了,其中的LL表示长度,VAR表示后面的数据,两个LL表示两位长,最大是99,如果是三位就是“LLLVAR”,最大是999。这样看我们定义的ISO8583规范文档时直接根据这几个字母就理解某个变长字段的意思了。

    该解决的几个问题到这里都解决了,我们来回顾下自己设计的ISO8583规范。其实没有什么,无非是把金融行业可能出现的数据分门别类,排好顺序,接着把它们连接起来,组成一个报文发送出去而已。其中针对该报文的设计进行了一些优化,引入了bit map位图的概念,也算是一个不错的想法。

    剩下的工作就简单了,我们就直接收集金融行业可能出现的数据字段类型,分成128个字段类型,如果没有到128个这么多就先保留一些下来,另外考虑到有些人有特殊的要求,我们规定可以将128个字段中的几个字段你自己来定义其内容,也算是一种扩展了。

    这样,最后我们就得到了ISO8583规范的那张字段描述表了。想要详细的知道每个字段的含义直接对着表看就可以,比较简单。

1、 位图描述如下: 
  位图位置:1 
  格式:定长 
  类型:B16(二进制16位,16*8=128bit) 
  描述: 
  如将位图的第一位设为'1',表示使用扩展位图(128个域),否则表示只使用基本位图(64个域)。 
  如使用某数据域,应在位图中将相应的位设位'1',如使用41域,需将位图的41位设为'1'。 
  选用条件:如使用65到128域,需设位图域第一位为'1'


 2、每个域的定义如下: 
  typedef struct ISO8583 
  { 
    int   bit_flag;      /*域数据类型0 -- string, 1 -- int, 2 -- binary*/ 
    char  *data_name;     /*域名*/ 
    int   length;       /*数据域长度*/ 
    int   length_in_byte;   /*实际长度(如果是变长)*/ 
    int   variable_flag;   /*是否变长标志0:否 2:2位变长, 3:3位变长*/ 
    int   datatyp;      /*0 -- string, 1 -- int, 2 -- binary*/ 
    char  *data;       /*存放具体值*/ 
    int   attribute;     /*保留*/ 

  } ISO8583; 

 3、变长,定长域说明 
  如第二域:域名为主帐号, 
  数据类型为string 
  长度为22(是长长度不得超过此数) 
  是个2位变长域 
  由于是2位变长,在打包时需在数据域前加上数据的实际长度,如为19位,则表示为: 
  19+数据值(即前两位为长度)

  如第三域:域名为处理码, 
  数据类型为string 
  长度为6 
  是个定长域 

  必须填满6位。 

转载自:https://blog.csdn.net/cbacq/article/details/51495562

              https://blog.csdn.net/cbacq/article/details/51495575


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325838054&siteId=291194637