最近在做一個項目,用到了8583協議。踩了許多坑,項目已經上線了,寫一篇博客記錄一下最近使用的一些方法總結。
(一)主要介紹8583協議,(二)總結使用Java兩種方式來實現8583.
需要代碼的請直接看(二),不過建議你還是先看看(一),多了解了解總沒有壞處的。
1.8583 簡介
8583協議是基於ISO8583報文國際標准的包格式的通訊協議,8583包最多由128個字段域組成,每個域都有統一的規定,並有定長與變長之分。8583包前面一段為位圖,它是打包解包確定字段域的關鍵代替。8583協議多在POS機的開發上使用。(摘自百度百科解釋)8583報文里,采用了以域的形式進行傳輸。與普通json不同是,json是key=value的形式,而8583是雙方約定好,每個域是什么意思,然后再域里面進行填值。8583的格式一般由三部分組成,頭部信息、位圖和域。
2.8583 結構介紹
8583的結構:報文長度(4個字節,可以根據協議自己定)+報文頭(可以是TPDU+消息標識等等,一般4個字節,如果加上TPDU那么10個字節以上了,根據協議自己定)+位圖(8字節,如果是128域表示,這個域占16字節)+實際數據data,一般數據都采用16進制表示法。注意,這里只是通常表示是這樣的,根據實際情況會有所不同。8583最多有128個域,每個域都有統一的規定,並有定長與變長之分。什么是定長,什么是變長呢?說白了就是定長是固定長度,變長是可變長度。每個域是定長還是變長,都會在域中有說明。說明一下,有很多公司使用了8583協議,其實是偽8583協議,意思就是采用了8583協議,但是他們里面域的用法與實際8583有很大區別,所以大家請注意了。
3.8583 內容介紹
下圖是對於8583報文結構樣例表格說明,請記住,這是樣例,不同的項目可能會有細小差別,請勿照搬照用,對於下圖的字母所代表的含義,后面有講到。
報文長度 |
TPDU |
報文頭 |
應用數據 |
||||||
ISO8583 Msg |
|||||||||
|
ID |
目的 地址 |
源地址 |
應用類別定義 |
軟件 版本號 |
終端 狀態 |
處理 要求 |
保留 使用 |
交易數據 |
H4 |
60H |
NN NN |
NN NN |
N2 |
N2 |
N1 |
ANS1 |
N6 |
不定長度 |
- 報文長度,這個一般是等后面除長度部分拼好以后計算出來的,這個長度也就是報文頭+位圖+ 實際數據的長度,在這里就是4+8(16)+data.length()/2。注意,如果是16進制表示,那么就是兩個字節表示一位,后面我們詳細舉例。假設我們計算長度是42,那么4個字節是0042,16進制表示法是30 30 34 32。這里我使用到的是0042.
- TPDU,全稱Transport Protocol Data Unit,是指傳送協議數據單元,這里不做過多的解釋,有興趣自行百度。
- 報文頭部分,一般來講都是固定部分,假設是只用4個字節表示消息類型,比如用1000表示交易類型的報文,1200表示退款類型的報文等等,那么實際表示應該是31 30 30 30 30、31 32 30 30。
- 應用數據,這里就不太一致了,我這的項目是共64域,之前還遇到過128域的情況。其實域多少不用在意,原理都是一樣的。
4.域中格式說明
在8583接口文檔中,大概能看到如下常用符號定義:
—— M 強制域(Mandatory),此域在該消息中必須出現否則將被認為消息格式出錯。
—— C 條件域(Conditional),此域在一定條件下出現在該消息中,具體的條件請參考備注說明。
—— O 選用域(Optional),此域在該消息中由發送方自選。。
—— Space 此域在該種消息中不出現。
—— A 字母a-z
—— n 數字0-9
—— s 特殊字符
—— an 字母和數字字符
—— ans 字母、數字和特殊字符
—— MM 月
—— DD 日
—— YY 年
—— hh 小時
—— mm 分
—— ss 秒
—— LL 允許的最大長度為99
—— LLL 允許的最大長度為999
—— VAR 可變長度域
—— b 數據的二進制表示,后跟數字表示位(bit)的個數
—— B 用於表示變長的二進制數,后跟數字表示二進制數據所占字節(Byte)的個數
—— z 按GB/T 15120和GB/T 17552的2、3磁道編碼
—— cn BCD壓縮編碼數值,右補F
舉個例子:
位 |
域名定義 |
屬性 |
格式 |
類型 |
請求 |
響應 |
備注 |
|
類型 |
n4 |
|
BCD |
1234 |
2234 |
TYPE |
|
位元表 |
b64 |
|
BINARY |
M |
M |
BIT MAP |
2 |
XXX |
n..19 |
LLVAR |
BCD |
C |
M |
XXXXXXXXXXXXXXXXXXXX |
- 首先從以上表格中,我們能看到在數據域里面,前四位固定長度是類型,請求使用1234,成功響應回來是2234,
- 其次跟在后面的是位元表,共64位,由16位明文數字構成,代表哪個域里有值,哪個域沒值。這里我簡單介紹一下,位元表怎么使用。
假設位元表是:7020008000C00053。
7的二進制是0111,這就代表了1域是空,2,3,4域有值;
0的二進制是0000,5,6,7,8全是空。
數字16位,二進制64位,則可以看出,這個報文里面,哪些域是有值,哪些沒值的。
- 2域,數字19位,左靠BCD補0。這是什么意思呢?假設我有19位數字“1234567891234567891”,那么在拼接報文中,就是“1912345678912345678910”,前面19代表域的長度是19
5.8583 如何發送
當我們組裝好了報文,如何發送給目標服務器呢?使用socket發送。
如果不清楚socket的,可以自行百度一下,這里不做過多的講述。這里推薦使用socket連接池、tcp連接池的方式發送,連接池的好吃這里不做過多講述。如果需要代碼,請看ISO 8583使用總結(附Java部分源碼)(二)(暫時還沒寫呢)。