package com.eactive.eai.common.util; import java.io.BufferedInputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Iterator; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; import org.apache.tools.ant.filters.StringInputStream; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import com.eactive.eai.common.EAIKeys; import com.eactive.eai.common.message.MessageType; import com.eactive.eai.common.monitor.EAIServiceMonitor; import com.eactive.eai.common.property.PropManager; import com.eactive.eai.transformer.message.ISO8583Message; import com.eactive.eai.transformer.message.ISO8583MessageFactory; import com.eactive.eai.transformer.util.IConv; import com.eactive.eai.transformer.util.ISO8583DumpUtil; import com.ext.eai.common.stdmessage.STDMessageErrorKeys; import com.jayway.jsonpath.JsonPath; import com.solab.iso8583.IsoMessage; public final class MessageUtil { static Logger logger = LoggerFactory.getLogger(MessageUtil.class); //public static final String ERROR_MESSAGE_DEFAULT_FORMAT = "{\"error\":{\"code\":\"%s\",\"message\":\"%s\"}}"; // public static final String ERROR_MESSAGE_DEFAULT_FORMAT = "{\"code\":\"%s\",\"message\":\"%s\"}"; public static final String ERROR_MESSAGE_DEFAULT_FORMAT = "{\"error\":\"%s\",\"error_description\":\"%s\"}"; public static final String ERROR_CODE_AP_ERROR = "E.GW.AP_ERROR"; public static final String ERROR_CODE_AUTH_FAIL = "E.GW.AUTH_FAIL"; public static final String ERROR_CODE_SERVICE_NOT_FOUND = "E.GW.SERVICE_NOT_FOUND"; private MessageUtil() { } // ASCII Bytes에서 특정길이의 값을 추출하는 Method public static String getAscBytes(byte[] message, int startPos, int length) { if (message == null || message.length < startPos) { return null; } byte[] outBytes = new byte[length]; System.arraycopy(message, startPos, outBytes, 0, length); return new String(outBytes); } // EBCDIC Bytes에서 특정길이의 값을 추출하는 Method public static String getEbcdicBytes(byte[] message, int startPos, int length) { if (message == null || message.length < startPos) { return null; } byte[] outBytes = new byte[length]; System.arraycopy(message, startPos, outBytes, 0, length); String key = null; try { key = IConv.ebcdicToASCII(outBytes); } catch (Exception e) { return null; } return key; } // XML 에서 특정TAG name 의 값을 추출하는 Method public static String getXmlFld(String xmlMessage, String tagName) { try { String sTag = "<" + tagName + ">"; String eTag = ""; int s_idx = xmlMessage.indexOf(sTag); int e_idx = xmlMessage.indexOf(eTag); if (s_idx == -1 || e_idx == -1) { return ""; } else { return xmlMessage.substring(s_idx + sTag.length(), e_idx); } } catch (Exception e) { return ""; } } public static String getJSONValue(Object message, String key) { try { if (message instanceof JSONObject) { JSONObject json = (JSONObject) message; Iterator i = json.keySet().iterator(); while (i.hasNext()) { String keys = (String) i.next(); Object obj = json.get(keys); if (obj instanceof String) { if (keys.equals(key)) { return (String) json.get(key); } } else { String value = getJSONValue(obj, key); if (!"".equals(value)) return value; } } } else if (message instanceof JSONArray) { JSONArray arr = (JSONArray) message; for (int i = 0; i < arr.size(); i++) { JSONObject json = (JSONObject) arr.get(i); if (json.containsKey(key)) { return (String) ((JSONObject) message).get(key); } else { String value = getJSONValue(json, key); if (!"".equals(value)) return value; } } } return ""; } catch (Exception e) { return ""; } } public static String getISO8583Fld(IsoMessage isoMessage, int index) { // Field는 Max 128까지만 정의 if (index <= 128) { return isoMessage.getObjectValue(index); } else { return ""; } } public static IsoMessage parseIsoMessage(byte[] message, String messageType) throws Exception { // ISO8583Message iso8583Message = null; // if (StringUtils.equals(messageType, EAITable.ISO8583_TYPE)) { // iso8583Message = new ISO8583Message(); // } else if (StringUtils.equals(messageType, EAITable.ISO8583_H2H_TYPE)) { // iso8583Message = new ISO8583H2HMessage(); // } ISO8583Message iso8583Message = ISO8583MessageFactory.create(messageType); if (iso8583Message == null) { throw new Exception("Cannot create ISO8583Message, messageType=" + messageType); } // MessageFactory mf = iso8583Message.createMessageFactory(); // // // Message Type으로 parseMap을 등록해야 MessageFactory에서 사용가능 // byte[] _type = new byte[4]; // System.arraycopy(message, 0, _type, 0, 4); // // HashMap parseMap = iso8583Message.getFullSpecMap(mf.getCharacterEncoding()); // // mf.setParseMap(Integer.parseInt(new String(_type), 16), parseMap); // // IsoMessage m = mf.parseMessage(message, 0); IsoMessage m = iso8583Message.parseIsoMessage(message, 0); if (logger.isDebugEnabled()) logger.debug("Parsed Key ISO Message: \n" + dumpIsoMessage(m)); return m; } public static String dumpIsoMessage(IsoMessage isoMessage) { return dumpIsoMessage(isoMessage, null); } public static String dumpIsoMessage(IsoMessage isoMessage, ISO8583Message iso8583Message) { return ISO8583DumpUtil.dumpIsoMessage(isoMessage, iso8583Message); } // EAI헤더의 응답코드가 오류인지 판별하는 기능 public static boolean checkRspErrCd(String rspErrCd) { if (rspErrCd == null) { return false; } else if (rspErrCd.startsWith("RE") || rspErrCd.startsWith("RF")) { return false; } else { return true; } } // Message내의 특정 byte를 다른 byte로 치환 public static byte[] removeBytes(byte[] source, byte removeByte, byte replace) { byte[] seBytes = new byte[source.length]; int sPos = 0; for (int i = 0; i < source.length; i++) { if (source[i] == removeByte) { seBytes[sPos] = replace; sPos++; } else { seBytes[sPos] = source[i]; sPos++; } } byte[] newBytes = new byte[sPos]; System.arraycopy(seBytes, 0, newBytes, 0, newBytes.length); return newBytes; } // 업무오류메시지응답에 대한 XML을 생성 public static byte[] makeErrMsgXml(String errMsg) { if (errMsg == null) { errMsg = ""; } StringBuffer sb = new StringBuffer(); sb.append(""); sb.append(errMsg); sb.append(""); return sb.toString().getBytes(); } public static String makeErrMsgXmlString(String errMsg) { if (errMsg == null) { errMsg = ""; } StringBuffer sb = new StringBuffer(); sb.append(""); sb.append(errMsg); sb.append(""); return sb.toString(); } public static byte[] makeErrMsgXml(byte[] errMsg) { if (errMsg == null) errMsg = new byte[0]; return makeErrMsgXml(new String(errMsg)); } // public static byte[] makeStandardErrMsgJson(String errCode, String errMsg, String encode) { // if (errCode == null) { // errCode = ""; // } else { // errCode = getTobeCode(errCode); // } // STDErrorCodeVO vo = STDErrorCodeManager.getInstance().getSTDErrorCode(errCode); // // String errCodeCtnt = ""; // 에러내용 // String actCtnt = ""; // 조치내용 // // if (vo != null) { // errCodeCtnt = vo.getIsdErrCasCt(); // if (vo.getActnCode() != null) { // actCtnt = vo.getActnCode().getActnMsgCtnt(); // } // } // // StringBuffer sb = new StringBuffer(); // sb.append("{\"messageHeader\":{"); // sb.append(" \"messageList\" : "); // sb.append(" ["); // sb.append(" {\"MSG_CODE\":\"" + errCode + "\",\"MSG_CNTT\":\"" + errCodeCtnt + "\",\"addMessageList\": "); // sb.append(" ["); // sb.append(" {\"ADTN_MSG_CODE\":\"\",\"ADTN_MSG_CNTT\":\"\"} "); // sb.append(" ] "); // sb.append(" }"); // sb.append(" ]"); // sb.append(" }"); // sb.append("}"); // // try { // return sb.toString().getBytes(encode); // } catch (UnsupportedEncodingException e) { // return sb.toString().getBytes(); // } // } public static byte[] makeStandardErrMsgXml(byte[] errCode) { if (errCode == null) errCode = new byte[0]; return makeErrMsgXml(new String(errCode)); } public static String makeStandardErrMsgXmlString(String errCode) { return makeErrMsgXmlString(errCode); } public static String replaceMsgXmlString(String Msg) { if (Msg == null) { Msg = ""; } Msg = Msg.replaceAll("<", "["); Msg = Msg.replaceAll(">", "]"); return Msg; } public static byte[] replaceMsgXml(String Msg) { if (Msg == null) { Msg = ""; } Msg = Msg.replaceAll("<", "["); Msg = Msg.replaceAll(">", "]"); return Msg.getBytes(); } public static byte[] replaceMsgXml(byte[] Msg) { if (Msg == null) Msg = new byte[0]; return replaceMsgXml(new String(Msg)); } // 요청,응답 유무를 판단하는 메소드 public static String transClassify(String tmpTrans) { String result = "0"; if (tmpTrans.equals(EAIKeys.TR_REQ) || tmpTrans.equals(EAIKeys.TR_RE_REQ) || tmpTrans.equals(EAIKeys.TR_CANCEL_REQ)) { // 요청 거래 result = "0"; } else if (tmpTrans.equals(EAIKeys.TR_RES) || tmpTrans.equals(EAIKeys.TR_CANCEL_RES)) { // 응답거래 result = "1"; } return result; } public static String removeXMLHeader(String xmlMsg) { if (xmlMsg == null) { return ""; } else { xmlMsg = xmlMsg.trim(); } int sPos = xmlMsg.indexOf(""); // 중간에 있는 경우 - CDATA 의 내용 if (sPos == 0 && ePos > -1) { xmlMsg = xmlMsg.substring(ePos + 2); } return xmlMsg; } public static byte[] removeXMLHeader(byte[] xmlMsg) { return removeXMLHeader(new String(xmlMsg)).getBytes(); } public static String addXMLHeader(String encode, String xmlMsg) { if (xmlMsg != null) { xmlMsg = "" + xmlMsg; } return xmlMsg; } public static byte[] addXMLHeader(String encode, byte[] xmlMsg) throws UnsupportedEncodingException { return addXMLHeader(encode, new String(xmlMsg, encode)).getBytes(encode); } public static String removeXMLRootItem(String xmlString, String rootItemName) { String prefix = "<" + rootItemName + ">"; String suffix = ""; int s_idx = xmlString.indexOf(prefix); int e_idx = xmlString.indexOf(suffix); if (s_idx == -1 || e_idx == -1) { return xmlString; } else { return xmlString.substring(s_idx + prefix.length(), e_idx); } } public static boolean isBizDataEmpty(Object bizData) { boolean isEmpty = false; if (bizData == null) { isEmpty = true; } else { if (bizData instanceof byte[]) { if (((byte[]) bizData).length == 0) { isEmpty = true; } } else if (bizData instanceof String) { if (((String) bizData).length() == 0) { isEmpty = true; } } } return isEmpty; } public static String getTobeCode(String oldErrCode){ if ("".equals(oldErrCode)){ return STDMessageErrorKeys.SYSTEM_ERROR_CODE_VALUE; } if ("RECEAIOWP010".equals(oldErrCode)){ //책임자 승인 타임아웃 return STDMessageErrorKeys.APPROVE_ERROR_CODE_VALUE; } if ("RECEAIFBF010".equals(oldErrCode)){ //책임자 승인자가 존재하지 않는 오류 return STDMessageErrorKeys.APPROVE_NOT_FOUND_ERROR_CODE_VALUE; } if ("RECEAIIRP020,RECEAIIRP120,RECEAIIRP110".indexOf(oldErrCode) >= 0 ){ //유효값 오류 return STDMessageErrorKeys.VALID_VALUE_ERROR_CODE_VALUE; } if ("RECEAIAHA020".equals(oldErrCode)) { // 미로그인 에러 return STDMessageErrorKeys.NOT_LOGIN_ERROR_CODE_VALUE; } if ("RECEAIAHA021".equals(oldErrCode)) { // 중복로그인 에러 return STDMessageErrorKeys.DUP_LOGIN_ERROR_CODE_VALUE; } if ("RECEAIAHA022".equals(oldErrCode)) { // UUID가 같지 않은 에러 return STDMessageErrorKeys.UUID_MISMATCH_ERROR_CODE_VALUE; } if ("RECEAIIRP072".equals(oldErrCode)) { // 유량제어 초과 에러 return STDMessageErrorKeys.RATELIMIT_ERROR_CODE_VALUE; } if (EAIServiceMonitor.getInstance().isTimeOutCodes(oldErrCode)){ //TIMEOUT일경우 return STDMessageErrorKeys.TIMEOUT_ERROR_CODE_VALUE; }else if (EAIServiceMonitor.getInstance().isBizErrorCodes(oldErrCode)){ //업무오류일경우 return STDMessageErrorKeys.BIZ_ERROR_CODE_VALUE; }else{ return STDMessageErrorKeys.SYSTEM_ERROR_CODE_VALUE; } } public static String getTobeMessage(String oldErrCode){ if ("".equals(oldErrCode)){ return STDMessageErrorKeys.SYSTEM_ERROR_MSG_VALUE; } if ("RECEAIOWP010".equals(oldErrCode)){//책임자승인 타임아웃 return STDMessageErrorKeys.APPROVE_ERROR_MSG_VALUE; } if ("RECEAIFBF010".equals(oldErrCode)){ //책임자 승인자가 존재하지 않는 오류 return STDMessageErrorKeys.APPROVE_NOT_FOUND_ERROR_MSG_VALUE; } if ("RECEAIIRP020,RECEAIIRP120,RECEAIIRP110".indexOf(oldErrCode) >= 0 ){//유효값 오류 return STDMessageErrorKeys.VALID_VALUE_ERROR_MSG_VALUE; } if ("RECEAIAHA020".equals(oldErrCode)) { // 미로그인 에러 return STDMessageErrorKeys.NOT_LOGIN_ERROR_MSG_VALUE; } if ("RECEAIAHA021".equals(oldErrCode)) { // 중복로그인 에러 return STDMessageErrorKeys.DUP_LOGIN_ERROR_MSG_VALUE; } if ("RECEAIAHA022".equals(oldErrCode)) { // UUID가 같지 않은 에러 return STDMessageErrorKeys.UUID_MISMATCH_ERROR_MSG_VALUE; } if ("RECEAIIRP072".equals(oldErrCode)) { // 유량제어 초과 에러 return STDMessageErrorKeys.RATELIMIT_ERROR_MSG_VALUE; } if (EAIServiceMonitor.getInstance().isTimeOutCodes(oldErrCode) ){ //TIMEOUT일경우 return STDMessageErrorKeys.TIMEOUT_ERROR_MSG_VALUE; }else if (EAIServiceMonitor.getInstance().isBizErrorCodes(oldErrCode)){ //업무오류일경우 return STDMessageErrorKeys.BIZ_ERROR_MSG_VALUE; }else{ return STDMessageErrorKeys.SYSTEM_ERROR_MSG_VALUE; } } // TODO json tunning 요소 다시 확인해봐야됨(불필요한 파싱) public static String addJsonRootItem(String jsonString, String rootItemName) { JSONObject value = (JSONObject) JSONValue.parse(jsonString); JSONObject root = new JSONObject(); root.put(rootItemName, value); return root.toJSONString(); } // TODO json tunning 요소 다시 확인해봐야됨(불필요한 파싱) public static String removeJsonRootItem(String jsonString, String rootItemName) { JSONObject value = (JSONObject) JSONValue.parse(jsonString); JSONObject sub = (JSONObject) value.get(rootItemName); return sub.toJSONString(); } public static String toAdapterTypeString(Object data, String charset) throws Exception { if (data instanceof String) { return (String) data; } else if (data instanceof byte[]) { String encode = StringUtils.defaultIfBlank(charset, Charset.defaultCharset().name()); return new String((byte[]) data, encode); } else { throw new Exception("unsupported object - " + data.getClass()); } } public static boolean isBytesMessage(String messageType) { return StringUtils.equalsAny(messageType, MessageType.ASC, MessageType.EBC); } /** * 표준전문에 내외부구분이 없는 사이트를 고려하여 서비스정보(he01)에 internalExternalDvcd 추가
* 표준전문의 값을 우선으로 한다(없으면 서비스정보(he01)의 값으로 설정) */ public static String getInExDivision(String mapperValue, String eaiSvcValue) { if (StringUtils.isNotBlank(mapperValue)) { return mapperValue; } else { return eaiSvcValue; } } public static String makeErrorMessageByMessageType(String msgType, String msgCharset, String code, String msg, String errorFormat) { if (StringUtils.equals(msgType, MessageType.XML)) { return makeXmlErrorMessage(code, msg, msgCharset, errorFormat); } else { return makeJsonErrorMessage(code, msg, errorFormat); } } public static String makeJsonErrorMessage(String code, String msg) { return makeJsonErrorMessage(code, msg, null); } public static String makeXmlErrorMessage(String code, String msg, String charset) { return makeXmlErrorMessage(code, msg, charset, null); } public static String makeJsonErrorMessage(String code, String msg, String errorFormat) { if (StringUtils.isBlank(errorFormat)) { errorFormat = PropManager.getInstance().getProperty("MessageUtil", "ERROR_MESSAGE_DEFAULT_FORMAT", ERROR_MESSAGE_DEFAULT_FORMAT); } // errorFormat에 %s가 1개만 있으면 msg만, 2개 이상이면 code, msg 전달 int paramCount = StringUtils.countMatches(errorFormat, "%s"); if (paramCount == 1) { return String.format(errorFormat, JSONValue.escape(msg)); } else { return String.format(errorFormat, code, JSONValue.escape(msg)); } } public static String makeXmlErrorMessage(String code, String msg, String charset, String errorFormat) { if (StringUtils.isNotBlank(errorFormat)) { try { return String.format(errorFormat, StringUtils.defaultIfBlank(charset, "UTF-8"), code, msg); } catch (Exception e) { logger.error(e.getMessage()); } } return String.format( "%s%s", StringUtils.defaultIfBlank(charset, "UTF-8"), code, msg); } /** * XPath를 이용하여 XML 메시지에서 값을 추출 * @param xmlMessage XML 메시지 * @param xpath XPath 표현식 * @return 추출된 값 (실패 시 빈 문자열) */ public static String getXmlFldByXPath(String xmlMessage, String xpath) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new BufferedInputStream(new StringInputStream(xmlMessage))); XPath xPath = XPathFactory.newInstance().newXPath(); String value = (String) xPath.evaluate(xpath, document, XPathConstants.STRING); return value != null ? value.trim() : ""; } catch (Exception e) { logger.error("XPath 처리 중 오류 발생: " + e.getMessage()); return ""; } } /** * JSONPath를 이용하여 JSON 메시지에서 값을 추출 * @param json JSON 객체 * @param jsonPath JSONPath 표현식 * @return 추출된 값 (실패 시 빈 문자열) */ public static String getJSONValueByPath(Object json, String jsonPath) { try { if(json == null || jsonPath == null) return ""; JsonPath path = JsonPath.compile(jsonPath); Object result = path.read(json); if(result == null) return ""; // 결과가 기본 타입인 경우 if(result instanceof String || result instanceof Number || result instanceof Boolean) { return String.valueOf(result); } // JSON 객체나 배열인 경우 else if(result instanceof JSONObject || result instanceof JSONArray) { return result.toString(); } return ""; } catch (Exception e) { logger.error("JSONPath 처리 중 오류 발생: " + e.getMessage()); return ""; } } }