自定义8583模板,打包解包,使用j8583包有改动

j8583_boss.xml

<?xml version=”1.0″ encoding=”UTF-8″?><!DOCTYPE j8583-config PUBLIC “-//J8583//DTD CONFIG 1.0//EN””C:/tvpay/config/j8583.dtd”><j8583-config>

<!– These are the ISO headers to be prepended to the message types specified –><header type=”1027″>1027</header><header type=”1028″>1028</header><header type=”1005″>1005</header><header type=”1006″>1006</header>

<!– The server example uses this to read the requests –><parse type=”1027″><field num=”2″ type=”LLVAR” /><field num=”3″ type=”LLVAR” /><field num=”4″ type=”NUMERIC” length=”4″ /><field num=”5″ type=”NUMERIC” length=”4″ /><field num=”6″ type=”NUMERIC” length=”4″ /><field num=”7″ type=”NUMERIC” length=”1″ /><field num=”8″ type=”NUMERIC” length=”1″ /><field num=”43″ type=”LLVAR” /><field num=”44″ type=”LLVAR” /><field num=”45″ type=”LLVAR” /></parse>

<parse type=”1005″><field num=”2″ type=”LLVAR” /><field num=”3″ type=”LLVAR” /><field num=”4″ type=”NUMERIC” length=”4″ /><field num=”5″ type=”NUMERIC” length=”4″ /><field num=”6″ type=”NUMERIC” length=”4″ /><field num=”7″ type=”NUMERIC” length=”1″ /><field num=”8″ type=”NUMERIC” length=”1″ /><field num=”19″ type=”LLVAR” /><field num=”21″ type=”LLVAR” /><field num=”23″ type=”ALPHA” length=”2″ /><field num=”24″ type=”LLVAR” /><field num=”27″ type=”LLVAR” /><!– <field num=”39″ type=”NUMERIC” length=”6″ /> –></parse>

<!– The client example uses this to read the responses –><parse type=”1028″><field num=”2″ type=”LLVAR” /><field num=”3″ type=”LLVAR” /><field num=”4″ type=”NUMERIC” length=”4″ /><field num=”5″ type=”NUMERIC” length=”4″ /><field num=”6″ type=”NUMERIC” length=”4″ /><field num=”7″ type=”NUMERIC” length=”1″ /><field num=”8″ type=”NUMERIC” length=”1″ /><field num=”41″ type=”LLLVAR” /><field num=”43″ type=”LLVAR” /><field num=”44″ type=”LLVAR” /><field num=”45″ type=”LLVAR” /></parse>

<parse type=”1006″><field num=”2″ type=”LLVAR” /><field num=”3″ type=”LLVAR” /><field num=”4″ type=”NUMERIC” length=”4″ /><field num=”5″ type=”NUMERIC” length=”4″ /><field num=”6″ type=”NUMERIC” length=”4″ /><field num=”7″ type=”NUMERIC” length=”1″ /><field num=”8″ type=”NUMERIC” length=”1″ /><field num=”19″ type=”LLVAR” /><field num=”20″ type=”LLVAR” /><field num=”21″ type=”LLVAR” /><field num=”22″ type=”LLVAR” /><field num=”23″ type=”ALPHA” length=”2″/><field num=”24″ type=”LLVAR” /><field num=”27″ type=”LLVAR” /><field num=”29″ type=”NUMERIC” length=”10″ /></parse>

</j8583-config>

package com.sumavision.connector.iso8583.parse;

import java.io.*;import java.util.*;

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.io.Resource;

import com.sumavision.connector.iso8583.util.ConfigParser;import com.sumavision.connector.iso8583.util.IsoValue;import com.sumavision.connector.iso8583.util.MessageFactory;import com.sumavision.connector.iso8583.util.SimpleTraceGenerator;import com.sumavision.connector.iso8583.util.IsoMessage;import com.sumavision.connector.iso8583.util.IsoType;import com.sumavision.connector.util.DesEncrypt;import com.sumavision.connector.util.Hex2GBKStringUtil;import com.sumavision.connector.util.PacketIdGenerator;import com.sumavision.connector.util.RequestIdGenerator;import com.sumavision.crpt.MessageDigestMD5;

/*** <p>数据打包解包服务</p>* @author Administrator*/public class PacketDataOperateService {private final Logger log = LoggerFactory.getLogger(this.getClass());//模板文件配置路径private final String OPERATE_TEMPLATE_PATH = “com/sumavision/connector/iso8583/parse/j8583_boss.xml”;private Resource templatePath = null;//获取用户信息(终端号) 支付平台传来的交易代码private final String GET_TERMINALNO_TRANSCODE = “BT000201”;//获取用户缴费账单(BOSS缴费单) 支付平台传来的交易代码private final String GET_USERFEE_TRANSCODE = “BT000202”;//获取用户信息(终端号) 功能码private final int GET_TERMINALNO_FUNCNO = 1027;//获取用户信息(终端号) 返回响应功能码private final int GET_TERMINALNO_RESPONSE_FUNCNO =1028;//获取用户缴费账单(BOSS缴费单) 功能码private final int GET_USERFEE_FUNCNO = 1005;//获取用户缴费账单(BOSS缴费单) 返回响应功能码private final int GET_USERFEE_RESPONSE_FUNCNO = 1006;//机顶盒内部编码private final String STB_INSIDE_CODE = “STB_INSIDE_CODE”;//厂商编号private final String MANUFACTURERS_NO = “MANUFACTURERS_NO”;//硬件版本号private final String HARDWARE_VERSION_NO = “HARDWARE_VERSION_NO”;//客户编码private final String CUSTOMER_NO = “CUSTOMER_NO”;//账户编码private final String ACCOUNT_NO = “ACCOUNT_NO”;//业务编码private final String SERVICE_TYPE = “SERVICE_TYPE”;//服务号码private final String SUBSCRIBER_NO = “SUBSCRIBER_NO”;//账务周期private final String BILLING_CYCLE = “BILLING_CYCLE”;//开始标识+包长度+包体+校验字段+结束标识//报文开始标识private final String PACKET_HEADER = “|*!#”;//报文结束标识private final String PACKET_TAILER = “#@&^”;private static final Map<String,String> retCodeMsgMap = new HashMap<String,String>();/*初始化错误代码表*/static{retCodeMsgMap.put(“0000”, “交易成功”);retCodeMsgMap.put(“0001”, “服务器忙”);retCodeMsgMap.put(“0002”, “无法解析字符串”);retCodeMsgMap.put(“0003”, “SMS系统内部错误”);retCodeMsgMap.put(“0004”, “版本号不支持”);retCodeMsgMap.put(“0005”, “数据库没有该银行的记录”);retCodeMsgMap.put(“0006”, “银行代码与银行认证码不符”);retCodeMsgMap.put(“0007”, “客户编码不存在”);retCodeMsgMap.put(“0008”, “帐户编码不存在”);retCodeMsgMap.put(“0009”, “业务编码不存在”);retCodeMsgMap.put(“0010”, “服务号码不存在”);retCodeMsgMap.put(“0011”, “账务周期不存在”);retCodeMsgMap.put(“0012”, “银行流水号不存在”);retCodeMsgMap.put(“0013”, “余额账本不存在”);retCodeMsgMap.put(“0014”, “存在多个余额账本,请按余额账本编号查询”);retCodeMsgMap.put(“0015”, “存在一个服务号码由多个客户的帐户付费”);retCodeMsgMap.put(“0016”, “已缴费”);retCodeMsgMap.put(“0017”, “已签订代扣协议”);retCodeMsgMap.put(“0018”, “此帐户未使用该流水号签订代扣协议”);retCodeMsgMap.put(“0019”, “此客户有多个帐户,请使用帐户编号”);retCodeMsgMap.put(“0020”, “预存失败,预存超过余额上限”);retCodeMsgMap.put(“0021”, “实缴金额不等于实际费用加滞纳金”);retCodeMsgMap.put(“0022”, “冲正失败”);retCodeMsgMap.put(“0023”, “已经对账,不能进行冲正”);retCodeMsgMap.put(“0024”, “已经冲正,不能再次冲正”);retCodeMsgMap.put(“0025”, “必填数据未填充”);retCodeMsgMap.put(“0026”, “代扣失败”);retCodeMsgMap.put(“0027”, “发票号码不存在”);retCodeMsgMap.put(“0028”, “发票号码不可使用”);retCodeMsgMap.put(“0029”, “附加信息域格式错误”);retCodeMsgMap.put(“0030”, “产品信息域格式错误”);retCodeMsgMap.put(“0032”, “找不到对应用户”);}/** * <p>打包数据</p> * @param map * @return * @throws Exception */public String packetData(Map<String, Object> map) throws Exception{log.info(“打包数据准备…Map >>{}”,map);if(null==map || map.size()<1){log.error(“请求参数域为空,打包失败”);return null;}if (!map.containsKey(“STB_ID”)) {log.error(“请求参数STB_ID域为空,打包失败”);return null;}String stb = map.get(“STB_ID”).toString();map.put(“MANUFACTURERS_NO”, stb.substring(0, 3));map.put(“HARDWARE_VERSION_NO”, stb.substring(3, 18));map.put(“STB_INSIDE_CODE”, stb.substring(18, 25));MessageFactory mfact = ConfigParser.createFromStream(templatePath.getInputStream());//MessageFactory mfact = ConfigParser.createFromClasspathConfig(templatePath.);//mfact.setAssignDate(true);//mfact.setTraceNumberGenerator(new SimpleTraceGenerator((int)(System.currentTimeMillis() % 100000)));String transcode = (String)map.get(“TRANSCODE”);IsoMessage m = null;if(null!=transcode && transcode.equals(GET_TERMINALNO_TRANSCODE)){m= _cardNumberForMachinePacket(map,mfact);}else if(null!=transcode && transcode.equals(GET_USERFEE_TRANSCODE)){m= _accessToUserFeesBillPacket(map,mfact);}else{log.error(“交易代码错误,打包失败”);return null;}String packetStr = new String(m.writeData());String packetLenStr = String.valueOf(packetStr.length()+32);StringBuffer sbuff = new StringBuffer();sbuff.append(PACKET_HEADER);if(packetLenStr.length()<8){sbuff.append(“00000000”.substring(packetLenStr.length()));}sbuff.append(packetStr.length()+32);sbuff.append(packetStr);sbuff.append(generateValidateCode(packetStr).toLowerCase());sbuff.append(PACKET_TAILER);log.info(“打包数据完成…报文 >>{}”,sbuff.toString());return sbuff.toString();}/** * <p>解析报文字符串</p> * @param pstr报文体 * @param vstr校验字段 * @return * @throws Exception */@SuppressWarnings(“rawtypes”)public Map parseData(String pstr,String vstr,int funcCode) throws Exception{log.info(“解包数据准备…报文体 >>{}”,pstr);log.info(“解包数据准备…报文校验字段 >>{}”,vstr);MessageFactory mfact = ConfigParser.createFromStream(templatePath.getInputStream());//MessageFactory mfact = ConfigParser.createFromClasspathConfig(templatePath);//mfact.setAssignDate(true);//mfact.setTraceNumberGenerator(new SimpleTraceGenerator((int)(System.currentTimeMillis() % 100000)));mfact.setUseBinaryMessages(false);//可能有中文//String bstr = new String(bytes,”GBK”);//int functionCode = Integer.valueOf(pstr.substring(68, 72));//String packetDataStr = bstr.substring(12, bstr.length()-4-32);//String validateStr = bstr.substring(bstr.length()-4-32, bstr.length()-4);Map map = null;byte[] packetBytes = pstr.getBytes(“GBK”);if(funcCode==GET_TERMINALNO_RESPONSE_FUNCNO){if(!validateResponseData(pstr,vstr)){throw new Exception(“数据包校验失败,无效数据包”);}map = cardNumberForMachinePacket_(mfact.parseMessage(packetBytes, 4136));}else if(funcCode==GET_USERFEE_RESPONSE_FUNCNO){//查询单用户余额账本的 返回报文中含有中文字符,返回的校验码与对报文做MD5生成的校验码不一致//未找到原因: 暂时不做校验map = accessToUserFeesBillPacket_(mfact.parseMessage(packetBytes, 4102));}else{log.error(“无法识别的功能码,解包失败”);return null;}log.info(“解包数据完成…Map >>{}”,map);return map;}/** * 打包 * @param mf * @param input * @return */@SuppressWarnings(“rawtypes”)private IsoMessage _cardNumberForMachinePacket(Map input,MessageFactory mf){//IsoMessage m = mf.newMessage(GET_TERMINALNO_FUNCNO);IsoMessage m = new IsoMessage();m.setBinary(false);//m.setBinary(true);//会话ID 对来自银行前置机接入SMS的请求数据,此处填写由银行前置机产生的会话ID,在传输过程中应保持一对请求/响应的数据中 SessionID 保持不变m.setValue(2, RequestIdGenerator.genRequestId(), IsoType.LLVAR, 16);//数据包序号 从 0 开始,顺序累加,步长为 1,循环使用m.setValue(3, PacketIdGenerator.genPacketId(), IsoType.LLVAR, 32);//银行代码暂时不知道,先写1111m.setValue(4, 2000, IsoType.NUMERIC, 4);//功能码业务标识,用于标识请求/响应数据包代表的业务操作m.setValue(5, GET_TERMINALNO_FUNCNO, IsoType.NUMERIC, 4);//响应吗标识业务处理结果m.setValue(6, 0000, IsoType.NUMERIC, 4);//重发标识0 标识普通数据包;1:标识重发数据包m.setValue(7, 0, IsoType.NUMERIC, 1);//加密标识0 标识包体数据为明文,1:标识包体数据为加密数据m.setValue(8, 0, IsoType.NUMERIC, 1);//机顶盒内部编码 StbInsideCodem.setValue(43, input.get(STB_INSIDE_CODE), IsoType.LLVAR, 50);//厂商编号ManufacturersNom.setValue(44, input.get(MANUFACTURERS_NO), IsoType.LLVAR, 20);//硬件版本号 HardwareVersionNom.setValue(45, input.get(HARDWARE_VERSION_NO), IsoType.LLVAR, 20);return m;}/** * 打包 * @param mf * @param input * @return */@SuppressWarnings(“rawtypes”)private IsoMessage _accessToUserFeesBillPacket(Map input,MessageFactory mf){IsoMessage m = mf.newMessage(GET_USERFEE_FUNCNO);m.setBinary(false);//会话ID 对来自银行前置机接入SMS的请求数据,此处填写由银行前置机产生的会话ID,在传输过程中应保持一对请求/响应的数据中 SessionID 保持不变m.setValue(2, RequestIdGenerator.genRequestId(), IsoType.LLVAR, 16);//数据包序号 从 0 开始,顺序累加,步长为 1,循环使用m.setValue(3, PacketIdGenerator.genPacketId(), IsoType.LLVAR, 32);//银行代码暂时不知道,先写1111m.setValue(4, 2000, IsoType.NUMERIC, 4);//功能码业务标识,用于标识请求/响应数据包代表的业务操作m.setValue(5, GET_USERFEE_FUNCNO, IsoType.NUMERIC, 4);//响应吗标识业务处理结果m.setValue(6, 0000, IsoType.NUMERIC, 4);//重发标识0 标识普通数据包;1:标识重发数据包m.setValue(7, 0, IsoType.NUMERIC, 1);//加密标识0 标识包体数据为明文,,1:标识包体数据为加密数据m.setValue(8, 0, IsoType.NUMERIC, 1);//客户编码 CustomerNo广电客户的编码m.setValue(19, input.get(CUSTOMER_NO), IsoType.LLVAR, 20);//下面3项必填一项if(null!=input.get(ACCOUNT_NO)){//账户编码AccountNo广电客户的帐户编码m.setValue(21, input.get(ACCOUNT_NO), IsoType.LLVAR, 20);}if(null!=input.get(SERVICE_TYPE)){//业务编码 ServiceType公共业务00数字电视业务02m.setValue(23, input.get(SERVICE_TYPE), IsoType.ALPHA, 2);}if(null!=input.get(SUBSCRIBER_NO)){//服务号码 SubscriberNo智能卡号、上网帐号等m.setValue(24, input.get(SUBSCRIBER_NO), IsoType.LLVAR, 20);}//账务周期 BillingCycle 可选//m.setValue(39, input.get(BILLING_CYCLE), IsoType.LLVAR, 20);return m;}/** * 解包 * @param im * @return */@SuppressWarnings({ “rawtypes”, “unchecked” })private Map cardNumberForMachinePacket_(IsoMessage im){log.info(“cardNumberForMachinePacket_ : receive Msg :”+printIsoMessage(im));//银行代码IsoValue bankCode = im.getAt(4);//功能码IsoValue functionCode = im.getAt(5);//boss响应吗IsoValue retCode = im.getAt(6);//加密标识IsoValue isEncrpt = im.getAt(8);//机顶盒内部编码IsoValue stbInsideCode = im.getAt(43);//厂商编码IsoValue manufacturersNo = im.getAt(44);//硬件版本号IsoValue hardwareVersionNo = im.getAt(45);//附件信息响应中的“附加信息”域经过加密处理,加密方式会通过其他方式告知。其中的内容如下://智能卡号/t 客户ID/t 用户ID/t 客户姓名/t 客户地址例如://1234567890 1521 1598 张三 天津市河西区气象台路卫星里IsoValue additionalData = im.getAt(41);if(!String.valueOf(functionCode.getValue()).equals(String.valueOf(GET_TERMINALNO_RESPONSE_FUNCNO))){log.error(“功能码不正确”);}Map map = new HashMap();map.put(“RETCODE”, retCode.getValue());map.put(“TRANSMSG”, getTransMsg(paddingRetCode(String.valueOf(retCode.getValue()))));//map.put(“BANK_CODE”, bankCode.getValue());map.put(“IS_ENCRPT”, isEncrpt.getValue());map.put(“STB_INSIDE_CODE”, stbInsideCode.getValue());map.put(“MANUFACTURERS_NO”, manufacturersNo.getValue());map.put(“HARDWARE_VERSION_NO”, hardwareVersionNo.getValue());map.put(“ADDITIONAL_DATA”, additionalData.getValue());Object addData = additionalData.getValue();//additionalData解密String additional_Str = null;if(null!=addData){String raw_additional_Str = decrptDesString(String.valueOf(addData));if(null!=raw_additional_Str){additional_Str = Hex2GBKStringUtil.toStringHex(raw_additional_Str);log.info(“HEX字符串转为GBK文本串为 /n {}”,additional_Str);}}try{String[] infos = parseAdditionalInfo(additional_Str);//智能卡号map.put(“ICCARD_ID”, infos[0]);//客户IDmap.put(“CUSTOMER_ID”, infos[1]);//用户IDmap.put(“USER_ID”, infos[2]);//客户姓名map.put(“CUSTOMER_NAME”, infos[3]);//客户地址map.put(“USER_ADDRESS”, infos[4]);}catch(Exception e){log.error(“解析附加信息失败 , 原因: {}”,e);//智能卡号map.put(“ICCARD_ID”, null);//客户IDmap.put(“CUSTOMER_ID”, null);//用户IDmap.put(“USER_ID”, null);//客户姓名map.put(“CUSTOMER_NAME”, null);//客户地址map.put(“USER_ADDRESS”, null);}return map;}/** * 解包 * @param im * @return */@SuppressWarnings({ “rawtypes”, “unchecked” })private Map accessToUserFeesBillPacket_(IsoMessage im){log.info(“accessToUserFeesBillPacket_ : receive Msg :”+printIsoMessage(im));//银行代码IsoValue bankCode = im.getAt(4);//功能码IsoValue functionCode = im.getAt(5);//boss响应吗IsoValue retCode = im.getAt(6);//加密标识IsoValue isEncrpt = im.getAt(8);//客户编码IsoValue customerNo = im.getAt(19);//客户名称IsoValue customerName = im.getAt(20);//账户编码IsoValue accountNo = im.getAt(21);//帐户名称IsoValue accountName = im.getAt(22);//业务编码IsoValue serviceType = im.getAt(23);//服务号码IsoValue subscriNo = im.getAt(24);//余额 IsoValue balance = im.getAt(29);if(!String.valueOf(functionCode).equals(String.valueOf(GET_USERFEE_RESPONSE_FUNCNO))){log.error(“功能码不正确”);}Map map = new HashMap();map.put(“RETCODE”, retCode.getValue());map.put(“TRANSMSG”, getTransMsg(paddingRetCode(String.valueOf(retCode.getValue()))));//map.put(“BANK_CODE”, bankCode.getValue());map.put(“IS_ENCRPT”, isEncrpt.getValue());map.put(“CUSTOMER_NO”, customerNo.getValue());map.put(“CUSTOMER_NAME”, customerName.getValue());map.put(“BALACNE”, balance==null?null:balance.getValue());return map;}/** * <p>校验响应数据包的校验码是否正确</p> * @param rawData待校验数据串 * @param validateCode校验码 * @return */private boolean validateResponseData(String rawData,String validateCode){return validateCode.equals(MessageDigestMD5.keyedEncode(rawData, “”));}/** * <p>获取返回码对应的消息</p> * @param code * @return */private String getTransMsg(String code){if(retCodeMsgMap.containsKey(code)){return retCodeMsgMap.get(code);}else{return “交易失败”;}}private String paddingRetCode(String rawcode){if(rawcode.length()<4){return “0000”.substring(rawcode.length())+rawcode;}else{return rawcode;}}/** * <p>解密DES加密串</p> * @param rawData * @return * @throws Exception */private String decrptDesString(String rawData) {String rstr = null;log.info(“DES解密算法解密源字符串: /n {}”,rawData);if(null==rawData){log.error(“源加密字符串为空!”);return null;}try {// 设置密钥 静态,设置一次即可 密钥是固定的,写死即可DesEncrypt.setKey(“A000000000000000”);rstr = DesEncrypt.desDecrypt(rawData);} catch (Exception e) {log.error(“DES解密算法 解密密码串失败, 原因: {}”,e);}log.info(“DES解密算法解密结果: /n {}”,rstr);return rstr;}private String printIsoMessage(IsoMessage m) {StringBuffer sbuff = new StringBuffer();sbuff.append(“TYPE: ” + Integer.toHexString(m.getType()) +” /n”);for (int i = 2; i < 128; i++) {if (m.hasField(i)) {sbuff.append(“F ” + i + “(” + m.getField(i).getType() + “): ” + m.getObjectValue(i) + ” -> ‘”+ m.getField(i).toString() + “‘ /n”);}}return sbuff.toString();}/** * <p>解密附加信息 * 用于 解析 根据机顶盒号查询用户响应 * </p> * @param s * @return[0]智能卡号 * [1]客户ID * [2]用户ID * [3]客户姓名 * [4]客户地址 * @throws Exception */private String[] parseAdditionalInfo(String s) throws Exception{if(null!=s && !””.equals(s)){String[] ss = s.trim().split(“//t”);if(ss.length!=5){throw new Exception(“解析附加信息失败,信息格式不正确!”);}else{return new String[]{ss[0].trim(),ss[1].trim(),ss[2].trim(),ss[3].trim(),ss[4].trim()};}}else{throw new Exception(“解析附加信息失败,信息格式不正确!”);}}/** * <p>发送报文时生成校验码</p> * @param rawData * @return */private String generateValidateCode(String rawData){return MessageDigestMD5.keyedEncode(rawData, “”);}public static void main(String[] strs) throws Exception{PacketDataOperateService pd = new PacketDataOperateService();//System.out.println(pd.generateValidateCode(“7F003E28000000001613039575047501073200000000000000000000000000000006200010060000001210600001287906傅雪晶1200000301582511傅雪晶-帐户00120000030158250000067062”));//System.out.println(pd.generateValidateCode(“12345678901234567890”).length());String r = pd.decrptDesString(“3EE1B1F40175DC92701588F6F40A7762B05859FACE94BA7CD7EC5513E4DBE3C519CD9BFF085642C765BDAD8F06D719F5A75161E54ACF5230BBD811E91E00A6A1C7FE957F19AEF1F6”);String additional_Str = Hex2GBKStringUtil.toStringHex(r);String[] ss = pd.parseAdditionalInfo(additional_Str);for(String s : ss){System.out.println(s);}//System.out.println(pd.paddingRetCode(“3”));}

public Resource getTemplatePath() {return templatePath;}

public void setTemplatePath(Resource templatePath) {this.templatePath = templatePath;}}

别想一下造出大海,必须先由小河川开始。

自定义8583模板,打包解包,使用j8583包有改动

相关文章:

你感兴趣的文章:

标签云: