POS协议解析
單純的講IS08583那些字段的定義,我覺得沒有什么意思,標(biāo)準(zhǔn)中已經(jīng)對每個(gè)字段解釋?的非常詳細(xì)了,如果你覺得理解英文版的ISO8583規(guī)范有些困難,網(wǎng)上也有同行為我們翻譯好的中文版ISO8583規(guī)范,所以我的目的是達(dá)到閱讀本文后?能夠?qū)SO8583知其然,亦知其所以然,使以前基本沒有接觸它的人也能夠達(dá)到掌握ISO8583報(bào)文規(guī)范。?好了,我們該轉(zhuǎn)入正題了。?最開始時(shí),金融系統(tǒng)只有IBM這些大的公司來提供設(shè)備,象各種主機(jī)與終端等。在各個(gè)計(jì)算機(jī)設(shè)備之間,需要交換數(shù)據(jù)。我們知道數(shù)據(jù)是通過網(wǎng)絡(luò)來傳送的,而在網(wǎng)絡(luò)上傳送的數(shù)據(jù)都是基于0或1這樣的二進(jìn)制數(shù)據(jù),如果沒有對數(shù)據(jù)進(jìn)行編碼,則這些數(shù)據(jù)沒有人能夠理解,屬于沒有用的數(shù)據(jù)。起初的X.25、SDLC以及現(xiàn)在流行的TCP/IP網(wǎng)絡(luò)協(xié)議都提供底層的通訊編碼協(xié)議,它們解決了最底層的通訊問題,能夠?qū)⒁淮址麖囊粋€(gè)地方傳送到另一個(gè)地方。但是,僅僅傳送字符串是沒有太大意義的,怎樣來解析字符串代表什么內(nèi)容是非常重要的,否則傳送一些“0123abcd”的字符串也是無用的亂碼。?讓我們隨著時(shí)光回到幾十年前的某個(gè)時(shí)刻,假設(shè)我們被推到歷史的舞臺上,由我們來設(shè)計(jì)一個(gè)通用報(bào)文協(xié)議,來解決金融系統(tǒng)之間的報(bào)文交換,暫且稱該協(xié)議叫做ISO8583協(xié)議。此時(shí),技術(shù)是在不斷的前行,當(dāng)初IBM一支獨(dú)秀的局面好像已經(jīng)不妙了,各種大小不一的公司都進(jìn)入金融行業(yè)以求能有所斬獲,呈一片百花齊放的局面。我們怎樣來設(shè)計(jì)一個(gè)報(bào)文協(xié)議,能夠?qū)⑦@些如雨后春筍般出現(xiàn)的所有公司都納入進(jìn)來,其實(shí)也不是一件很簡單的事。?我們還是先一步步的來考慮吧。金融行業(yè)其實(shí)涉及到的數(shù)據(jù)內(nèi)容并不是成千上萬,無法統(tǒng)計(jì),恰恰相反,是比較少的。我們都可以在心底數(shù)得過來,象交易類型、帳號、帳戶類型、密碼、交易金額、交易手續(xù)費(fèi)、日期時(shí)間、商戶代碼、2磁3磁數(shù)據(jù)、交易序列號等,把所有能夠總結(jié)出來的都總結(jié)起來不過100個(gè)左右的數(shù)據(jù)。那我們可以首先簡單的設(shè)計(jì)ISO8583,定義128個(gè)字段,將所有能夠考慮到的類似上面提到的“帳號”等金融數(shù)據(jù)類型,按照一個(gè)順序排起來,分別對應(yīng)128個(gè)字段中的一個(gè)字段。每個(gè)數(shù)據(jù)類型占固定的長度,這個(gè)順序和長度我們都事先定義好。這樣就簡單了,要發(fā)送一個(gè)報(bào)文時(shí),就將128個(gè)字段按照順序接起來,然后將接起來的整串?dāng)?shù)據(jù)包發(fā)送出去。?任何金融軟件收到ISO8583包后,直接按照我們定義的規(guī)范解包即可,因?yàn)檎麄€(gè)報(bào)文的128個(gè)字段從哪一位到哪一位代表什么,大家都知道,只要知道你的數(shù)據(jù)包是ISO8583包即可,我們都已經(jīng)定義好了。比如第1個(gè)字段是“交易類型”,長度為4位,第2個(gè)字段位是“帳號”,為19位等等。接收方就可以先取4位,再取接著的19位,依次類推,直到整個(gè)數(shù)據(jù)包128個(gè)字段都解完為止。?其實(shí)這種做法真是簡單直接,基本上就可以滿足需要了。不過我們有幾個(gè)問題要思考下:
1、?我怎么知道每個(gè)字段的數(shù)據(jù)類型呢,是數(shù)字還是字符?
2、?每個(gè)傳送的報(bào)文都把128個(gè)字段都傳過去,那網(wǎng)絡(luò)帶寬能夠承受得了,有時(shí)候我可能只需要其中5個(gè)字段,結(jié)果多收到了123個(gè)無用的字段。
3、?如果我某些字段的長度不固定,屬于變長怎么辦,因?yàn)槟悻F(xiàn)在解包是當(dāng)作數(shù)據(jù)包每個(gè)字段都是固定的,用C語言解包時(shí)直接依靠指針取固定長度的一串字符做為一個(gè)?字段。?我們來一一解決這些問題。?第一個(gè)問題簡單,我在定義ISO8583時(shí)除了定義每個(gè)字段表示什么,還規(guī)定其內(nèi)容是數(shù)字或是字符等即可??紤]可能出現(xiàn)的類型不過有以下幾種:字母、數(shù)?字、特殊字符、年月日等時(shí)間、二進(jìn)制數(shù)據(jù)。比如我對128個(gè)字段中的“商戶類型”字段定義其長度是15,同時(shí)定義其類型為字母。再精細(xì)點(diǎn),如果“商戶類型”里面的數(shù)據(jù)同時(shí)包括數(shù)字和字母呢?那我們就定義其類型為字母也可,為數(shù)字也可,即一個(gè)字段可以同時(shí)屬于多個(gè)類型。?第二個(gè)問題稍微復(fù)雜點(diǎn)。其本質(zhì)就是如果我只傳128個(gè)字段的5個(gè)字段,接收方怎么知道我傳了哪幾個(gè)字段給它了。要是我們把剩下的123全部填成0或其他特殊標(biāo)識,標(biāo)明該字段不需要使用?這種處理方法沒有半點(diǎn)用處,沒有解決網(wǎng)絡(luò)帶寬的本質(zhì)問題,還是要傳128個(gè)字段。?換個(gè)思路,我在報(bào)文前面加上個(gè)包頭,包頭里面包含的信息能夠讓別人知道只傳了5個(gè)字段。怎樣設(shè)計(jì)這個(gè)包頭,可以這樣,我?們用16個(gè)字節(jié),即128個(gè)bit(一個(gè)字節(jié)等于8bit)來表示128個(gè)字段中的某個(gè)字段是否存在。每個(gè)bit在計(jì)算機(jī)的二進(jìn)制里面不是1就是0,如果?是1就表示對應(yīng)的字段在本次報(bào)文中存在,如果是0就是不存在。這樣好了,如果別人接收到了ISO8583報(bào)文,可以先根據(jù)最前面的報(bào)文頭,就知道緊接著報(bào)?文頭后面的報(bào)文有哪些字段,沒有哪些字段了。比如,我要發(fā)送5個(gè)字段,分別屬于128個(gè)字段中的第2、3、6、8、9字段,我就可以將128bit的報(bào)文?頭填成011001011000000000………..,一共128個(gè)bit,后面就全是0了。注意其中第2、3、6、8、9位為1,其他都為0。?有了這個(gè)128bit的報(bào)文頭,我們就可以只發(fā)送需要的5個(gè)字段了。怎樣組織報(bào)文?先放上這128bit,即16個(gè)字節(jié)的頭,然后在頭后面放2、3、6、?8、9字段,這些字段緊挨在一起,3和6之間也不需要填上4、5這兩個(gè)字段了。接收方收到這個(gè)報(bào)文,它會根據(jù)128bit的報(bào)文頭來解包,它自然知道把第?3個(gè)字段取出后,就直接在第3字段的后面取第6個(gè)字段,每個(gè)字段的長度在ISO8583里面都定義好了,很輕松就把數(shù)據(jù)包解出來了。?這下好了,為了解決上面的第二問題,我們只是在報(bào)文中增加了16個(gè)字節(jié)的數(shù)據(jù),就輕松搞定了,我們把這16個(gè)字節(jié)稱為bit?map,即位圖,用來表示某個(gè)位是否存在。不過我們再稍微優(yōu)化一下,考慮到很多時(shí)候報(bào)文不需要128個(gè)字段這么多,其一半64個(gè)字段都不一定能夠用完。那?我可以將報(bào)文頭由128bit減到64bit,只有在需要的時(shí)候才把剩下的64bit放到報(bào)文里面,這樣報(bào)文長度不又少了8個(gè)字節(jié)嗎??是個(gè)好主意。我們把ISO8583的128個(gè)字段中最常見的都放到前64個(gè)字段中,那我們可以將處理縮小一倍。這樣我一般發(fā)送報(bào)文時(shí)只需發(fā)送64bit,?即一個(gè)字節(jié)的報(bào)文頭,再加上需要的幾個(gè)字段就可以了。如果有些報(bào)文用到64到128之間的字段呢?這個(gè)也好辦,我把64bit報(bào)文頭的第一位bit用來代?表特殊含義,如果該bit為1,則表示64bit后面跟了剩下的64bit報(bào)文頭;如果第一位bit為0,則表示64bit后面沒有跟剩下的64bit報(bào)?文頭,直接是128個(gè)字段中的報(bào)文了。那們,接收方會判斷一下報(bào)頭的第一個(gè)bit是1還是0,從而知道報(bào)文頭是64bit還是128bit了,就可以做相?應(yīng)處理。因?yàn)閳?bào)文頭第二個(gè)64bit屬于有時(shí)候有,所以我們叫它Extended?bit?map擴(kuò)展位圖,相應(yīng)的報(bào)文頭最開始的64bit我們叫它Primary?bit?map主位圖。我們直接把擴(kuò)展位圖固定放到128個(gè)字段的第一個(gè)字段,而主位圖每個(gè)數(shù)據(jù)包都有,就強(qiáng)制性放在所有128個(gè)字段的前面,并不歸入128個(gè)字?段中去。?第三個(gè)問題可以考慮這樣解決。比如第2個(gè)字段是“帳號”,是不定長的,可能有的銀行帳號是19位,有的是17位等。我們定ISO8583規(guī)范時(shí)可以規(guī)定第?2個(gè)字段是25位,這下足夠?qū)?9和17的情況都包含進(jìn)來,但是如果以后出現(xiàn)了30位的怎么辦?那我們現(xiàn)在將字段定為100位。以后超過100位怎么辦,?況且如果你只有19位的帳號,我們定義了100位,那81位的數(shù)據(jù)不是浪費(fèi)了網(wǎng)絡(luò)的帶寬??磥眍A(yù)先定義一個(gè)我們認(rèn)為比較大的位數(shù)是不太好的。
我們這樣,對于第2個(gè)字段“帳號”,在字段的開頭加上“帳號”的長度。比如帳號是0123456789,一共10位,我們變成100123456789,?注意前面多了個(gè)10,表示后面的10位為帳號。如果你接觸過COM里面的BSTR,應(yīng)該對這種處理比較熟悉了。接收方收到該字段后,它知道ISO8583?規(guī)定第2個(gè)字段“帳號”是變長的,所以會先取前面的2位出來,獲取其值,此時(shí)為長度,然后根據(jù)該長度值知道應(yīng)該拷貝該字段后面哪幾位數(shù)據(jù),才是真正的帳?號。如果你覺得長度如果只有兩位最多只能表示99位長,不太夠,我們也定義可以允許前面3位都為長度的變長字段,這樣就有999位長,應(yīng)該夠了吧。在規(guī)范?里面如果我定義某個(gè)字段的屬性是“LLVAR”,你注意了,其中的LL表示長度,VAR表示后面的數(shù)據(jù),兩個(gè)LL表示兩位長,最大是99,如果是三位就是?“LLLVAR”,最大是999。這樣看我們定義的ISO8583規(guī)范文檔時(shí)直接根據(jù)這幾個(gè)字母就理解某個(gè)變長字段的意思了。?該解決的幾個(gè)問題到這里都解決了,我們來回顧下自己設(shè)計(jì)的ISO8583規(guī)范。其實(shí)沒有什么,無非是把金融行業(yè)可能出現(xiàn)的數(shù)據(jù)分門別類,排好順序,接著把?它們連接起來,組成一個(gè)報(bào)文發(fā)送出去而已。其中針對該報(bào)文的設(shè)計(jì)進(jìn)行了一些優(yōu)化,引入了bit?map位圖的概念,也算是一個(gè)不錯(cuò)的想法。?剩下的工作就簡單了,我們就直接收集金融行業(yè)可能出現(xiàn)的數(shù)據(jù)字段類型,分成128個(gè)字段類型,如果沒有到128個(gè)這么多就先保留一些下來,另外考慮到有些?人有特殊的要求,我們規(guī)定可以將128個(gè)字段中的幾個(gè)字段你自己來定義其內(nèi)容,也算是一種擴(kuò)展了。?這樣,最后我們就得到了ISO8583規(guī)范的那張字段描述表了。想要詳細(xì)的知道每個(gè)字段的含義直接對著表看就可以,比較簡單
附個(gè)樣例解析 ISO8583報(bào)文如下(十六進(jìn)制表示法):
60?00?03?00?00?60?31?00?31?07?30?02?00?30?20?04?C0?20?C0?98?11?00?00?00?00?00?00?00?00?01?00?03?49?02?10?00?12?30?62?25?82?21?12?99?63?01?5D?15?11?10?10?00?00?35?36?38?35?32?33?31?34?32?33?35?32?31?34?35?32?36?38?35?39?32?33?36?31?35?36?C6?24?83?4D?36?7E?9E?9E?20?00?00?00?00?00?00?00?00?13?22?00?00?08?00?05?00?36?37?41?32?32?39?39?41
第一步
POS終端上送POS中心的消息報(bào)文結(jié)構(gòu)包括TPDU、報(bào)文頭和應(yīng)用數(shù)據(jù)三部分:
——TPDU說明:長度為10個(gè)字節(jié),壓縮時(shí)用BCD碼表示為5個(gè)字節(jié)長度的數(shù)值。
——報(bào)文頭說明:總長度為12字節(jié),壓縮時(shí)用BCD碼表示為6個(gè)字節(jié)長度的數(shù)值。?
——應(yīng)用數(shù)據(jù)說明:一般長度都是4個(gè)字節(jié),壓縮時(shí)用BCD碼表示為2個(gè)字節(jié)的長度的數(shù)值。
所以上述報(bào)文中前五個(gè)字節(jié)為TPDU,即60?00?03?00?00
報(bào)文頭占用六個(gè)字節(jié),即?60?31?00?31?07?30
應(yīng)用數(shù)據(jù)占用2個(gè)字節(jié),即?02?00?也就是"0200"
——0200金融類請求消息:
● ?POS查詢請求。
● ?POS消費(fèi)請求。
● ?POS消費(fèi)撤銷請求。
● ?POS預(yù)授權(quán)完成(請求)請求。
● ?POS預(yù)授權(quán)完成撤銷請求。
● ?電子現(xiàn)金脫機(jī)消費(fèi)請求。
● ?分期付款消費(fèi)請求。
● ?分期付款消費(fèi)撤銷請求。
● ?基于PBOC電子錢包/電子現(xiàn)金的IC圈存類交易請求。
● ?磁條卡現(xiàn)金充值請求。
第二步
分析位圖:
首先取第十四個(gè)字節(jié),即0x30?,轉(zhuǎn)化為二進(jìn)制為0011?0000,在該字節(jié)的第一位為0(從左往右)表示當(dāng)前報(bào)文中只需包括64個(gè)域,也就是從當(dāng)前字節(jié)開始連續(xù)8個(gè)字節(jié)為位圖(包括當(dāng)前字節(jié)),如要包括128個(gè)域,該位為1。
現(xiàn)在進(jìn)入關(guān)鍵的位圖分析,現(xiàn)在我們?nèi)〉搅吮硎疚粓D的8個(gè)字節(jié)即30?20?04?C0?20?C0?98?11,轉(zhuǎn)為二進(jìn)制為
00110000?00100000?00000100?11000000?00100000?11000000?10011000?00010001
位圖中為1的位置即代表相應(yīng)的域,在上面的二進(jìn)制位中從左往右有第3位、第4位、第11位、第22位、第25位、第26位、第35位、第41位、第42位、第49位、第52位、第53位、第60位、第64位。
下面開始這些域中的數(shù)據(jù),首先分析3域,3域?yàn)榻灰滋幚泶a,壓縮成BCD碼后占定長3個(gè)字節(jié),我們從位圖所占的8個(gè)字節(jié)后開始連續(xù)取3個(gè)字節(jié),即?00?00?00,解壓后即為“000000”,具體代表含義這里就不敘述了。
4域?yàn)榻灰捉痤~,壓縮成BCD碼后占定長6個(gè)字節(jié),同理取6個(gè)字節(jié),即00?00?00?00?00?01,也就是金額0.01元,具體轉(zhuǎn)換參考銀聯(lián)規(guī)范。
11域?yàn)槭芸ǚ较到y(tǒng)跟蹤號(流水號),壓縮成BCD碼占定長3個(gè)字節(jié),同理取3個(gè)字節(jié),即00?03?49,即000349。
22域?yàn)榉?wù)點(diǎn)輸入方式碼,壓縮成BCD碼占定長2個(gè)字節(jié),同理取2個(gè)字節(jié),即02?10,由于22域本身只占3個(gè)字節(jié),壓縮時(shí)左靠,右補(bǔ)0,所以轉(zhuǎn)換為“021”,具體含義不再敘述。
25域?yàn)榉?wù)點(diǎn)條件碼,壓縮成BCD碼占定長1個(gè)字節(jié),同理取1個(gè)字節(jié),即00,轉(zhuǎn)換為“00”,“00”代表正常提交。
26域?yàn)榉?wù)點(diǎn)PIN獲取碼,壓縮成BCD碼占定長1個(gè)字節(jié),同理取1個(gè)字節(jié),即12,轉(zhuǎn)換為“12”,表示服務(wù)點(diǎn)設(shè)備所允許輸入的個(gè)人密碼明文的最大長度為12。
解下來的35域由于不是定長,所以處理方法不同,先取一個(gè)字節(jié),即30,轉(zhuǎn)換為“30”,表示第二磁道的數(shù)據(jù)占用30個(gè)字節(jié),取連續(xù)15個(gè)字節(jié)即62?25?82?21?12?99?63?01?5D?15?11?10?10?00?00,這里不對這串?dāng)?shù)據(jù)進(jìn)行說明了。
41域?yàn)槭芸C(jī)終端標(biāo)識碼,占8個(gè)字節(jié)的定長域,取35?36?38?35?32?33?31?34。
42域?yàn)槭芸ǚ綐?biāo)識碼,占15個(gè)字節(jié)的定長域,取32?33?35?32?31?34?35?32?36?38?35?39?32?33?36。
49域?yàn)榻灰棕泿糯a,占3個(gè)字節(jié)的定長域,取31?35?36。
52域?yàn)閭€(gè)人標(biāo)識碼數(shù)據(jù),占8個(gè)字節(jié)的定長二進(jìn)制數(shù)域,取C6?24?83?4D?36?7E?9E?9E。
53域?yàn)榘踩刂菩畔?#xff0c;壓縮成BCD碼占8個(gè)字節(jié)定長域,取20?00?00?00?00?00?00?00。
60域?yàn)樽远x域,為不定長域,先取長度(壓縮成BCD碼占兩個(gè)字節(jié)),即00?13,轉(zhuǎn)換為13即占60域占13個(gè)字節(jié),壓縮成BCD碼占7個(gè)字節(jié),取22?00?00?08?00?05?00。
64域?yàn)閳?bào)文鑒別碼,占定長8個(gè)字節(jié),取最后八個(gè)字節(jié)36?37?41?32?32?39?39?41。
1、?我怎么知道每個(gè)字段的數(shù)據(jù)類型呢,是數(shù)字還是字符?
2、?每個(gè)傳送的報(bào)文都把128個(gè)字段都傳過去,那網(wǎng)絡(luò)帶寬能夠承受得了,有時(shí)候我可能只需要其中5個(gè)字段,結(jié)果多收到了123個(gè)無用的字段。
3、?如果我某些字段的長度不固定,屬于變長怎么辦,因?yàn)槟悻F(xiàn)在解包是當(dāng)作數(shù)據(jù)包每個(gè)字段都是固定的,用C語言解包時(shí)直接依靠指針取固定長度的一串字符做為一個(gè)?字段。?我們來一一解決這些問題。?第一個(gè)問題簡單,我在定義ISO8583時(shí)除了定義每個(gè)字段表示什么,還規(guī)定其內(nèi)容是數(shù)字或是字符等即可??紤]可能出現(xiàn)的類型不過有以下幾種:字母、數(shù)?字、特殊字符、年月日等時(shí)間、二進(jìn)制數(shù)據(jù)。比如我對128個(gè)字段中的“商戶類型”字段定義其長度是15,同時(shí)定義其類型為字母。再精細(xì)點(diǎn),如果“商戶類型”里面的數(shù)據(jù)同時(shí)包括數(shù)字和字母呢?那我們就定義其類型為字母也可,為數(shù)字也可,即一個(gè)字段可以同時(shí)屬于多個(gè)類型。?第二個(gè)問題稍微復(fù)雜點(diǎn)。其本質(zhì)就是如果我只傳128個(gè)字段的5個(gè)字段,接收方怎么知道我傳了哪幾個(gè)字段給它了。要是我們把剩下的123全部填成0或其他特殊標(biāo)識,標(biāo)明該字段不需要使用?這種處理方法沒有半點(diǎn)用處,沒有解決網(wǎng)絡(luò)帶寬的本質(zhì)問題,還是要傳128個(gè)字段。?換個(gè)思路,我在報(bào)文前面加上個(gè)包頭,包頭里面包含的信息能夠讓別人知道只傳了5個(gè)字段。怎樣設(shè)計(jì)這個(gè)包頭,可以這樣,我?們用16個(gè)字節(jié),即128個(gè)bit(一個(gè)字節(jié)等于8bit)來表示128個(gè)字段中的某個(gè)字段是否存在。每個(gè)bit在計(jì)算機(jī)的二進(jìn)制里面不是1就是0,如果?是1就表示對應(yīng)的字段在本次報(bào)文中存在,如果是0就是不存在。這樣好了,如果別人接收到了ISO8583報(bào)文,可以先根據(jù)最前面的報(bào)文頭,就知道緊接著報(bào)?文頭后面的報(bào)文有哪些字段,沒有哪些字段了。比如,我要發(fā)送5個(gè)字段,分別屬于128個(gè)字段中的第2、3、6、8、9字段,我就可以將128bit的報(bào)文?頭填成011001011000000000………..,一共128個(gè)bit,后面就全是0了。注意其中第2、3、6、8、9位為1,其他都為0。?有了這個(gè)128bit的報(bào)文頭,我們就可以只發(fā)送需要的5個(gè)字段了。怎樣組織報(bào)文?先放上這128bit,即16個(gè)字節(jié)的頭,然后在頭后面放2、3、6、?8、9字段,這些字段緊挨在一起,3和6之間也不需要填上4、5這兩個(gè)字段了。接收方收到這個(gè)報(bào)文,它會根據(jù)128bit的報(bào)文頭來解包,它自然知道把第?3個(gè)字段取出后,就直接在第3字段的后面取第6個(gè)字段,每個(gè)字段的長度在ISO8583里面都定義好了,很輕松就把數(shù)據(jù)包解出來了。?這下好了,為了解決上面的第二問題,我們只是在報(bào)文中增加了16個(gè)字節(jié)的數(shù)據(jù),就輕松搞定了,我們把這16個(gè)字節(jié)稱為bit?map,即位圖,用來表示某個(gè)位是否存在。不過我們再稍微優(yōu)化一下,考慮到很多時(shí)候報(bào)文不需要128個(gè)字段這么多,其一半64個(gè)字段都不一定能夠用完。那?我可以將報(bào)文頭由128bit減到64bit,只有在需要的時(shí)候才把剩下的64bit放到報(bào)文里面,這樣報(bào)文長度不又少了8個(gè)字節(jié)嗎??是個(gè)好主意。我們把ISO8583的128個(gè)字段中最常見的都放到前64個(gè)字段中,那我們可以將處理縮小一倍。這樣我一般發(fā)送報(bào)文時(shí)只需發(fā)送64bit,?即一個(gè)字節(jié)的報(bào)文頭,再加上需要的幾個(gè)字段就可以了。如果有些報(bào)文用到64到128之間的字段呢?這個(gè)也好辦,我把64bit報(bào)文頭的第一位bit用來代?表特殊含義,如果該bit為1,則表示64bit后面跟了剩下的64bit報(bào)文頭;如果第一位bit為0,則表示64bit后面沒有跟剩下的64bit報(bào)?文頭,直接是128個(gè)字段中的報(bào)文了。那們,接收方會判斷一下報(bào)頭的第一個(gè)bit是1還是0,從而知道報(bào)文頭是64bit還是128bit了,就可以做相?應(yīng)處理。因?yàn)閳?bào)文頭第二個(gè)64bit屬于有時(shí)候有,所以我們叫它Extended?bit?map擴(kuò)展位圖,相應(yīng)的報(bào)文頭最開始的64bit我們叫它Primary?bit?map主位圖。我們直接把擴(kuò)展位圖固定放到128個(gè)字段的第一個(gè)字段,而主位圖每個(gè)數(shù)據(jù)包都有,就強(qiáng)制性放在所有128個(gè)字段的前面,并不歸入128個(gè)字?段中去。?第三個(gè)問題可以考慮這樣解決。比如第2個(gè)字段是“帳號”,是不定長的,可能有的銀行帳號是19位,有的是17位等。我們定ISO8583規(guī)范時(shí)可以規(guī)定第?2個(gè)字段是25位,這下足夠?qū)?9和17的情況都包含進(jìn)來,但是如果以后出現(xiàn)了30位的怎么辦?那我們現(xiàn)在將字段定為100位。以后超過100位怎么辦,?況且如果你只有19位的帳號,我們定義了100位,那81位的數(shù)據(jù)不是浪費(fèi)了網(wǎng)絡(luò)的帶寬??磥眍A(yù)先定義一個(gè)我們認(rèn)為比較大的位數(shù)是不太好的。
我們這樣,對于第2個(gè)字段“帳號”,在字段的開頭加上“帳號”的長度。比如帳號是0123456789,一共10位,我們變成100123456789,?注意前面多了個(gè)10,表示后面的10位為帳號。如果你接觸過COM里面的BSTR,應(yīng)該對這種處理比較熟悉了。接收方收到該字段后,它知道ISO8583?規(guī)定第2個(gè)字段“帳號”是變長的,所以會先取前面的2位出來,獲取其值,此時(shí)為長度,然后根據(jù)該長度值知道應(yīng)該拷貝該字段后面哪幾位數(shù)據(jù),才是真正的帳?號。如果你覺得長度如果只有兩位最多只能表示99位長,不太夠,我們也定義可以允許前面3位都為長度的變長字段,這樣就有999位長,應(yīng)該夠了吧。在規(guī)范?里面如果我定義某個(gè)字段的屬性是“LLVAR”,你注意了,其中的LL表示長度,VAR表示后面的數(shù)據(jù),兩個(gè)LL表示兩位長,最大是99,如果是三位就是?“LLLVAR”,最大是999。這樣看我們定義的ISO8583規(guī)范文檔時(shí)直接根據(jù)這幾個(gè)字母就理解某個(gè)變長字段的意思了。?該解決的幾個(gè)問題到這里都解決了,我們來回顧下自己設(shè)計(jì)的ISO8583規(guī)范。其實(shí)沒有什么,無非是把金融行業(yè)可能出現(xiàn)的數(shù)據(jù)分門別類,排好順序,接著把?它們連接起來,組成一個(gè)報(bào)文發(fā)送出去而已。其中針對該報(bào)文的設(shè)計(jì)進(jìn)行了一些優(yōu)化,引入了bit?map位圖的概念,也算是一個(gè)不錯(cuò)的想法。?剩下的工作就簡單了,我們就直接收集金融行業(yè)可能出現(xiàn)的數(shù)據(jù)字段類型,分成128個(gè)字段類型,如果沒有到128個(gè)這么多就先保留一些下來,另外考慮到有些?人有特殊的要求,我們規(guī)定可以將128個(gè)字段中的幾個(gè)字段你自己來定義其內(nèi)容,也算是一種擴(kuò)展了。?這樣,最后我們就得到了ISO8583規(guī)范的那張字段描述表了。想要詳細(xì)的知道每個(gè)字段的含義直接對著表看就可以,比較簡單
附個(gè)樣例解析 ISO8583報(bào)文如下(十六進(jìn)制表示法):
60?00?03?00?00?60?31?00?31?07?30?02?00?30?20?04?C0?20?C0?98?11?00?00?00?00?00?00?00?00?01?00?03?49?02?10?00?12?30?62?25?82?21?12?99?63?01?5D?15?11?10?10?00?00?35?36?38?35?32?33?31?34?32?33?35?32?31?34?35?32?36?38?35?39?32?33?36?31?35?36?C6?24?83?4D?36?7E?9E?9E?20?00?00?00?00?00?00?00?00?13?22?00?00?08?00?05?00?36?37?41?32?32?39?39?41
第一步
POS終端上送POS中心的消息報(bào)文結(jié)構(gòu)包括TPDU、報(bào)文頭和應(yīng)用數(shù)據(jù)三部分:
——TPDU說明:長度為10個(gè)字節(jié),壓縮時(shí)用BCD碼表示為5個(gè)字節(jié)長度的數(shù)值。
——報(bào)文頭說明:總長度為12字節(jié),壓縮時(shí)用BCD碼表示為6個(gè)字節(jié)長度的數(shù)值。?
——應(yīng)用數(shù)據(jù)說明:一般長度都是4個(gè)字節(jié),壓縮時(shí)用BCD碼表示為2個(gè)字節(jié)的長度的數(shù)值。
所以上述報(bào)文中前五個(gè)字節(jié)為TPDU,即60?00?03?00?00
報(bào)文頭占用六個(gè)字節(jié),即?60?31?00?31?07?30
應(yīng)用數(shù)據(jù)占用2個(gè)字節(jié),即?02?00?也就是"0200"
——0200金融類請求消息:
● ?POS查詢請求。
● ?POS消費(fèi)請求。
● ?POS消費(fèi)撤銷請求。
● ?POS預(yù)授權(quán)完成(請求)請求。
● ?POS預(yù)授權(quán)完成撤銷請求。
● ?電子現(xiàn)金脫機(jī)消費(fèi)請求。
● ?分期付款消費(fèi)請求。
● ?分期付款消費(fèi)撤銷請求。
● ?基于PBOC電子錢包/電子現(xiàn)金的IC圈存類交易請求。
● ?磁條卡現(xiàn)金充值請求。
第二步
分析位圖:
首先取第十四個(gè)字節(jié),即0x30?,轉(zhuǎn)化為二進(jìn)制為0011?0000,在該字節(jié)的第一位為0(從左往右)表示當(dāng)前報(bào)文中只需包括64個(gè)域,也就是從當(dāng)前字節(jié)開始連續(xù)8個(gè)字節(jié)為位圖(包括當(dāng)前字節(jié)),如要包括128個(gè)域,該位為1。
現(xiàn)在進(jìn)入關(guān)鍵的位圖分析,現(xiàn)在我們?nèi)〉搅吮硎疚粓D的8個(gè)字節(jié)即30?20?04?C0?20?C0?98?11,轉(zhuǎn)為二進(jìn)制為
00110000?00100000?00000100?11000000?00100000?11000000?10011000?00010001
位圖中為1的位置即代表相應(yīng)的域,在上面的二進(jìn)制位中從左往右有第3位、第4位、第11位、第22位、第25位、第26位、第35位、第41位、第42位、第49位、第52位、第53位、第60位、第64位。
下面開始這些域中的數(shù)據(jù),首先分析3域,3域?yàn)榻灰滋幚泶a,壓縮成BCD碼后占定長3個(gè)字節(jié),我們從位圖所占的8個(gè)字節(jié)后開始連續(xù)取3個(gè)字節(jié),即?00?00?00,解壓后即為“000000”,具體代表含義這里就不敘述了。
4域?yàn)榻灰捉痤~,壓縮成BCD碼后占定長6個(gè)字節(jié),同理取6個(gè)字節(jié),即00?00?00?00?00?01,也就是金額0.01元,具體轉(zhuǎn)換參考銀聯(lián)規(guī)范。
11域?yàn)槭芸ǚ较到y(tǒng)跟蹤號(流水號),壓縮成BCD碼占定長3個(gè)字節(jié),同理取3個(gè)字節(jié),即00?03?49,即000349。
22域?yàn)榉?wù)點(diǎn)輸入方式碼,壓縮成BCD碼占定長2個(gè)字節(jié),同理取2個(gè)字節(jié),即02?10,由于22域本身只占3個(gè)字節(jié),壓縮時(shí)左靠,右補(bǔ)0,所以轉(zhuǎn)換為“021”,具體含義不再敘述。
25域?yàn)榉?wù)點(diǎn)條件碼,壓縮成BCD碼占定長1個(gè)字節(jié),同理取1個(gè)字節(jié),即00,轉(zhuǎn)換為“00”,“00”代表正常提交。
26域?yàn)榉?wù)點(diǎn)PIN獲取碼,壓縮成BCD碼占定長1個(gè)字節(jié),同理取1個(gè)字節(jié),即12,轉(zhuǎn)換為“12”,表示服務(wù)點(diǎn)設(shè)備所允許輸入的個(gè)人密碼明文的最大長度為12。
解下來的35域由于不是定長,所以處理方法不同,先取一個(gè)字節(jié),即30,轉(zhuǎn)換為“30”,表示第二磁道的數(shù)據(jù)占用30個(gè)字節(jié),取連續(xù)15個(gè)字節(jié)即62?25?82?21?12?99?63?01?5D?15?11?10?10?00?00,這里不對這串?dāng)?shù)據(jù)進(jìn)行說明了。
41域?yàn)槭芸C(jī)終端標(biāo)識碼,占8個(gè)字節(jié)的定長域,取35?36?38?35?32?33?31?34。
42域?yàn)槭芸ǚ綐?biāo)識碼,占15個(gè)字節(jié)的定長域,取32?33?35?32?31?34?35?32?36?38?35?39?32?33?36。
49域?yàn)榻灰棕泿糯a,占3個(gè)字節(jié)的定長域,取31?35?36。
52域?yàn)閭€(gè)人標(biāo)識碼數(shù)據(jù),占8個(gè)字節(jié)的定長二進(jìn)制數(shù)域,取C6?24?83?4D?36?7E?9E?9E。
53域?yàn)榘踩刂菩畔?#xff0c;壓縮成BCD碼占8個(gè)字節(jié)定長域,取20?00?00?00?00?00?00?00。
60域?yàn)樽远x域,為不定長域,先取長度(壓縮成BCD碼占兩個(gè)字節(jié)),即00?13,轉(zhuǎn)換為13即占60域占13個(gè)字節(jié),壓縮成BCD碼占7個(gè)字節(jié),取22?00?00?08?00?05?00。
64域?yàn)閳?bào)文鑒別碼,占定長8個(gè)字節(jié),取最后八個(gè)字節(jié)36?37?41?32?32?39?39?41。
總結(jié)
- 上一篇: Java实现 蓝桥杯VIP 算法提高 阮
- 下一篇: ConstraintLayout中Cha