8583報文詳解

2021-09-27 07:10:11 字數 3557 閱讀 9714

讓我們隨著時光回到幾十年前的某個時刻,假設我們被推到歷史的舞台上,由我們來設計乙個通用報文協議,來解決金融系統之間的報文交換,暫且稱該協議叫做iso8583協議。此時,技術是在不斷的前行,當初ibm一支獨秀的局面好像已經不妙了,各種大小不一的公司都進入金融行業以求能有所斬獲,呈一片百花齊放的局面。我們怎樣來設計乙個報文協議,能夠將這些如雨後春筍般出現的所有公司都納入進來,其實也不是一件很簡單的事。     

我們還是先一步步的來考慮吧。金融行業其實涉及到的資料內容並不是成千上萬,無法統計,恰恰相反,是比較少的。我們都可以在心底數得過來,象交易型別、帳號、帳戶型別、密碼、交易金額、交易手續費、日期時間、商戶**、2磁3磁資料、交易序列號等,把所有能夠總結出來的都總結起來不過100個左右的資料。那我們可以首先簡單的設計iso8583,定義128個字段,將所有能夠考慮到的類似上面提到的「帳號」等金融資料型別,按照乙個順序排起來,分別對應128個字段中的乙個字段。每個資料型別佔固定的長度,這個順序和長度我們都事先定義好。這樣就簡單了,要傳送乙個報文時,就將128個字段按照順序接起來,然後將接起來的整串資料報傳送出去。      任何金融軟體收到iso8583包後,直接按照我們定義的規範解包即可,因為整個報文的128個字段從哪一位到哪一位代表什麼,大家都知道,只要知道你的資料報是iso8583包即可,我們都已經定義好了。比如第1個字段是「交易型別」,長度為4位,第2個字段位是「帳號」,為19位等等。接收方就可以先取4位,再取接著的19位,依次類推,直到整個資料報128個字段都解完為止。     

其實這種做法真是簡單直接,基本上就可以滿足需要了。不過我們有幾個問題要思考下: 1、 我怎麼知道每個欄位的資料型別呢,是數字還是字元? 2、 每個傳送的報文都把128個字段都傳過去,那網路頻寬能夠承受得了,有時候我可能只需要其中5個字段,結果多收到了123個無用的字段。 3、 如果我某些欄位的長度不固定,屬於變長怎麼辦,因為你現在解包是當作資料報每個欄位都是固定的,用c語言解包時直接依靠指標取固定長度的一串字元做為乙個字段。      我們來一一解決這些問題。     

第乙個問題簡單,我在定義iso8583時除了定義每個字段表示什麼,還規定其內容是數字或是字元等即可。考慮可能出現的型別不過有以下幾種:字母、數字、特殊字元、年月日等時間、二進位制資料。比如我對128個字段中的「商戶型別」字段定義其長度是15,同時定義其型別為字母。再精細點,如果「商戶型別」裡面的資料同時包括數字和字母呢?那我們就定義其型別為字母也可,為數字也可,即乙個字段可以同時屬於多個型別。     

第二個問題稍微複雜點。其本質就是如果我只傳128個字段的5個字段,接收方怎麼知道我傳了哪幾個欄位給它了。要是我們把剩下的123全部填成0或其他特殊標識,標明該字段不需要使用?這種處理方法沒有半點用處,沒有解決網路頻寬的本質問題,還是要傳128個字段。 2 4 16 2 8 256     換個思路,我在報文前面加上個包頭,包頭裡面包含的資訊能夠讓別人知道只傳了5個字段。怎樣設計這個包頭,可以這樣,我們用16個位元組,即128個bit(乙個位元組等於8bit)來表示128個字段中的某個字段是否存在。每個bit在計算機的二進位制裡面不是1就是0,如果是1就表示對應的字段在本次報文中存在,如果是0就是不存在。這樣好了,如果別人接收到了iso8583報文,可以先根據最前面的報文頭,就知道緊接著報文頭後面的報文有哪些字段,沒有哪些欄位了。比如,我要傳送5個字段,分別屬於128個字段中的第2、3、6、8、9欄位,我就可以將128bit的報文頭填成011001011000000000………..,一共128個bit,後面就全是0了。注意其中第2、3、6、8、9位為1,其他都為0。     

有了這個128bit的報文頭,我們就可以只傳送需要的5個字段了。怎樣組織報文?先放上這128bit,即2個位元組的頭,然後在頭後面放2、3、6、8、9欄位,這些字段緊挨在一起,3和6之間也不需要填上4、5這兩個欄位了。接收方收到這個報文,它會根據128bit的報文頭來解包,它自然知道把第3個字段取出後,就直接在第3欄位的後面取第6個字段,每個欄位的長度在iso8583裡面都定義好了,很輕鬆就把資料報解出來了。     

這下好了,為了解決上面的第二問題,我們只是在報文中增加了2個位元組的資料,就輕鬆搞定了,我們把這2個位元組稱為bit map,即位圖,用來表示某個位是否存在。不過我們再稍微優化一下,考慮到很多時候報文不需要128個字段這麼多,其一半64個字段都不一定能夠用完。那我可以將報文頭由128bit減到64bit,只有在需要的時候才把剩下的64bit放到報文裡面,這樣報文長度不又少了1個位元組嗎?     

是個好主意。我們把iso8583的128個字段中最常見的都放到前64個字段中,那我們可以將處理縮小一倍。這樣我一般傳送報文時只需傳送64bit,即乙個位元組的報文頭,再加上需要的幾個欄位就可以了。如果有些報文用到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規範的那張欄位描述表了。想要詳細的知道每個欄位的含義直接對著表看就可以,比較簡單。

8583報文筆記

參考 資料型別 字母 數字 特殊字元 年月日等時間 二進位制資料 位圖 bit map 前16位元組 即128位 表示後面哪些欄位是有資料的 0表示沒有資料,1表示有資料 後面的資料區域直接中間沒有資料 比如 第2 3 6 8 9欄位有資料,可以這樣表示 011001011000.128位 後面的資...

8583報文相關(知識小結)

1 開頭第乙個位元組為開始標識,後面兩個位元組為再後面的資料長度 符號為位元組,可能要從16位折算為10位,也可能為直接顯示,目前來看公司是直接顯示 和結尾2個位元組用於校驗 2 在tpdu 5位元組 和報文頭 6位元組 之後的是訊息型別 2位元組 訊息型別可在報文格式的 請求一欄 看到對應的 3 ...

全面掌握ISO8583報文

我剛進入金融行業時,就知道了is08583報文協議,我想可能我還沒進入這個行業都已經聽過了,可知iso8583的影響力有多大了。最初剛接觸它時,確實對其中的一些細節概念不是很清晰,對有些地方比較迷惑。鑑於此,我想很多同行也必然會經歷同樣得階段,所以我寫下本文,以便大家能夠少走一些彎路。同時,我在網上...