ISO 8583使用总结(附Java部分源码)(二)

第一种实现方式

第一种实现方式分为三步:

  • 第一步:创建域对象
  • 第二步:创建各种数据转换的工具类
  • 第三步:封装请求

第一步:创建域对象

这一步就比较简单了,也比较容易理解,适合域比较少,或者每次填写就那么十几个域。
打开你的接口文档,看一下文档中的接口报文都有多少个域,我这里是有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,如果有需要请移步下载,如果觉得还可以,请给个赞。如果有任何问题,欢迎留言,我会及时回复。

posted @ 2019-08-05 18:37  大橙砸  阅读(1382)  评论(4编辑  收藏  举报