j8583_boss.xml
<?xml version="1.0" encoding="UTF-8"?>
<?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>
PacketDataOperateService.java
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);
// 银行代码 暂时不知道,先写1111
m.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);
// 机顶盒内部编码 StbInsideCode
m.setValue(43, input.get(STB_INSIDE_CODE), IsoType.LLVAR, 50);
// 厂商编号 ManufacturersNo
m.setValue(44, input.get(MANUFACTURERS_NO), IsoType.LLVAR, 20);
// 硬件版本号 HardwareVersionNo
m.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);
// 银行代码 暂时不知道,先写1111
m.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 数字电视业务02
m.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]);
// 客户ID
map.put("CUSTOMER_ID", infos[1]);
// 用户ID
map.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);
// 客户ID
map.put("CUSTOMER_ID", null);
// 用户ID
map.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;
}
}