我剛進(jìn)入金融行業(yè)時(shí),就知道了IS08583報文協(xié)議,我想可能我還沒(méi)進(jìn)入這個(gè)行業(yè)都已經(jīng)聽(tīng)過(guò)了,可知ISO8583的影響力有多大了。最初剛接觸它時(shí),確實(shí)對其中的一些細節概念不是很清晰,對有些地方比較迷惑。鑒于此,我想很多同行也必然會(huì )經(jīng)歷同樣得階段,所以我寫(xiě)下本文,以便大家能夠少走一些彎路。同時(shí),我在網(wǎng)上(http://blog.csdn.net/lysheng/archiv.../03/309914.aspx)寫(xiě)下我要寫(xiě)“全面掌握ISO8583報文”和“符合CEN/XFS(即WOSA/XFS)規范的SP編寫(xiě)”兩篇文章時(shí),很多人都詢(xún)問(wèn)我什么時(shí)候能夠寫(xiě)出來(lái),可知許多人是需要了解這方面的知識的,即使我時(shí)間不是很多,也得盡量將這兩篇文章寫(xiě)出來(lái),給需要的人提供一些參考。
如果單純的講IS08583那些字段的定義,我覺(jué)得沒(méi)有什么意思,標準中已經(jīng)對每個(gè)字段解釋的非常詳細了,如果你覺(jué)得理解英文版的ISO8583規范有些困難,網(wǎng)上也有同行為我們翻譯好的中文版ISO8583規范,所以我的目的是達到閱讀本文后能夠對ISO8583知其然,亦知其所以然,使以前基本沒(méi)有接觸它的人也能夠達到掌握ISO8583報文規范。
好了,我們該轉入正題了。
最開(kāi)始時(shí),金融系統只有IBM這些大的公司來(lái)提供設備,象各種主機與終端等。在各個(gè)計算機設備之間,需要交換數據。我們知道數據是通過(guò)網(wǎng)絡(luò )來(lái)傳送的,而在網(wǎng)絡(luò )上傳送的數據都是基于0或1這樣的二進(jìn)制數據,如果沒(méi)有對數據進(jìn)行編碼,則這些數據沒(méi)有人能夠理解,屬于沒(méi)有用的數據。起初的X.25、SDLC以及現在流行的TCP/IP網(wǎng)絡(luò )協(xié)議都提供底層的通訊編碼協(xié)議,它們解決了最底層的通訊問(wèn)題,能夠將一串字符從一個(gè)地方傳送到另一個(gè)地方。但是,僅僅傳送字符串是沒(méi)有太大意義的,怎樣來(lái)解析字符串代表什么內容是非常重要的,否則傳送一些“0123abcd”的字符串也是無(wú)用的亂碼。
讓我們隨著(zhù)時(shí)光回到幾十年前的某個(gè)時(shí)刻,假設我們被推到歷史的舞臺上,由我們來(lái)設計一個(gè)通用報文協(xié)議,來(lái)解決金融系統之間的報文交換,暫且稱(chēng)該協(xié)議叫做ISO8583協(xié)議。此時(shí),技術(shù)是在不斷的前行,當初IBM一支獨秀的局面好像已經(jīng)不妙了,各種大小不一的公司都進(jìn)入金融行業(yè)以求能有所斬獲,呈一片百花齊放的局面。我們怎樣來(lái)設計一個(gè)報文協(xié)議,能夠將這些如雨后春筍般出現的所有公司都納入進(jìn)來(lái),其實(shí)也不是一件很簡(jiǎn)單的事。
我們還是先一步步的來(lái)考慮吧。金融行業(yè)其實(shí)涉及到的數據內容并不是成千上萬(wàn),無(wú)法統計,恰恰相反,是比較少的。我們都可以在心底數得過(guò)來(lái),象交易類(lèi)型、賬號、帳戶(hù)類(lèi)型、密碼、交易金額、交易手續費、日期時(shí)間、商戶(hù)代碼、2磁3磁數據、交易序列號等,把所有能夠總結出來(lái)的都總結起來(lái)不過(guò)100個(gè)左右的數據。那我們可以首先簡(jiǎn)單的設計ISO8583,定義128個(gè)字段,將所有能夠考慮到的類(lèi)似上面提到的“賬號”等金融數據類(lèi)型,按照一個(gè)順序排起來(lái),分別對應128個(gè)字段中的一個(gè)字段。每個(gè)數據類(lèi)型占固定的長(cháng)度,這個(gè)順序和長(cháng)度我們都事先定義好。這樣就簡(jiǎn)單了,要發(fā)送一個(gè)報文時(shí),就將128個(gè)字段按照順序接起來(lái),然后將接起來(lái)的整串數據包發(fā)送出去。
任何金融軟件收到ISO8583包后,直接按照我們定義的規范解包即可,因為整個(gè)報文的128個(gè)字段從哪一位到哪一位代表什么,大家都知道,只要知道你的數據包是ISO8583包即可,我們都已經(jīng)定義好了。比如第1個(gè)字段是“交易類(lèi)型”,長(cháng)度為4位,第2個(gè)字段位是“賬號”,為19位等等。接收方就可以先取4位,再取接著(zhù)的19位,依次類(lèi)推,直到整個(gè)數據包128個(gè)字段都解完為止。
其實(shí)這種做法真是簡(jiǎn)單直接,基本上就可以滿(mǎn)足需要了。不過(guò)我們有幾個(gè)問(wèn)題要思考下:
1、 我怎么知道每個(gè)字段的數據類(lèi)型呢,是數字還是字符?
2、 每個(gè)傳送的報文都把128個(gè)字段都傳過(guò)去,那網(wǎng)絡(luò )帶寬能夠承受得了,有時(shí)候我可能只需要其中5個(gè)字段,結果多收到了123個(gè)無(wú)用的字段。
3、 如果我某些字段的長(cháng)度不固定,屬于變長(cháng)怎么辦,因為你現在解包是當作數據包每個(gè)字段都是固定的,用C語(yǔ)言解包時(shí)直接依靠指針取固定長(cháng)度的一串字符做為一個(gè)字段。
我們來(lái)一一解決這些問(wèn)題。
第一個(gè)問(wèn)題簡(jiǎn)單,我在定義ISO8583時(shí)除了定義每個(gè)字段表示什么,還規定其內容是數字或是字符等即可??紤]可能出現的類(lèi)型不過(guò)有以下幾種:字母、數字、特殊字符、年月日等時(shí)間、二進(jìn)制數據。比如我對128個(gè)字段中的“商戶(hù)類(lèi)型”字段定義其長(cháng)度是15,同時(shí)定義其類(lèi)型為字母。再精細點(diǎn),如果“商戶(hù)類(lèi)型”里面的數據同時(shí)包括數字和字母呢?那我們就定義其類(lèi)型為字母也可,為數字也可,即一個(gè)字段可以同時(shí)屬于多個(gè)類(lèi)型。
第二個(gè)問(wèn)題稍微復雜點(diǎn)。其本質(zhì)就是如果我只傳128個(gè)字段的5個(gè)字段,接收方怎么知道我傳了哪幾個(gè)字段給它了。要是我們把剩下的123全部填成0或其他特殊標識,標明該字段不需要使用?這種處理方法沒(méi)有半點(diǎn)用處,沒(méi)有解決網(wǎng)絡(luò )帶寬的本質(zhì)問(wèn)題,還是要傳128個(gè)字段。
換個(gè)思路,我在報文前面加上個(gè)包頭,包頭里面包含的信息能夠讓別人知道只傳了5個(gè)字段。怎樣設計這個(gè)包頭,可以這樣,我們用16個(gè)字節,即128個(gè)bit(一個(gè)字節等于8bit)來(lái)表示128個(gè)字段中的某個(gè)字段是否存在。每個(gè)bit在計算機的二進(jìn)制里面不是1就是0,如果是1就表示對應的字段在本次報文中存在,如果是0就是不存在。這樣好了,如果別人接收到了ISO8583報文,可以先根據最前面的報文頭,就知道緊接著(zhù)報文頭后面的報文有哪些字段,沒(méi)有哪些字段了。比如,我要發(fā)送5個(gè)字段,分別屬于128個(gè)字段中的第2、3、6、8、9字段,我就可以將128bit的報文頭填成011001011000000000………..,一共128個(gè)bit,后面就全是0了。注意其中第2、3、6、8、9位為1,其他都為0。
有了這個(gè)128bit的報文頭,我們就可以只發(fā)送需要的5個(gè)字段了。怎樣組織報文?先放上這128bit,即16個(gè)字節的頭,然后在頭后面放2、3、6、8、9字段,這些字段緊挨在一起,3和6之間也不需要填上4、5這兩個(gè)字段了。接收方收到這個(gè)報文,它會(huì )根據128bit的報文頭來(lái)解包,它自然知道把第3個(gè)字段取出后,就直接在第3字段的后面取第6個(gè)字段,每個(gè)字段的長(cháng)度在ISO8583里面都定義好了,很輕松就把數據包解出來(lái)了。
這下好了,為了解決上面的第二問(wèn)題,我們只是在報文中增加了16個(gè)字節的數據,就輕松搞定了,我們把這16個(gè)字節稱(chēng)為bit map,即位圖,用來(lái)表示某個(gè)位是否存在。不過(guò)我們再稍微優(yōu)化一下,考慮到很多時(shí)候報文不需要128個(gè)字段這么多,其一半64個(gè)字段都不一定能夠用完。那我可以將報文頭由128bit減到64bit,只有在需要的時(shí)候才把剩下的64bit放到報文里面,這樣報文長(cháng)度不又少了8個(gè)字節嗎?
是個(gè)好主意。我們把ISO8583的128個(gè)字段中最常見(jiàn)的都放到前64個(gè)字段中,那我們可以將處理縮小一倍。這樣我一般發(fā)送報文時(shí)只需發(fā)送64bit,即一個(gè)字節的報文頭,再加上需要的幾個(gè)字段就可以了。如果有些報文用到64到128之間的字段呢?這個(gè)也好辦,我把64bit報文頭的第一位bit用來(lái)代表特殊含義,如果該bit為1,則表示64bit后面跟了剩下的64bit報文頭;如果第一位bit為0,則表示64bit后面沒(méi)有跟剩下的64bit報文頭,直接是128個(gè)字段中的報文了。那們,接收方會(huì )判斷一下報頭的第一個(gè)bit是1還是0,從而知道報文頭是64bit還是128bit了,就可以做相應處理。因為報文頭第二個(gè)64bit屬于有時(shí)候有,所以我們叫它Extended bit map擴展位圖,相應的報文頭最開(kāi)始的64bit我們叫它Primary bit map主位圖。我們直接把擴展位圖固定放到128個(gè)字段的第一個(gè)字段,而主位圖每個(gè)數據包都有,就強制性放在所有128個(gè)字段的前面,并不歸入128個(gè)字段中去。
第三個(gè)問(wèn)題可以考慮這樣解決。比如第2個(gè)字段是“賬號”,是不定長(cháng)的,可能有的銀行賬號是19位,有的是17位等。我們定ISO8583規范時(shí)可以規定第2個(gè)字段是25位,這下足夠將19和17的情況都包含進(jìn)來(lái),但是如果以后出現了30位的怎么辦?那我們現在將字段定為100位。以后超過(guò)100位怎么辦,況且如果你只有19位的賬號,我們定義了100位,那81位的數據不是浪費了網(wǎng)絡(luò )的帶寬??磥?lái)預先定義一個(gè)我們認為比較大的位數是不太好的。
我們這樣,對于第2個(gè)字段“賬號”,在字段的開(kāi)頭加上“賬號”的長(cháng)度。比如賬號是0123456789,一共10位,我們變成100123456789,注意前面多了個(gè)10,表示后面的10位為賬號。如果你接觸過(guò)COM里面的BSTR,應該對這種處理比較熟悉了。接收方收到該字段后,它知道ISO8583規定第2個(gè)字段“賬號”是變長(cháng)的,所以會(huì )先取前面的2位出來(lái),獲取其值,此時(shí)為長(cháng)度,然后根據該長(cháng)度值知道應該拷貝該字段后面哪幾位數據,才是真正的賬號。如果你覺(jué)得長(cháng)度如果只有兩位最多只能表示99位長(cháng),不太夠,我們也定義可以允許前面3位都為長(cháng)度的變長(cháng)字段,這樣就有999位長(cháng),應該夠了吧。在規范里面如果我定義某個(gè)字段的屬性是“LLVAR”,你注意了,其中的LL表示長(cháng)度,VAR表示后面的數據,兩個(gè)LL表示兩位長(cháng),最大是99,如果是三位就是“LLLVAR”,最大是999。這樣看我們定義的ISO8583規范文檔時(shí)直接根據這幾個(gè)字母就理解某個(gè)變長(cháng)字段的意思了。
該解決的幾個(gè)問(wèn)題到這里都解決了,我們來(lái)回顧下自己設計的ISO8583規范。其實(shí)沒(méi)有什么,無(wú)非是把金融行業(yè)可能出現的數據分門(mén)別類(lèi),排好順序,接著(zhù)把它們連接起來(lái),組成一個(gè)報文發(fā)送出去而已。其中針對該報文的設計進(jìn)行了一些優(yōu)化,引入了bit map位圖的概念,也算是一個(gè)不錯的想法。
剩下的工作就簡(jiǎn)單了,我們就直接收集金融行業(yè)可能出現的數據字段類(lèi)型,分成128個(gè)字段類(lèi)型,如果沒(méi)有到128個(gè)這么多就先保留一些下來(lái),另外考慮到有些人有特殊的要求,我們規定可以將128個(gè)字段中的幾個(gè)字段你自己來(lái)定義其內容,也算是一種擴展了。
這樣,最后我們就得到了ISO8583規范的那張字段描述表了。想要詳細的知道每個(gè)字段的含義直接對著(zhù)表看就可以,比較簡(jiǎn)單。
全文完
劉永勝 2005年于迪堡廣州
聯(lián)系客服