第一種實現方式
第一種實現方式分為三步:
- 第一步:創建域對象
- 第二步:創建各種數據轉換的工具類
- 第三步:封裝請求
第一步:創建域對象
這一步就比較簡單了,也比較容易理解,適合域比較少,或者每次填寫就那么十幾個域。
打開你的接口文檔,看一下文檔中的接口報文都有多少個域,我這里是有64個域,有的域下面還有子域。
public class Message8583Body {
private String msgType;// 消息類型
private String bitMap;// 位元表
private String domain2;
private String domain3;
private String domain4;
···
private String domain48;
private String domain49;
private String domain58;
private String domain58_1;
private String domain58_2;
private String domain58_3;
}
這里我就簡單表示一下,共有64域,根據每個域和其子域中創建一個類。子域我以58域這里舉例,假設55域下面還有三個子域,有子域的地方set方法需要特別處理。
public String getDomain58() {
return domain58;
}
public void setDomain58(String domain58) {
this.domain58 = domain58;
}
public String getDomain58_1() {
return domain58_1;
}
public void setDomain58_1(String domain58_1) {
this.domain58_1 = domain58_1;
this.domain58 += domain58_1;
}
public String getDomain58_2() {
return domain58_2;
}
public void setDomain58_2(String domain58_2) {
this.domain58_2 = domain58_2;
this.domain58 += domain58_2;
}
public String getDomain58_3() {
return domain58_3;
}
public void setDomain58_3(String domain58_3) {
this.domain58_3 = domain58_3;
this.domain58 += domain58_3;
}
也就是說,這個子域報文是依次向后拼接在58域后面的。假如58_1下面還有子域,一樣的寫法這里就不多闡述了。到此為止,第一步完成了。
(WARNING:我這里是簡要表達意思,使用時請依據實際情況考慮高並發的問題。)
第二步:創建各種數據轉換的工具類
因為在8583中,報文是以數字和字母進行傳輸的,有的是轉成ASCII,有的只是左/右靠BCD補0等等。這里列出常用的字符轉換,如果需要我這邊完整版本,請移步github。
/**
* 獲取位元表
*
* @param list
* @return
*/
public static String getBitMap(List<Integer> list) {
StringBuffer result = new StringBuffer("");
byte[] bytes = new byte[64];
for (int i = 0; i < 64; i++) {
if (list.contains(i + 1)) {
bytes[i] = 1;
} else {
bytes[i] = 0;
}
}
StringBuffer sb = new StringBuffer("");
for (int i = 0; i <= 64; i++) {
if (i % 4 == 0 && i != 0) {
result.append(
String.format("%x", Integer.valueOf(sb.toString(), 2))
.toUpperCase());
sb.delete(0, sb.length());
if (i < 64) {
sb.append(bytes[i]);
}
} else {
sb.append(bytes[i]);
}
}
log.info("bitMap=" + result.toString());
return result.toString();
}
/**
* 普通字符串轉為ascii字符串
*
* @param asciiString 字節數組
* @return
*/
public static String asciiToHex(String asciiString) {
if (asciiString == null) {
return "";
}
StringBuffer buff = new StringBuffer();
byte[] bytes = asciiString.getBytes();
int len = bytes.length;
for (int j = 0; j < len; j++) {
if ((bytes[j] & 0xff) < 16) {
buff.append('0');
}
buff.append(Integer.toHexString(bytes[j] & 0xff).toUpperCase());
}
return buff.toString();
}
由於篇幅限制,我這里就暫時先列出兩個示例方法,創建好各種工具,第二步就算完成了。
第三步:封裝請求
封裝請求比較簡單了,先進行位元表創建,然后進行域賦值就可以了。
//位元表填寫
Integer[] array = {2,3,4,11,25,41,42,58,60,63,64};
List<Integer> list= Arrays.asList(array);
這里位元表里面的值代表了哪些域有值,通過數據創建一個list,然后對域賦值的時候,再將list轉化為位元表。
下面進行對於賦值,還是先上示例代碼
Message8583Body body = new Message8583Body();
body.setMsgType("1111");
body.setBitMap(getBitMap(list));
body.setDomain2("2222");
body.setDomain3("3333");
body.setDomain4("4444");
···
body.setDomain58_1("581581581");
body.setDomain58_2("582582582");
body.setDomain58_3("583583583");
String domain58 = (這里調用實際報文轉換的方式,一般58域是獲取整體報文長度,拼裝在58域的前面)(body.getDomain58(), 3);
body.setDomain58(domain58);
當把你的報文都set完畢后,調用和服務方約定的方式,計算所有的報文長度,拼在報文前面。到此為止,第三步完成了。
三步都做好后,此時就可以用socket發送到服務方了,剩下就是調試工作。
第二種實現方式
第二種實現方式也分為三步:
- 第一步:創建域對象
- 第二步:創建各種數據轉換的工具類
- 第三步:封裝請求
第一步:創建域對象
這一步就與第一步不同的是,這個域對象不再是簡單的表示每個域的報文了,而是這個一個類,代表所有域的信息。
public class FieldObject {
/**
* 域所在的位
*/
private int index;
/**
* 長度
*/
private int length;
/**
* 格式
*/
private int format;
/**
* 類型
*/
private int type;
/**
* 值
*/
private String value;
/**
* 是否定長
*/
private int isVar;
/**
* 響應結果LLLVAR長度
*/
private int varLength;
}
上面是每一個域的信息,包括所在的位,長度,字段信息等。這個類有兩個構造方法,一個是請求對象的構建,一個是響應報文的解析。
/**
* ISO 8583請求對象構建
* @param index
* @param value
* @param varLength
* @param type
*/
public FieldObject(int index,String value,int isVar,int type){
this.index = index;
this.value = value;
this.isVar = isVar;
this.type = type;
}
/**
* ISO8583解析對象構建
* @param index
* @param length
* @param isVar
* @param type
*/
public FieldObject(int index,int length,int varLength,int type){
this.index = index;
this.length = length;
this.varLength = varLength;
this.type = type;
}
這兩個構建構造方法,一個是用來構建,一個用來解析,使用的時候注意參數不要傳遞錯誤導致問題。這里,第一步就做好了。
第二步:創建各種數據轉換的工具類
同第一種的第二步。
第三步:封裝請求
這里就先簡單演示一下,請求參數如何封裝
List<FieldObject> fieldList = new ArrayList<>();
fieldList.add( new FieldObject(1, "1111", 1, 1));
fieldList.add( new FieldObject(2, "2222", 2, 2));
fieldList.add( new FieldObject(3, "3333", 3, 3));
···
這里后面兩位是標識這個域的參數類型(比如1是普通數字,2是ASCII,3是BCD等等,看自己定義),當這個list拼裝好了之后,就可以進行參數封裝等信息然后發送給服務端。
到此為止,兩種封裝方式就分享給大家了,后面會上傳的到git,如果有需要請移步下載,如果覺得還可以,請給個贊。如果有任何問題,歡迎留言,我會及時回復。