diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java index db918b9..b9bac4a 100644 --- a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java +++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java @@ -1,1355 +1,1398 @@ -package com.eactive.eai.adapter.http.client.impl; - -import java.io.IOException; -import java.io.StringReader; -import java.math.BigDecimal; -import java.net.ConnectException; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.eactive.eai.common.property.PropManager; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.StopWatch; -import org.apache.hc.client5.http.classic.HttpClient; -import org.apache.hc.client5.http.classic.methods.HttpDelete; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.classic.methods.HttpPut; -import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.NameValuePair; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicNameValuePair; -import org.apache.hc.core5.http.protocol.BasicHttpContext; -import org.apache.hc.core5.http.protocol.HttpContext; -import org.apache.hc.core5.net.URIBuilder; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; - -import com.eactive.eai.adapter.AdapterGroupVO; -import com.eactive.eai.adapter.AdapterManager; -import com.eactive.eai.adapter.AdapterPropManager; -import com.eactive.eai.adapter.http.HttpMemoryLogger; -import com.eactive.eai.adapter.http.HttpMethodType; -import com.eactive.eai.adapter.http.client.HttpClient5AdapterServiceSupport; -import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey; -import com.eactive.eai.adapter.http.client.HttpClientAdapterVO; -import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; -import com.eactive.eai.adapter.http.dynamic.filter.AdapterAllowIPListFilter; -import com.eactive.eai.adapter.http.dynamic.filter.ApiAuthFilter; -import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilter; -import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterType; -import com.eactive.eai.adapter.http.dynamic.filter.IpWhiteListFilter; -import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthFilter; -import com.eactive.eai.common.TransactionContextKeys; -import com.eactive.eai.common.authoutbound.AccessTokenManagerByDB; -import com.eactive.eai.common.exception.ExceptionUtil; -import com.eactive.eai.common.message.MessageType; -import com.eactive.eai.common.util.CommonLib; -import com.jayway.jsonpath.DocumentContext; -import com.jayway.jsonpath.JsonPath; -import com.openbanking.eai.common.token.AccessTokenManager; -import com.openbanking.eai.common.token.AccessTokenVO; -import com.openbanking.eai.common.token.OAuth2AccessTokenVO; - -import edu.emory.mathcs.backport.java.util.Arrays; - -// encrypt test by jwhong -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import com.kjbank.encrypt.exchange.crypto.AES256Cipher; -import com.kjbank.encrypt.exchange.crypto.AESCipher; -import com.nimbusds.jwt.SignedJWT; -import com.kjbank.encrypt.exchange.crypto.AES256GCMCipher; -import com.eactive.eai.authserver.service.OAuth2Manager; - - -/** - * 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는 - * 기능을 제공한다.
- * 2. 처리 개요 :
- * * - 2020-09-25: Http Header 받아서 처리할 수 있게 기능 추가
- * 3. 주의사항
- * - * @author : - * @version : v 1.0.0 - * @see : HttpClientAdapterServiceFactory.java, - * HttpClientAdapterServiceSupport.java - * @since : - * - */ -public class HttpClient5AdapterServiceRest extends HttpClient5AdapterServiceSupport - implements HttpClientAdapterServiceKey { - public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest"; - public static final String TYPE_SIMPLE_REQUEST = "simpleRequest"; - public static final String REST_OPTION = "REST_OPTION"; - //public static final String HEADER_CONTENT_TYPE = "Content-Type"; - public static final String HEADER_GROUP = "HEADER_GROUP"; - public static final String HTTP_STATUS = "HTTP_STATUS"; - public static final String HEADER_KEYS = "HEADER_KEYS"; - public static final String AUTH_TOKEN = "AUTH_TOKEN"; - - public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id"; // jwhong - - private boolean useAdapterToken; - private boolean encryptResponseApply; - - /** - * 1. 기능 : REST API 통신에 사용
- * 2. 처리 개요 : - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
- * 3. 주의사항
- * - * @param prop Http Adapter 속성 정보 - * @return 반환 된 Object - * @exception Exception 수동 시스템 간 통신 중 발생 - **/ - @SuppressWarnings({ "unchecked" }) - public Object execute(Properties prop, Object data, Properties tempProp) throws Exception { - HttpClientAdapterVO vo = super.setting(prop, tempProp); - - // 2025.04.09 Authorization 헤더값을 프로퍼티(AUTH_TOKEN)에서 지정하여 설정할 수 있도록 수정 - // 2025.05.29 프로퍼티 그룹 AUTH_TOKEN이 없을때 Null Point Exception 발생하여 수정 - String bizCode = ""; - String authToken = ""; - try { - Properties authProp = PropManager.getInstance().getProperties(AUTH_TOKEN); //Authorization - bizCode = vo.getAdapterGroupName().substring(1, 4); - authToken = authProp.getProperty(bizCode, ""); - } catch (Exception e) { - logger.debug("Property Group AUTH_TOKEN is not Exist !!"); - } - - logger.debug("authToken :::::::::::::::::::::::::::::::::::" + authToken); - - String headerGroupName = prop.getProperty(HEADER_GROUP); - String relayResponseHeaderKeys = prop.getProperty(HEADER_KEYS, ""); - useAdapterToken = StringUtils.equalsIgnoreCase(prop.getProperty("ADAPTER_TOKEN_USE_YN", "N"), "Y"); - - boolean useForwardProxy = StringUtils.equalsIgnoreCase(prop.getProperty("FORWARD_PROXY_USE_YN", "N"), "Y"); - String forwardProxyUrl = prop.getProperty("FORWARD_PROXY_URL"); - - // ex) $.dataHeader.GW_RSLT_CD - String tokenErrorCodeKey = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_KEY"); - String tokenErrorCodeValues = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_VALUES"); - String tokenErrorHttpStatusCode = prop.getProperty("ADAPTER_TOKEN_ERROR_HTTP_STATUS_CODE"); // 200 or 400번대 - - // 레이아웃 메시지 타입 REST URL 추출 시 활용. Default JSON - String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON); - String inboundMethod = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_METHOD, "POST"); - - //Outbound 요청에 대한 응답 메시지의 복호화 여부 결정위해 - encryptResponseApply = StringUtils.equalsIgnoreCase(prop.getProperty("ENCRYPT_RESPONSE_APPLY", "N"), "Y"); - - /** - * @formatter:off - * TSEAIHE02.RESTOPTION 정보 => JSON 형태로 구성 - * - type : simpleRequest, variableUrlRequest - * - extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL - * - method : get, delete, post, put - * - contentType: application/json(default), application/x-www-form-urlencoded - * - adapterTokenUseYn: Y, N(default) - * ex) - * {"type":"simpleRequest","extraPath":"v2.0/accout/balance","method":"post"} - * @formatter:on - */ - - String restOptionData = tempProp.getProperty(REST_OPTION); - - JSONObject restOptionObject = parseJson(restOptionData); - if (restOptionObject == null) { - throw new Exception("OptionData parsing result is NULL"); - } - - String rmethod = (String) restOptionObject.getOrDefault("method", inboundMethod); - String contentType = (String) restOptionObject.getOrDefault("contentType", "application/json"); - String adapterTokenUseYn = (String) restOptionObject.get("adapterTokenUseYn"); - if (StringUtils.isNotBlank(adapterTokenUseYn)) { // interface 에 설정된게 우선한다. - useAdapterToken = StringUtils.equalsIgnoreCase(adapterTokenUseYn, "Y"); - } - - HttpClient mclient = this.client; - String sendData = ""; - if (data instanceof String) { - sendData = (String) data; - } else if (data instanceof byte[]) { - sendData = new String((byte[]) data, vo.getEncode()); - } - - ////mclient.getParams().setContentCharset(vo.getEncode()); - - JSONObject dataObject = null; - Object httpHeader = null; - Object dataContent = null; - - if (MessageType.JSON.equals(messageType)) { - - Object parsed = parseJsonGeneric(sendData); - - if(parsed instanceof JSONObject) { - dataObject = parseJson(sendData); - if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) { - httpHeader = dataObject.get(headerGroupName); - dataObject.remove(headerGroupName); - } - - dataContent = dataObject; - if (dataObject.containsKey("innerList")) { - JSONArray innerList = (JSONArray) dataObject.get("innerList"); - dataContent = innerList; - } - } - } - -// if (MessageType.JSON.equals(messageType)) { -// dataObject = parseJson(sendData); -// if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) { -// httpHeader = dataObject.get(headerGroupName); -// dataObject.remove(headerGroupName); -// } -// } - - logger.debug("HttpClientAdapterServiceRest] dataObject1 = [" + dataObject + "]"); - - // interface 에 설정된게 우선한다. - String uri = null; - if (dataObject == null) { - uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData); - } else { - uri = changeUrl(messageType, vo.getUrl(), restOptionData, dataObject); - } - - logger.debug("HttpClientAdapterServiceRest] dataObject2 = [" + dataObject + "]"); - -// ////if (vo.getConnectionTimeout() != 0) { -// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(vo.getConnectionTimeout()); -// } - - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL=[" + vo.getUrl() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") PARAMETER_NAME=[" + vo.getParameterName() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") ENCODE=[" + vo.getEncode() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") RESPONSE_TYPE=[" + vo.getResponseType() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL_ENCODE_YN=[" + vo.getUrlEncodeYn() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") CONNECTION_TIMEOUT=[" + vo.getConnectionTimeout() + "] "); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") REST_OPTION=[" + restOptionData + "] "); - } - - HttpUriRequestBase method = null; - - - // 메소드 타입에 따라 HttpRequestBase 인스턴스 생성 - switch (HttpMethodType.getValue(rmethod)) { - case GET: - method = new HttpGet(uri); - break; - case DELETE: - method = new HttpDelete(uri); - break; - case POST: - method = new HttpPost(uri); - break; - case PUT: - method = new HttpPut(uri); - break; - default: - method = new HttpGet(uri); - break; - } - - RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); - - if(useForwardProxy) { - java.net.URL url = new java.net.URL(forwardProxyUrl); - - // 프로토콜, 호스트, 포트 추출 - String protocol = url.getProtocol(); - String host = url.getHost(); - int port = url.getPort(); - HttpHost proxy = new HttpHost(protocol,host, port); - requestConfigBuilder.setProxy(proxy); - } - - // OAuth2AccessToken check 부분을 뒤에서 여기로 위치를 옮김, 나이스지키미 암호화 KEY를 얻기 위해서. JWHONG - OAuth2AccessTokenVO accessToken = null; - String auth =""; - if (useAdapterToken) { - AccessTokenManagerByDB tokenManager = AccessTokenManagerByDB.getInstance(); - accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName()); - - // 토큰이 없거나 만료 됐으면 재발급 - if (accessToken == null || accessToken.isExpired()) { - String oldToken = accessToken == null ? null : accessToken.getAccessToken(); - accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop, - oldToken); - } - - if (logger.isDebug()) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") TOKEN = [" - + accessToken + "]"); - } - - Properties properties = AdapterPropManager.getInstance().getProperties(vo.getAdapterName()); // jwhong - String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong - if (useAdapterToken && "AES256-NICEON".equals(encryptAlgorithm)) { - String niceToken = accessToken.getAccessToken(); - String clientId = JwtClientIdExtractor(niceToken); - long currentTime = System.currentTimeMillis(); - auth = niceToken + ":" + currentTime + ":" + clientId ; - auth = Base64.getEncoder().encodeToString(auth.getBytes("UTF-8")); - - setNiceOnAuthHeaders(method, auth); - } else { - setAuthHeaders(method, accessToken); // 원래 있던 logic - } - - - if (logger.isDebug()) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() - + ") RequestHeader [Authorization=" + method.getHeader("Authorization") + "]"); - } - } - - if(!StringUtils.isBlank(authToken)) { - setAuthHeaders(method, authToken); - } - // 여기 까지 - - configureHttpClient(requestConfigBuilder, vo, method); - - switch (HttpMethodType.getValue(rmethod)) { - case GET: - case DELETE: - HashMap h = getParameters(dataObject); - URIBuilder uriBuilder = new URIBuilder(uri); - for (Map.Entry entry : h.entrySet()) { - uriBuilder.addParameter(entry.getKey(), entry.getValue()); - } - URI fullUri = uriBuilder.build(); - if (method instanceof HttpGet) { - ((HttpGet) method).setUri(fullUri); - } else if (method instanceof HttpDelete) { - ((HttpDelete) method).setUri(fullUri); - } - if (logger.isDebug()) { - logger.debug("HttpClientAdapterServiceRest] (get Method) QueryString = [" + fullUri.getQuery() + "]"); - } - break; - case PUT: - case POST: -// assignPostBody(dataObject, contentType, vo.getEncode(), method); - //assignPostBody(dataContent, contentType, vo.getEncode(), method); // jwhong commnet - assignPostBody(dataContent, contentType, vo.getEncode(), method, vo.getAdapterName(), auth); - break; - default: - break; - } - - if (logger.isDebugEnabled()) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") method.getParams()=[" - + method.getEntity() + "] "); - } - - // OAuth2AccessToken 원래 있던 위치 JWHONG - - // 전달 header 셋팅 - // Adapter 레벨 header 보다 data로 넘어온 httpHeader를 우선 적용(header명이 같다면 덮어씀) - assignRequestHeaders(method, httpHeader); - - int status = -1; - - try { - byte[] responseMessage = null; - byte[] responseMessageOri = null; - Header[] responseHeaders; - - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - if (dataObject != null) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" - + dataObject.toJSONString() + "]"); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = " - + CommonLib.getDumpMessage(dataObject.toJSONString())); - } else { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" + sendData - + "]"); - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = " - + CommonLib.getDumpMessage(sendData)); - } - } - StopWatch stopWatch = new StopWatch(); - stopWatch.start(); - - if (vo.getTraceLevel() >= 3) { - HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(), - "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData)); - } - - String uuid = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID); - HttpContext context = new BasicHttpContext(); - context.setAttribute(TransactionContextKeys.TRANSACTION_UUID, uuid); - context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, vo.getAdapterGroupName()); - context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME, vo.getAdapterName()); - Integer logProcessNo = (Integer) tempProp.get(HttpClientAdapterServiceKey.LOG_PROCESS_NO); - if (logProcessNo != null && logProcessNo > 0) { - context.setAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO, logProcessNo); - } - - // encrypt algorithm type 추출 from adapter property jwhong - Properties properties = AdapterPropManager.getInstance().getProperties(vo.getAdapterName()); // jwhong - String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong - - try { - if (logger.isDebug()) { - logger.debug("[method getName]" + method.getMethod()); - logger.debug("[method getEntity]" + method.getEntity()); - logger.debug("[method getRequestHeaders]" + method.getHeaders().toString()); - logger.debug("[method getURI]" + method.getPath()); - } - try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method, context)) { - status = response.getCode(); - - //responseMessage = EntityUtils.toByteArray(response.getEntity()); - // 역기서 responseMessage를 decryption 해야 하나 by jwhong - - responseMessageOri = EntityUtils.toByteArray(response.getEntity()); - System.out.println("responseMessageOri 바이트 배열 길이: " + responseMessageOri.length); - - responseMessage = doOutboundPostFilter(responseMessageOri, encryptAlgorithm, vo.getAdapterName(), accessToken); // jwhong - // 여기까지 - - responseHeaders = response.getHeaders(); - - if (logger.isDebug()) { - logger.debug("[received status]" + status); - logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + responseMessage + "]"); - } - } - } catch (ConnectException e) { - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType()); - } - throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage()); - } - - stopWatch.stop(); - - /** - * @formatter:off - * OAuth 토큰 응답 체크(Adapter properties로 설정) - * 응답코드에 따라 유효한 토큰 확인(토큰 재발급 여부 확인) - * API 서비스 마다 정책이 다름(보통 400대에서 체크하나 200에서도 체크할 수 있음) - * - * TOKEN_ERROR_CODE_KEY: 응답 json error code key - * __ex) $.dataHeader.resultCode - * TOKEN_ERROR_CODE_VALUES: 토큰 재발급이 필요한 응답 error codes(ex: O0001,O0002,O0003) - * TOKEN_ERROR_HTTP_STATUS_CODE: 보통 400대에서 체크하나 API 제공자에 따라 200에서도 체클할수 있음 - * ex) TOKEN_ERROR_HTTP_STATUS_CODE = 200 - * @formatter:on - */ - boolean needReissue = false; - - Properties responseHeaderProp = assignRelayDataToInbound(tempProp, responseHeaders); - String responseString = new String(responseMessage, vo.getEncode()); - - Map map = new HashMap(); - tempProp.put(HttpAdapterServiceKey.OUTBOUND_PROPERTY_MAP, map); - map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_HEADERS, responseHeaderProp); - map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_MESSAGE, responseString); - map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_STATUS, status); - - if (status >= 200 && status <= 207) { - if (useAdapterToken && StringUtils.equals(tokenErrorHttpStatusCode, "200")) { - needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues, - vo.getEncode()); - } - } else if (status == 302) { - if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) { - relayResponseHeaderKeys += ",Location"; - } - } else { - String errMsg = String.format( - "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s", - status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseString); -// logger.error(errMsg); - - if (status >= 400 && status < 500) { - if (useAdapterToken) { - needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues, - vo.getEncode()); - } - - if (!needReissue) { - throw new Exception(errMsg); - } - } else { - - throw new Exception(errMsg); - } - } - - // ---------------------------------------------------------- - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType()); - logger.debug("HttpClientAdapterServiceRest] RECV " + vo.getEncode() + "(" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]"); -// logger.debug("HttpClientAdapterServiceRest] RECV MS949 (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "MS949") + "]"); -// logger.debug("HttpClientAdapterServiceRest] RECV euc-kr (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "euc-kr") + "]"); - logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = " + CommonLib.getDumpMessage(responseMessage)); - } - - if (useAdapterToken) { - if (responseMessage == null) { - throw new Exception("responseMessage is NULL, HttpStatus=" + status); - } - - // OAuth 토큰 재요청 코드 확인 - if (needReissue) { - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] retry access token response code = [" - + vo.getResponseType() + "] message = [" + new String(responseMessage, vo.getEncode()) - + "]"); - } - - // 토큰 재발급 - AccessTokenManager tokenManager = AccessTokenManager.getInstance(); - String oldToken = accessToken == null ? null : accessToken.getAccessToken(); - OAuth2AccessTokenVO newaccessToken = (OAuth2AccessTokenVO) tokenManager - .retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken); - method.setHeader("Authorization", newaccessToken.getAuthorization()); - - setAuthHeaders(method, newaccessToken); - - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() - + ") RETRY TOKEN = [" + newaccessToken + "]"); - } - - try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method)) { - status = response.getCode(); - responseMessage = EntityUtils.toByteArray(response.getEntity()); - // 여기서도 decryption 해야 할듯 하나.. by jwhong - - if (logger.isDebug()) { - logger.debug("[received status]" + status); - logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]"); - } - }catch (IOException e){ - throw new Exception("retry excuteMethod Exceptioin = " + e.getMessage()); - } - - - if (status == 302) { - if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) { - relayResponseHeaderKeys += ",Location"; - } - } else { - String errMsg = String.format( - "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s", - status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage); - throw new Exception(errMsg); - } - - // ---------------------------------------------------------- - if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { - logger.debug("HttpClientAdapterServiceRest] RETRY responseType =" + vo.getResponseType()); - logger.debug("HttpClientAdapterServiceRest] RETRY RECV " + vo.getEncode() + "(" - + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) - + "]"); - logger.debug("HttpClientAdapterServiceRest] RETRY RECV (" + vo.getAdapterGroupName() + ") = " - + CommonLib.getDumpMessage(responseMessage)); - } - // ---------------------------------------------------------- - } - } - - if (vo.getTraceLevel() >= 3) { - HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(), - "RECV [" + new String(responseMessage, vo.getEncode()) + "]" - + CommonLib.getDumpMessage(responseMessage)); - } - - - return assignResponseHeaders(method, responseMessage, headerGroupName, vo.getEncode(), messageType, - relayResponseHeaderKeys, status, responseHeaderProp); - } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우 - if (vo.getTraceLevel() >= 3) { - HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), - "HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : " - + ste.toString(), - ste); - } - logger.error("HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : " - + ste.toString(), ste); - throw ste; - } catch (ConnectException ce) { - if (vo.getTraceLevel() >= 3) { - HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), - "HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : " - + ce.toString(), - ce); - } - logger.error("HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : " - + ce.toString(), ce); - throw ce; - } catch (Exception e) { - if (vo.getTraceLevel() >= 3) { - HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), e.toString(), e); - } - logger.error("HttpClientAdapterServiceRest] Exception (" + vo.getAdapterGroupName() + ") : " + e.toString(), - e); - throw e; - } finally { - if (status != HttpStatus.SC_OK) { - String[] msgArgs = new String[1]; - msgArgs[0] = String.valueOf(status); - String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs); - if (logger.isDebug()) { - logger.debug(resMsg); - } - } - } - } - - private Properties assignRelayDataToInbound(Properties prop, Header[] responseHeaders) { - Properties headerProp = new Properties(); - if (responseHeaders == null || responseHeaders.length == 0) { - return headerProp; - } - - for (Header header : responseHeaders) { - headerProp.put(header.getName(), header.getValue()); - } - - return headerProp; - } - - /** - * 현재 1단계 레이아웃에만 적용되도록 구현됨. - * - * @param method - * @param responseMessage - * @param headerGroupName - * @param encode - * @param messageType - * @param relayHeaderKeys - * @return - * @throws Exception - */ - @SuppressWarnings("unchecked") - private String assignResponseHeaders(HttpUriRequestBase method, byte[] responseMessage, String headerGroupName, - String encode, String messageType, String relayHeaderKeys, int status, Properties responseHeaderProp) throws Exception { - if (!MessageType.JSON.equals(messageType) || StringUtils.isBlank(headerGroupName) - || StringUtils.isBlank(relayHeaderKeys)) { - return new String(responseMessage, encode); - } - - String[] relayKeyArr = org.springframework.util.StringUtils.tokenizeToStringArray(relayHeaderKeys, ","); - JSONObject headerJson = new JSONObject(); - for (String key : relayKeyArr) { - String value = responseHeaderProp.getProperty(key); - if (StringUtils.isNotBlank(value)) { - headerJson.put(key, value); - } - } - - headerJson.put(HTTP_STATUS, String.valueOf(status)); - - if (headerJson.size() <= 0) { - return new String(responseMessage, encode); - } - - JSONObject message = null; - if (responseMessage == null || responseMessage.length == 0) { - message = new JSONObject(); - } else { - message = parseJson(new String(responseMessage, encode)); - if (message == null) { - message = new JSONObject(); - message.put("Malformed_Response_Message", new String(responseMessage, encode)); - } - } - - if (StringUtils.isNotBlank(headerGroupName) && message != null) - message.put(headerGroupName, headerJson); - return message.toJSONString(); - } - - private void setAuthHeaders(HttpUriRequestBase method, String authorization) throws Exception { - method.setHeader("Authorization", - String.format("%s", authorization)); - } - - private void setAuthHeaders(HttpUriRequestBase method, OAuth2AccessTokenVO accessToken) throws Exception { - method.setHeader("Authorization", - String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken())); - } - - /* nice on 나이스 지키미 용으로 생성함 - * jwhong 2015-11-04 - */ - private void setNiceOnAuthHeaders(HttpUriRequestBase method, String auth) throws Exception { - method.setHeader("Authorization", - String.format("%s %s", AccessTokenVO.BEARER_TYPE, auth)); // 나이스지키미 format임 - method.setHeader("ProductID", "2303345072"); - //method.setHeader("Authorization", - // String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken())); - } - - /* nice clientid 추출을 위하여 추가한 내용임. jwhong - * - */ - private String JwtClientIdExtractor(String inboundToken) { - - String tokenClientId =""; - try { - SignedJWT signedJWT = SignedJWT.parse(inboundToken); - tokenClientId = (String) signedJWT.getJWTClaimsSet().getClaim(PAYLOAD_PARAM_NAME_CLIENT_ID); - } catch (Exception e) { - logger.error(e.getMessage()); - tokenClientId = ""; - } - - System.out.println("Token Client ID: " + tokenClientId); - return tokenClientId; - - } - - - private boolean checkTokenRetry(byte[] responseMessage, String tokenErrorCodeKey, String tokenErrorCodeValues, - String encode) { - if (responseMessage == null) { - return false; - } - - if (StringUtils.isBlank(tokenErrorCodeKey)) { - return false; - } - - if (StringUtils.isBlank(tokenErrorCodeValues)) { - return false; - } - - try { - DocumentContext jsonContext = JsonPath.parse(new String(responseMessage, encode)); - String responseCode = jsonContext.read(tokenErrorCodeKey); - if (StringUtils.isBlank(responseCode)) { - return false; - } - - String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenErrorCodeValues, ","); - return ArrayUtils.contains(arr, responseCode); - } catch (Exception e) { - logger.error("HttpClientAdapterServiceRest] checkTokenRetry error=" + e.getMessage()); - } - - return false; - } - - private void assignRequestHeaders(HttpUriRequestBase method, Object httpHeader) { - if (httpHeader == null) { - return; - } - - if (httpHeader instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) httpHeader; - for (Object key : jsonObject.keySet()) { - Object obj = jsonObject.get(key); - if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) { - continue; - } - - method.setHeader((String) key, (String) obj); - - if (logger.isDebugEnabled()) { - logger.debug("Request Header :" + (String) key + "=[" + (String) obj + "]"); - } - - } - } - } - - @SuppressWarnings("deprecation") - private void assignPostBody(Object eaiBody, String contentType, String charset, HttpUriRequestBase method, String adapterName, String niceAuth) { - if (eaiBody == null) { - return; - } - - if (StringUtils.contains(contentType, "application/x-www-form-urlencoded")) { - if (eaiBody instanceof JSONObject) { - List params = new ArrayList<>(); - JSONObject jsonObject = (JSONObject) eaiBody; - for (Object key : jsonObject.keySet()) { - //String encryptedValue = encrypt((String) jsonObject.get(key)); // encrypt by jwhong - //params.add(new BasicNameValuePair((String) key, encryptedValue )); - params.add(new BasicNameValuePair((String) key, (String) jsonObject.get(key))); - } - - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8); - method.setEntity(entity); - } - } else { - ContentType contentTypeObj = ContentType.create(contentType, charset); - - String eaiBodyMessage = doOutboundPreFilter(eaiBody, adapterName, niceAuth); // jwhong - StringEntity entity = new StringEntity(eaiBodyMessage, contentTypeObj); - // 요청 본문을 StringEntity 객체로 생성 - //StringEntity entity = new StringEntity(eaiBody.toString(), contentTypeObj); - - // 요청에 본문 추가 - method.setEntity(entity); - } - } - - // from here by jwhong - private String doOutboundPreFilter(Object eaiBody, String adapterName, String niceAuth) { - - Properties properties = AdapterPropManager.getInstance().getProperties(adapterName); // jwhong - String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong - //String encryptBaseKeyType = properties.getProperty("ENCRYPT_BASE_TYPE"); - String encryptClientId = properties.getProperty("ENCRYPT_CLIENT_ID"); - String encryptAES256Iv = properties.getProperty("ENCRYPT_AES256_IV"); - String encryptAES256Key = properties.getProperty("ENCRYPT_AES256_KEY"); - - // outbound encrypt 는 SecretKey 또는 NICE-auth 가 암호화 key로 사용된다. - // 참고로 inbound encrypt 에는 Token 또는 SecretKey 가 암호화 key로 사용된다. - // 여기에 NICE-auth 뭔지 파악하여 logic 추가해야 한다. - OAuth2Manager manager = OAuth2Manager.getInstance(); - ClientDetails clientDetail = manager.getClientDeatilsStore().get(encryptClientId); - String clientSecret = ""; - if ( clientDetail != null ) { // not null 이라는 것은 APIM Oauth Server에 등록된 client ID 이다. - // 이건 KJBank로 Outbound 나가는 것임 - clientSecret = clientDetail.getClientSecret(); - } else { // 그럼 업체로 Outbound 나가는것은, 업체에서 사용하는 secretkey를 사용한다. - clientSecret = encryptClientId; - } - - // Nice-auth , token 값을 substring 해서 사용한다. 나이스 지키미는 adapter token에서 추출된 token을 사용한다. - if (useAdapterToken && "AES256-NICEON".equals(encryptAlgorithm)) { - clientSecret = niceAuth; - } - - // 여기서 SECRETY인지 nice-auth 인지 check 하여 clientSecret 값을 정하는 logic 추가하여 넘겨야한다. - - String responseMessage = doOutboundPreEncrypt(eaiBody, encryptAlgorithm, clientSecret, encryptAES256Iv, encryptAES256Key); - return responseMessage; - - } - private String doOutboundPreEncrypt(Object eaiBody, String encryptAlgorithm, String clientSecretKey, String encryptAES256Iv, String encryptAES256Key ) { - - String encryptedMessage = ""; - String encryptedJsonKey = ""; - - encryptedJsonKey = getJsonKey(encryptAlgorithm); - - switch (encryptAlgorithm) { - case "AES": - encryptedMessage = encrypt(eaiBody.toString()); // encrypt by jwhong - break; - case "AES128-TOSS": - try { - String key = clientSecretKey.substring(22,38); - encryptedMessage = AESCipher.encrypt(eaiBody.toString(), key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); - } - break; - case "AES128-TOGETHER": - try { - String key = clientSecretKey.substring(44,60); - encryptedMessage = AESCipher.encrypt(eaiBody.toString(), key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); - } - break; - case "AES256": - try { - String key = clientSecretKey.substring(10,42); - encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256-KAKAO": - try { - encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), encryptAES256Iv, encryptAES256Key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256-TOSS": - try { - encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), encryptAES256Iv, encryptAES256Key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256-NICEON": - try { - String key = clientSecretKey.substring(10,42); - encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), key); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256GCM": - try { - byte[] key = AES256GCMCipher.generateKey(); - AES256GCMCipher cipher = new AES256GCMCipher(key); - byte[] aad = "metadata".getBytes(); - - encryptedMessage = cipher.encrypt(eaiBody.toString(), aad); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256GCM Encryption error=" + e.getMessage()); - } - break; - default: - encryptedMessage = eaiBody.toString(); - return encryptedMessage; - //break; - } - - Map map = new HashMap<>(); - map.put(encryptedJsonKey, encryptedMessage); - JSONObject json = new JSONObject(); - json.putAll(map); - return json.toJSONString(); - //return encryptedMessage; - } - - - private byte[] doOutboundPostFilter(byte[] eaiBody, String decryptAlgorithm, String adapterName, OAuth2AccessTokenVO niceAccessToken ) { - - if ( !encryptResponseApply) { - return eaiBody; - } - - Properties properties = AdapterPropManager.getInstance().getProperties(adapterName); // jwhong - //String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong - //String encryptBaseKeyType = properties.getProperty("ENCRYPT_BASE_TYPE"); - String encryptClientId = properties.getProperty("ENCRYPT_CLIENT_ID"); - String encryptAES256Iv = properties.getProperty("ENCRYPT_AES256_IV"); - String encryptAES256Key = properties.getProperty("ENCRYPT_AES256_KEY"); - - // outbound encrypt 는 SecretKey 또는 NICE-auth 가 암호화 key로 사용된다. - OAuth2Manager manager = OAuth2Manager.getInstance(); - ClientDetails clientDetail = manager.getClientDeatilsStore().get(encryptClientId); - String clientSecret = ""; - if ( clientDetail != null ) { - clientSecret = clientDetail.getClientSecret(); - } else { - clientSecret = encryptClientId; - } - - // Nice-auth , token 값을 substring 해서 사용한다. 나이스 지키미는 adapter token에서 추출된 token을 사용한다. - if (useAdapterToken && "AES256-NICEON".equals(decryptAlgorithm)) { - clientSecret = niceAccessToken.getAccessToken(); - } - - byte[] resPostMessage = doOutboundPostDecrypt(eaiBody, decryptAlgorithm, clientSecret, encryptAES256Iv, encryptAES256Key); - return resPostMessage; - } - - private byte[] doOutboundPostDecrypt(byte[] eaiBody, String decryptAlgorithm, String clientSecretKey, String encryptAES256Iv, String encryptAES256Key ) { - - byte[] decryptedMessage = null; - String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); - - eaiStringBody = extractBodyMsg(decryptAlgorithm, eaiStringBody); - - //test source - System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); - System.out.println("Base64 문자열: " + eaiStringBody); - System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); - System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); - - // Base64 디코딩 테스트 - try { - byte[] decoded = Base64.getDecoder().decode(eaiStringBody); - System.out.println("디코딩 성공, 길이: " + decoded.length); - } catch (IllegalArgumentException e) { - System.out.println("Base64 디코딩 실패: " + e.getMessage()); - } - // end test source - - switch (decryptAlgorithm) { - case "AES": - decryptedMessage = decrypt(eaiBody); // encrypt by jwhong - break; - case "AES128-TOSS": - try { - String key128 = clientSecretKey.substring(22,38); - String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); - } - break; - case "AES128-TOGETHER": - try { - String key128 = clientSecretKey.substring(44,60); - String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); - } - break; - case "AES256": - try { - String key = clientSecretKey.substring(10,42); - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); - } - break; - case "AES256-KAKAO": - try { - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, encryptAES256Iv, encryptAES256Key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256-TOSS": - try { - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, encryptAES256Iv, encryptAES256Key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); - } - break; - case "AES256-NICEON": - try { - String key = clientSecretKey.substring(10,42); - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); - } - break; - case "AES256GCM": - try { - byte[] key = AES256GCMCipher.generateKey(); - AES256GCMCipher cipher = new AES256GCMCipher(key); - byte[] aad = "metadata".getBytes(); - String decryptedStrMessage = cipher.decrypt(eaiStringBody, aad); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); - } - break; - default: - try { - decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); - } - break; - } - - return decryptedMessage; - } - - - private String extractBodyMsg(String decryptAlgorithm, String eaiStringBody) { - - String decryptedJsonKey = ""; - String decryptedBodyMessage = ""; - - decryptedJsonKey = getJsonKey(decryptAlgorithm); - - try { - JSONParser parser = new JSONParser(); - JSONObject jsonObject = (JSONObject) parser.parse(eaiStringBody); - decryptedBodyMessage = (String) jsonObject.get(decryptedJsonKey); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClient5AdapterServiceRest] extractBodyMsg error : " + e.getMessage()); - } - - return decryptedBodyMessage; - - } - - private String getJsonKey(String Algorithm) { - - String jsonKey = ""; - - switch (Algorithm) { - case "AES128-TOSS": - jsonKey = "preScreeningRequest"; - break; - case "AES128-TOGETHER": - jsonKey = "obpTxData"; - break; - case "AES256": - jsonKey = "preScreeningRequest"; - break; - case "AES256-KAKAO": - jsonKey = "encrypted_data"; - break; - case "AES256-TOSS": - jsonKey = "encryptedData"; - break; - case "AES256-NICEON": - jsonKey = "preScreeningRequest"; - break; - case "AES256GCM": - break; - default: - break; - } - return jsonKey; - } - // by jwhong - private String encrypt(String plainText) { - try { - SecretKeySpec key = new SecretKeySpec("1234567890123456".getBytes(), "AES"); - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, key); - byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); - return Base64.getEncoder().encodeToString(encrypted); - } catch (Exception e) { - // 예외 로그 출력 또는 사용자 정의 처리 - e.printStackTrace(); - return null; // 또는 에러 메시지 반환 - } - } - - - public static byte[] decrypt(byte[] encryptedBytes) { - try { - // byte[] --> Base64 문자열로 변환 - String encryptedText = new String(encryptedBytes, StandardCharsets.UTF_8).trim(); - // 암호화에 사용한 키와 동일한 키 사용 - SecretKeySpec key = new SecretKeySpec("1234567890123456".getBytes(), "AES"); - - // 암호화와 동일한 알고리즘 설정 - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.DECRYPT_MODE, key); - - // Base64로 인코딩된 문자열을 디코딩 - byte[] decodedBytes = Base64.getDecoder().decode(encryptedText); - - // 복호화 수행 - byte[] decryptedBytes = cipher.doFinal(decodedBytes); - - // UTF-8 문자열로 변환하여 반환 - //return new String(decryptedBytes, StandardCharsets.UTF_8); - //복호화된 바이트 배열 반환 - return decryptedBytes; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - - private HashMap getParameters(Object message) throws Exception { - - HashMap result = new HashMap(); - - if (message != null) { - if (message instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) message; - for (Object key : jsonObject.keySet()) { - Object obj = jsonObject.get(key); - if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) { - continue; - } - result.put((String) key, getStringValue(obj)); - } - } else { - String[] messages = ((String) message).split("&"); - String[] data = null; - - for (int i = 0; i < messages.length; i++) { - data = messages[i].split("=", 2); - if (data.length == 2) { - result.put(data[0], data[1]); - } - } - } - } - - return result; - } - - public String getStringValue(Object obj) { - if (obj == null) { - return null; - } - - if (obj instanceof String) { - return (String) obj; - } else if (obj instanceof Long) { - return Long.toString((Long) obj); - } else if (obj instanceof BigDecimal) { - return ((BigDecimal) obj).toPlainString(); - } else { - return (String) obj; - } - } - - public static Object parseJsonGeneric(String jsonData) { - if (StringUtils.isBlank(jsonData)) { - return null; - } - - try { - JSONParser parser = new JSONParser(); - Object parsedObj = parser.parse(jsonData); - return parsedObj; - } catch (ParseException e) { - e.printStackTrace(); - return null; - } - } - - @SuppressWarnings("deprecation") - private JSONObject parseJson(String message) throws Exception { - if (message == null) { - return null; - } - - return (JSONObject) JSONValue.parse(message); - } - - private Document convertXmlDocument(String message) throws Exception { - SAXReader builder = new SAXReader(); - Document document = builder.read(new StringReader(message)); - return document; - } - - @SuppressWarnings("deprecation") - private String changeUrl(String messageType, String url, String restOption, Object sendData) { - if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) { - try { - if (StringUtils.isBlank(restOption)) { - return url; - } - List urlVariableList = new ArrayList(); - JSONObject restOptionObject = parseJson(restOption); - - if (restOptionObject == null) - throw new Exception("restOption is NULL"); - - String type = (String) restOptionObject.get("type"); - String requestExtraPath = (String) restOptionObject.get("extraPath"); - url = getUrl(url, requestExtraPath); - if (TYPE_VARIABLE_URL_REQUEST.equals(type)) { - Pattern p = Pattern.compile("\\{(.*?)\\}"); - Matcher m = p.matcher(requestExtraPath); - List uriVariables = new ArrayList<>(); - while(m.find()) { - String fieldName = m.group(1); - uriVariables.add(fieldName); - } - if (MessageType.JSON.equals(messageType)) { - JSONObject jsonObject; - if (sendData instanceof JSONObject) { - jsonObject = (JSONObject) sendData; - } else { - jsonObject = (JSONObject) JSONValue.parse((String) sendData); - } - for (Object tempObject : uriVariables) { - String urlVaribleId = (String) tempObject; - String uriVariable = (String) jsonObject.get(urlVaribleId); - urlVariableList.add(uriVariable); - jsonObject.remove(urlVaribleId); - } - } else if (MessageType.XML.equals(messageType)) { - Document doc; - if (sendData instanceof Document) { - doc = (Document) sendData; - } else { - doc = convertXmlDocument((String) sendData); - } - for (Object tempObject : uriVariables) { - String urlVaribleId = (String) tempObject; - Element element = (Element) doc.selectSingleNode("//" + urlVaribleId); - urlVariableList.add(element.getText()); - if (doc.getRootElement() == element) { - doc = null; - } else { - element.getParent().remove(element); - } - } - } - if (urlVariableList.size() > 0) { - UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build(); - Object[] urls = urlVariableList.toArray(); - url = uriComponents.expand(urls).toUriString(); - logger.debug("HttpClientAdapterServiceRest] after extand url=[" + url + "] "); - } - } - } catch (Exception e) { - logger.error("Failed to change url", e); - } - } - return url; - } - - private String getUrl(String baseUrl, String extraPath) { - if (StringUtils.isBlank(extraPath)) { - return baseUrl; - } - - if (StringUtils.contains(extraPath, "http://") || StringUtils.contains(extraPath, "https://")) { - return extraPath; - } - - String targetUrl = baseUrl; - if (!targetUrl.endsWith("/")) { - targetUrl += "/"; - } - if (extraPath.startsWith("/")) { - targetUrl += extraPath.substring(1); - } else { - targetUrl += extraPath; - } - - logger.debug("HttpClientAdapterServiceRest] after concatenate url=[" + targetUrl + "] "); - return targetUrl; - } -} +package com.eactive.eai.adapter.http.client.impl; + +import java.io.IOException; +import java.io.StringReader; +import java.math.BigDecimal; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.eactive.eai.common.property.PropManager; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.StopWatch; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpDelete; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.apache.hc.core5.http.protocol.BasicHttpContext; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.net.URIBuilder; +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import com.eactive.eai.adapter.AdapterGroupVO; +import com.eactive.eai.adapter.AdapterManager; +import com.eactive.eai.adapter.AdapterPropManager; +import com.eactive.eai.adapter.http.HttpMemoryLogger; +import com.eactive.eai.adapter.http.HttpMethodType; +import com.eactive.eai.adapter.http.client.HttpClient5AdapterServiceSupport; +import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey; +import com.eactive.eai.adapter.http.client.HttpClientAdapterVO; +import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; +import com.eactive.eai.adapter.http.dynamic.filter.AdapterAllowIPListFilter; +import com.eactive.eai.adapter.http.dynamic.filter.ApiAuthFilter; +import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilter; +import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterType; +import com.eactive.eai.adapter.http.dynamic.filter.IpWhiteListFilter; +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthFilter; +import com.eactive.eai.common.TransactionContextKeys; +import com.eactive.eai.common.authoutbound.AccessTokenManagerByDB; +import com.eactive.eai.common.exception.ExceptionUtil; +import com.eactive.eai.common.message.MessageType; +import com.eactive.eai.common.util.CommonLib; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.openbanking.eai.common.token.AccessTokenManager; +import com.openbanking.eai.common.token.AccessTokenVO; +import com.openbanking.eai.common.token.OAuth2AccessTokenVO; + +import edu.emory.mathcs.backport.java.util.Arrays; + +// encrypt test by jwhong +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; +import com.nimbusds.jwt.SignedJWT; +import com.kjbank.encrypt.exchange.crypto.AES256GCMCipher; +import com.eactive.eai.authserver.service.OAuth2Manager; +import java.util.Set; + + +/** + * 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는 + * 기능을 제공한다.
+ * 2. 처리 개요 :
+ * * - 2020-09-25: Http Header 받아서 처리할 수 있게 기능 추가
+ * 3. 주의사항
+ * + * @author : + * @version : v 1.0.0 + * @see : HttpClientAdapterServiceFactory.java, + * HttpClientAdapterServiceSupport.java + * @since : + * + */ +public class HttpClient5AdapterServiceRest extends HttpClient5AdapterServiceSupport + implements HttpClientAdapterServiceKey { + public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest"; + public static final String TYPE_SIMPLE_REQUEST = "simpleRequest"; + public static final String REST_OPTION = "REST_OPTION"; + //public static final String HEADER_CONTENT_TYPE = "Content-Type"; + public static final String HEADER_GROUP = "HEADER_GROUP"; + public static final String HTTP_STATUS = "HTTP_STATUS"; + public static final String HEADER_KEYS = "HEADER_KEYS"; + public static final String AUTH_TOKEN = "AUTH_TOKEN"; + + public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id"; // jwhong + + private boolean useAdapterToken; + private boolean encryptResponseApply; + + /** + * 1. 기능 : REST API 통신에 사용
+ * 2. 처리 개요 : - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+ * 3. 주의사항
+ * + * @param prop Http Adapter 속성 정보 + * @return 반환 된 Object + * @exception Exception 수동 시스템 간 통신 중 발생 + **/ + @SuppressWarnings({ "unchecked" }) + public Object execute(Properties prop, Object data, Properties tempProp) throws Exception { + HttpClientAdapterVO vo = super.setting(prop, tempProp); + + // 2025.04.09 Authorization 헤더값을 프로퍼티(AUTH_TOKEN)에서 지정하여 설정할 수 있도록 수정 + // 2025.05.29 프로퍼티 그룹 AUTH_TOKEN이 없을때 Null Point Exception 발생하여 수정 + String bizCode = ""; + String authToken = ""; + try { + Properties authProp = PropManager.getInstance().getProperties(AUTH_TOKEN); //Authorization + bizCode = vo.getAdapterGroupName().substring(1, 4); + authToken = authProp.getProperty(bizCode, ""); + } catch (Exception e) { + logger.debug("Property Group AUTH_TOKEN is not Exist !!"); + } + + logger.debug("authToken :::::::::::::::::::::::::::::::::::" + authToken); + + String headerGroupName = prop.getProperty(HEADER_GROUP); + String relayResponseHeaderKeys = prop.getProperty(HEADER_KEYS, ""); + useAdapterToken = StringUtils.equalsIgnoreCase(prop.getProperty("ADAPTER_TOKEN_USE_YN", "N"), "Y"); + + boolean useForwardProxy = StringUtils.equalsIgnoreCase(prop.getProperty("FORWARD_PROXY_USE_YN", "N"), "Y"); + String forwardProxyUrl = prop.getProperty("FORWARD_PROXY_URL"); + + // ex) $.dataHeader.GW_RSLT_CD + String tokenErrorCodeKey = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_KEY"); + String tokenErrorCodeValues = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_VALUES"); + String tokenErrorHttpStatusCode = prop.getProperty("ADAPTER_TOKEN_ERROR_HTTP_STATUS_CODE"); // 200 or 400번대 + + // 레이아웃 메시지 타입 REST URL 추출 시 활용. Default JSON + String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON); + String inboundMethod = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_METHOD, "POST"); + + //Outbound 요청에 대한 응답 메시지의 복호화 여부 결정위해 jwhong + encryptResponseApply = StringUtils.equalsIgnoreCase(prop.getProperty("ENCRYPT_RESPONSE_APPLY", "N"), "Y"); + + /** + * @formatter:off + * TSEAIHE02.RESTOPTION 정보 => JSON 형태로 구성 + * - type : simpleRequest, variableUrlRequest + * - extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL + * - method : get, delete, post, put + * - contentType: application/json(default), application/x-www-form-urlencoded + * - adapterTokenUseYn: Y, N(default) + * ex) + * {"type":"simpleRequest","extraPath":"v2.0/accout/balance","method":"post"} + * @formatter:on + */ + + String restOptionData = tempProp.getProperty(REST_OPTION); + + JSONObject restOptionObject = parseJson(restOptionData); + if (restOptionObject == null) { + throw new Exception("OptionData parsing result is NULL"); + } + + String rmethod = (String) restOptionObject.getOrDefault("method", inboundMethod); + String contentType = (String) restOptionObject.getOrDefault("contentType", "application/json"); + String adapterTokenUseYn = (String) restOptionObject.get("adapterTokenUseYn"); + if (StringUtils.isNotBlank(adapterTokenUseYn)) { // interface 에 설정된게 우선한다. + useAdapterToken = StringUtils.equalsIgnoreCase(adapterTokenUseYn, "Y"); + } + + HttpClient mclient = this.client; + String sendData = ""; + if (data instanceof String) { + sendData = (String) data; + } else if (data instanceof byte[]) { + sendData = new String((byte[]) data, vo.getEncode()); + } + + ////mclient.getParams().setContentCharset(vo.getEncode()); + + JSONObject dataObject = null; + Object httpHeader = null; + Object dataContent = null; + + if (MessageType.JSON.equals(messageType)) { + + Object parsed = parseJsonGeneric(sendData); + + if(parsed instanceof JSONObject) { + dataObject = parseJson(sendData); + if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) { + httpHeader = dataObject.get(headerGroupName); + dataObject.remove(headerGroupName); + } + + dataContent = dataObject; + if (dataObject.containsKey("innerList")) { + JSONArray innerList = (JSONArray) dataObject.get("innerList"); + dataContent = innerList; + } + } + } + +// if (MessageType.JSON.equals(messageType)) { +// dataObject = parseJson(sendData); +// if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) { +// httpHeader = dataObject.get(headerGroupName); +// dataObject.remove(headerGroupName); +// } +// } + + logger.debug("HttpClientAdapterServiceRest] dataObject1 = [" + dataObject + "]"); + + // interface 에 설정된게 우선한다. + String uri = null; + if (dataObject == null) { + uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData); + } else { + uri = changeUrl(messageType, vo.getUrl(), restOptionData, dataObject); + } + + logger.debug("HttpClientAdapterServiceRest] dataObject2 = [" + dataObject + "]"); + +// ////if (vo.getConnectionTimeout() != 0) { +// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(vo.getConnectionTimeout()); +// } + + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL=[" + vo.getUrl() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") PARAMETER_NAME=[" + vo.getParameterName() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") ENCODE=[" + vo.getEncode() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") RESPONSE_TYPE=[" + vo.getResponseType() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL_ENCODE_YN=[" + vo.getUrlEncodeYn() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") CONNECTION_TIMEOUT=[" + vo.getConnectionTimeout() + "] "); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") REST_OPTION=[" + restOptionData + "] "); + } + + HttpUriRequestBase method = null; + + + // 메소드 타입에 따라 HttpRequestBase 인스턴스 생성 + switch (HttpMethodType.getValue(rmethod)) { + case GET: + method = new HttpGet(uri); + break; + case DELETE: + method = new HttpDelete(uri); + break; + case POST: + method = new HttpPost(uri); + break; + case PUT: + method = new HttpPut(uri); + break; + default: + method = new HttpGet(uri); + break; + } + + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + + if(useForwardProxy) { + java.net.URL url = new java.net.URL(forwardProxyUrl); + + // 프로토콜, 호스트, 포트 추출 + String protocol = url.getProtocol(); + String host = url.getHost(); + int port = url.getPort(); + HttpHost proxy = new HttpHost(protocol,host, port); + requestConfigBuilder.setProxy(proxy); + } + + // OAuth2AccessToken check 부분을 뒤에서 여기로 위치를 옮김, 나이스지키미 암호화 KEY를 얻기 위해서. JWHONG + OAuth2AccessTokenVO accessToken = null; + String auth =""; + if (useAdapterToken) { + AccessTokenManagerByDB tokenManager = AccessTokenManagerByDB.getInstance(); + accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName()); + + // 토큰이 없거나 만료 됐으면 재발급 + if (accessToken == null || accessToken.isExpired()) { + String oldToken = accessToken == null ? null : accessToken.getAccessToken(); + accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop, + oldToken); + } + + if (logger.isDebug()) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") TOKEN = [" + + accessToken + "]"); + } + + Properties properties = AdapterPropManager.getInstance().getProperties(vo.getAdapterName()); // jwhong + String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong + if (useAdapterToken && "AES256-NICEON".equals(encryptAlgorithm)) { + String niceToken = accessToken.getAccessToken(); + String clientId = JwtClientIdExtractor(niceToken); + long currentTime = System.currentTimeMillis(); + auth = niceToken + ":" + currentTime + ":" + clientId ; + auth = Base64.getEncoder().encodeToString(auth.getBytes("UTF-8")); + + setNiceOnAuthHeaders(method, auth); + } else { + setAuthHeaders(method, accessToken); // 원래 있던 logic + } + + + if (logger.isDebug()) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + + ") RequestHeader [Authorization=" + method.getHeader("Authorization") + "]"); + } + } + + if(!StringUtils.isBlank(authToken)) { + setAuthHeaders(method, authToken); + } + // 여기 까지 + + configureHttpClient(requestConfigBuilder, vo, method); + + switch (HttpMethodType.getValue(rmethod)) { + case GET: + case DELETE: + HashMap h = getParameters(dataObject); + URIBuilder uriBuilder = new URIBuilder(uri); + for (Map.Entry entry : h.entrySet()) { + uriBuilder.addParameter(entry.getKey(), entry.getValue()); + } + URI fullUri = uriBuilder.build(); + if (method instanceof HttpGet) { + ((HttpGet) method).setUri(fullUri); + } else if (method instanceof HttpDelete) { + ((HttpDelete) method).setUri(fullUri); + } + if (logger.isDebug()) { + logger.debug("HttpClientAdapterServiceRest] (get Method) QueryString = [" + fullUri.getQuery() + "]"); + } + break; + case PUT: + case POST: +// assignPostBody(dataObject, contentType, vo.getEncode(), method); + //assignPostBody(dataContent, contentType, vo.getEncode(), method); // jwhong commnet + assignPostBody(dataContent, contentType, vo.getEncode(), method, vo.getAdapterName(), auth); + break; + default: + break; + } + + if (logger.isDebugEnabled()) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") method.getParams()=[" + + method.getEntity() + "] "); + } + + // OAuth2AccessToken 원래 있던 위치 JWHONG + + // 전달 header 셋팅 + // Adapter 레벨 header 보다 data로 넘어온 httpHeader를 우선 적용(header명이 같다면 덮어씀) + assignRequestHeaders(method, httpHeader); + + // KJBank API 추적정보를 Header에 제공. jwhong + assignRequestKJHeaders(method, prop, tempProp ); + + int status = -1; + + try { + byte[] responseMessage = null; + byte[] responseMessageOri = null; + Header[] responseHeaders; + + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + if (dataObject != null) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" + + dataObject.toJSONString() + "]"); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = " + + CommonLib.getDumpMessage(dataObject.toJSONString())); + } else { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" + sendData + + "]"); + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = " + + CommonLib.getDumpMessage(sendData)); + } + } + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + if (vo.getTraceLevel() >= 3) { + HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(), + "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData)); + } + + String uuid = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID); + HttpContext context = new BasicHttpContext(); + context.setAttribute(TransactionContextKeys.TRANSACTION_UUID, uuid); + context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, vo.getAdapterGroupName()); + context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME, vo.getAdapterName()); + Integer logProcessNo = (Integer) tempProp.get(HttpClientAdapterServiceKey.LOG_PROCESS_NO); + if (logProcessNo != null && logProcessNo > 0) { + context.setAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO, logProcessNo); + } + + // encrypt algorithm type 추출 from adapter property jwhong + Properties properties = AdapterPropManager.getInstance().getProperties(vo.getAdapterName()); // jwhong + String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong + + try { + if (logger.isDebug()) { + logger.debug("[method getName]" + method.getMethod()); + logger.debug("[method getEntity]" + method.getEntity()); + logger.debug("[method getRequestHeaders]" + method.getHeaders().toString()); + logger.debug("[method getURI]" + method.getPath()); + } + try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method, context)) { + status = response.getCode(); + + //responseMessage = EntityUtils.toByteArray(response.getEntity()); + // 역기서 responseMessage를 decryption 해야 하나 by jwhong + + responseMessageOri = EntityUtils.toByteArray(response.getEntity()); + System.out.println("responseMessageOri 바이트 배열 길이: " + responseMessageOri.length); + + responseMessage = doOutboundPostFilter(responseMessageOri, encryptAlgorithm, vo.getAdapterName(), accessToken); // jwhong + // 여기까지 + + responseHeaders = response.getHeaders(); + + if (logger.isDebug()) { + logger.debug("[received status]" + status); + logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + responseMessage + "]"); + } + } + } catch (ConnectException e) { + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType()); + } + throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage()); + } + + stopWatch.stop(); + + /** + * @formatter:off + * OAuth 토큰 응답 체크(Adapter properties로 설정) + * 응답코드에 따라 유효한 토큰 확인(토큰 재발급 여부 확인) + * API 서비스 마다 정책이 다름(보통 400대에서 체크하나 200에서도 체크할 수 있음) + * + * TOKEN_ERROR_CODE_KEY: 응답 json error code key + * __ex) $.dataHeader.resultCode + * TOKEN_ERROR_CODE_VALUES: 토큰 재발급이 필요한 응답 error codes(ex: O0001,O0002,O0003) + * TOKEN_ERROR_HTTP_STATUS_CODE: 보통 400대에서 체크하나 API 제공자에 따라 200에서도 체클할수 있음 + * ex) TOKEN_ERROR_HTTP_STATUS_CODE = 200 + * @formatter:on + */ + boolean needReissue = false; + + Properties responseHeaderProp = assignRelayDataToInbound(tempProp, responseHeaders); + String responseString = new String(responseMessage, vo.getEncode()); + + Map map = new HashMap(); + tempProp.put(HttpAdapterServiceKey.OUTBOUND_PROPERTY_MAP, map); + map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_HEADERS, responseHeaderProp); + map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_MESSAGE, responseString); + map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_STATUS, status); + + if (status >= 200 && status <= 207) { + if (useAdapterToken && StringUtils.equals(tokenErrorHttpStatusCode, "200")) { + needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues, + vo.getEncode()); + } + } else if (status == 302) { + if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) { + relayResponseHeaderKeys += ",Location"; + } + } else { + String errMsg = String.format( + "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s", + status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseString); +// logger.error(errMsg); + + if (status >= 400 && status < 500) { + if (useAdapterToken) { + needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues, + vo.getEncode()); + } + + if (!needReissue) { + throw new Exception(errMsg); + } + } else { + + throw new Exception(errMsg); + } + } + + // ---------------------------------------------------------- + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType()); + logger.debug("HttpClientAdapterServiceRest] RECV " + vo.getEncode() + "(" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]"); +// logger.debug("HttpClientAdapterServiceRest] RECV MS949 (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "MS949") + "]"); +// logger.debug("HttpClientAdapterServiceRest] RECV euc-kr (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "euc-kr") + "]"); + logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = " + CommonLib.getDumpMessage(responseMessage)); + } + + if (useAdapterToken) { + if (responseMessage == null) { + throw new Exception("responseMessage is NULL, HttpStatus=" + status); + } + + // OAuth 토큰 재요청 코드 확인 + if (needReissue) { + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] retry access token response code = [" + + vo.getResponseType() + "] message = [" + new String(responseMessage, vo.getEncode()) + + "]"); + } + + // 토큰 재발급 + AccessTokenManager tokenManager = AccessTokenManager.getInstance(); + String oldToken = accessToken == null ? null : accessToken.getAccessToken(); + OAuth2AccessTokenVO newaccessToken = (OAuth2AccessTokenVO) tokenManager + .retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken); + method.setHeader("Authorization", newaccessToken.getAuthorization()); + + setAuthHeaders(method, newaccessToken); + + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + + ") RETRY TOKEN = [" + newaccessToken + "]"); + } + + try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method)) { + status = response.getCode(); + responseMessage = EntityUtils.toByteArray(response.getEntity()); + // 여기서도 decryption 해야 할듯 하나.. by jwhong + + if (logger.isDebug()) { + logger.debug("[received status]" + status); + logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]"); + } + }catch (IOException e){ + throw new Exception("retry excuteMethod Exceptioin = " + e.getMessage()); + } + + + if (status == 302) { + if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) { + relayResponseHeaderKeys += ",Location"; + } + } else { + String errMsg = String.format( + "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s", + status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage); + throw new Exception(errMsg); + } + + // ---------------------------------------------------------- + if (logger.isDebug() && "N".equals(vo.getTestCallYn())) { + logger.debug("HttpClientAdapterServiceRest] RETRY responseType =" + vo.getResponseType()); + logger.debug("HttpClientAdapterServiceRest] RETRY RECV " + vo.getEncode() + "(" + + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + + "]"); + logger.debug("HttpClientAdapterServiceRest] RETRY RECV (" + vo.getAdapterGroupName() + ") = " + + CommonLib.getDumpMessage(responseMessage)); + } + // ---------------------------------------------------------- + } + } + + if (vo.getTraceLevel() >= 3) { + HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(), + "RECV [" + new String(responseMessage, vo.getEncode()) + "]" + + CommonLib.getDumpMessage(responseMessage)); + } + + + return assignResponseHeaders(method, responseMessage, headerGroupName, vo.getEncode(), messageType, + relayResponseHeaderKeys, status, responseHeaderProp); + } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우 + if (vo.getTraceLevel() >= 3) { + HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), + "HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : " + + ste.toString(), + ste); + } + logger.error("HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : " + + ste.toString(), ste); + throw ste; + } catch (ConnectException ce) { + if (vo.getTraceLevel() >= 3) { + HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), + "HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : " + + ce.toString(), + ce); + } + logger.error("HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : " + + ce.toString(), ce); + throw ce; + } catch (Exception e) { + if (vo.getTraceLevel() >= 3) { + HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), e.toString(), e); + } + logger.error("HttpClientAdapterServiceRest] Exception (" + vo.getAdapterGroupName() + ") : " + e.toString(), + e); + throw e; + } finally { + if (status != HttpStatus.SC_OK) { + String[] msgArgs = new String[1]; + msgArgs[0] = String.valueOf(status); + String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs); + if (logger.isDebug()) { + logger.debug(resMsg); + } + } + } + } + + private Properties assignRelayDataToInbound(Properties prop, Header[] responseHeaders) { + Properties headerProp = new Properties(); + if (responseHeaders == null || responseHeaders.length == 0) { + return headerProp; + } + + for (Header header : responseHeaders) { + headerProp.put(header.getName(), header.getValue()); + } + + return headerProp; + } + + /** + * 현재 1단계 레이아웃에만 적용되도록 구현됨. + * + * @param method + * @param responseMessage + * @param headerGroupName + * @param encode + * @param messageType + * @param relayHeaderKeys + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + private String assignResponseHeaders(HttpUriRequestBase method, byte[] responseMessage, String headerGroupName, + String encode, String messageType, String relayHeaderKeys, int status, Properties responseHeaderProp) throws Exception { + if (!MessageType.JSON.equals(messageType) || StringUtils.isBlank(headerGroupName) + || StringUtils.isBlank(relayHeaderKeys)) { + return new String(responseMessage, encode); + } + + String[] relayKeyArr = org.springframework.util.StringUtils.tokenizeToStringArray(relayHeaderKeys, ","); + JSONObject headerJson = new JSONObject(); + for (String key : relayKeyArr) { + String value = responseHeaderProp.getProperty(key); + if (StringUtils.isNotBlank(value)) { + headerJson.put(key, value); + } + } + + headerJson.put(HTTP_STATUS, String.valueOf(status)); + + if (headerJson.size() <= 0) { + return new String(responseMessage, encode); + } + + JSONObject message = null; + if (responseMessage == null || responseMessage.length == 0) { + message = new JSONObject(); + } else { + message = parseJson(new String(responseMessage, encode)); + if (message == null) { + message = new JSONObject(); + message.put("Malformed_Response_Message", new String(responseMessage, encode)); + } + } + + if (StringUtils.isNotBlank(headerGroupName) && message != null) + message.put(headerGroupName, headerJson); + return message.toJSONString(); + } + + private void setAuthHeaders(HttpUriRequestBase method, String authorization) throws Exception { + method.setHeader("Authorization", + String.format("%s", authorization)); + } + + private void setAuthHeaders(HttpUriRequestBase method, OAuth2AccessTokenVO accessToken) throws Exception { + method.setHeader("Authorization", + String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken())); + } + + /* nice on 나이스 지키미 용으로 생성함 + * jwhong 2015-11-04 + */ + private void setNiceOnAuthHeaders(HttpUriRequestBase method, String auth) throws Exception { + method.setHeader("Authorization", + String.format("%s %s", AccessTokenVO.BEARER_TYPE, auth)); // 나이스지키미 format임 + method.setHeader("ProductID", "2303345072"); + //method.setHeader("Authorization", + // String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken())); + } + + /* nice clientid 추출을 위하여 추가한 내용임. jwhong + * + */ + private String JwtClientIdExtractor(String inboundToken) { + + String tokenClientId =""; + try { + SignedJWT signedJWT = SignedJWT.parse(inboundToken); + tokenClientId = (String) signedJWT.getJWTClaimsSet().getClaim(PAYLOAD_PARAM_NAME_CLIENT_ID); + } catch (Exception e) { + logger.error(e.getMessage()); + tokenClientId = ""; + } + + System.out.println("Token Client ID: " + tokenClientId); + return tokenClientId; + + } + + + private boolean checkTokenRetry(byte[] responseMessage, String tokenErrorCodeKey, String tokenErrorCodeValues, + String encode) { + if (responseMessage == null) { + return false; + } + + if (StringUtils.isBlank(tokenErrorCodeKey)) { + return false; + } + + if (StringUtils.isBlank(tokenErrorCodeValues)) { + return false; + } + + try { + DocumentContext jsonContext = JsonPath.parse(new String(responseMessage, encode)); + String responseCode = jsonContext.read(tokenErrorCodeKey); + if (StringUtils.isBlank(responseCode)) { + return false; + } + + String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenErrorCodeValues, ","); + return ArrayUtils.contains(arr, responseCode); + } catch (Exception e) { + logger.error("HttpClientAdapterServiceRest] checkTokenRetry error=" + e.getMessage()); + } + + return false; + } + + private void assignRequestHeaders(HttpUriRequestBase method, Object httpHeader) { + if (httpHeader == null) { + return; + } + + if (httpHeader instanceof JSONObject) { + JSONObject jsonObject = (JSONObject) httpHeader; + for (Object key : jsonObject.keySet()) { + Object obj = jsonObject.get(key); + if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) { + continue; + } + + method.setHeader((String) key, (String) obj); + + if (logger.isDebugEnabled()) { + logger.debug("Request Header :" + (String) key + "=[" + (String) obj + "]"); + } + + } + } + } + + /* + * KJBank Target System으로 요청 보낼때 header에 clientId(업체정보), APIM거래추적자(UUID), 최초 요청시간 을 보낸다. jwhong + */ + private void assignRequestKJHeaders(HttpUriRequestBase method, Properties prop, Properties tempProp) { + + Properties inboundHeaders = (Properties) tempProp.get(HttpAdapterServiceKey.INBOUND_HEADER); + String authorization = inboundHeaders.getProperty("authorization"); + String jwtToken = ""; + + if (authorization != null && authorization.startsWith("Bearer ")) { + jwtToken = authorization.substring(7); // "Bearer " 이후의 JWT만 추출 + //System.out.println("JWT Token: " + jwtToken); + } + + /* 업체정보 */ + String clientId = JwtClientIdExtractor(jwtToken); + method.setHeader("clientId", clientId); + + /* APIM 거래추적자 */ + String uuid = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID, ""); + method.setHeader("traceId", uuid); + + /* 최초요청시간 */ + Set keys = tempProp.stringPropertyNames(); + for (String key : keys) { + String value = tempProp.getProperty(key); + System.out.println(key + " = " + value); + } + + String receivedTimestamp = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_REQUESTED_TIME, ""); + method.setHeader("receivedTimestamp", receivedTimestamp); + } + + @SuppressWarnings("deprecation") + private void assignPostBody(Object eaiBody, String contentType, String charset, HttpUriRequestBase method, String adapterName, String niceAuth) { + if (eaiBody == null) { + return; + } + + if (StringUtils.contains(contentType, "application/x-www-form-urlencoded")) { + if (eaiBody instanceof JSONObject) { + List params = new ArrayList<>(); + JSONObject jsonObject = (JSONObject) eaiBody; + for (Object key : jsonObject.keySet()) { + //String encryptedValue = encrypt((String) jsonObject.get(key)); // encrypt by jwhong + //params.add(new BasicNameValuePair((String) key, encryptedValue )); + params.add(new BasicNameValuePair((String) key, (String) jsonObject.get(key))); + } + + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8); + method.setEntity(entity); + } + } else { + ContentType contentTypeObj = ContentType.create(contentType, charset); + + String eaiBodyMessage = doOutboundPreFilter(eaiBody, adapterName, niceAuth); // jwhong + StringEntity entity = new StringEntity(eaiBodyMessage, contentTypeObj); + // 요청 본문을 StringEntity 객체로 생성 + //StringEntity entity = new StringEntity(eaiBody.toString(), contentTypeObj); + + // 요청에 본문 추가 + method.setEntity(entity); + } + } + + // from here by jwhong + private String doOutboundPreFilter(Object eaiBody, String adapterName, String niceAuth) { + + Properties properties = AdapterPropManager.getInstance().getProperties(adapterName); // jwhong + String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM",""); // jwhong + //String encryptBaseKeyType = properties.getProperty("ENCRYPT_BASE_TYPE"); + String encryptClientId = properties.getProperty("ENCRYPT_CLIENT_ID"); + String encryptAES256Iv = properties.getProperty("ENCRYPT_AES256_IV"); + String encryptAES256Key = properties.getProperty("ENCRYPT_AES256_KEY"); + + // outbound encrypt 는 SecretKey 또는 NICE-auth 가 암호화 key로 사용된다. + // 참고로 inbound encrypt 에는 Token 또는 SecretKey 가 암호화 key로 사용된다. + // 여기에 NICE-auth 뭔지 파악하여 logic 추가해야 한다. + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(encryptClientId); + String clientSecret = ""; + if ( clientDetail != null ) { // not null 이라는 것은 APIM Oauth Server에 등록된 client ID 이다. + // 이건 KJBank로 Outbound 나가는 것임 + clientSecret = clientDetail.getClientSecret(); + } else { // 그럼 업체로 Outbound 나가는것은, 업체에서 사용하는 secretkey를 사용한다. + clientSecret = encryptClientId; + } + + // Nice-auth , token 값을 substring 해서 사용한다. 나이스 지키미는 adapter token에서 추출된 token을 사용한다. + if (useAdapterToken && "AES256-NICEON".equals(encryptAlgorithm)) { + clientSecret = niceAuth; + } + + // 여기서 SECRETY인지 nice-auth 인지 check 하여 clientSecret 값을 정하는 logic 추가하여 넘겨야한다. + + String responseMessage = doOutboundPreEncrypt(eaiBody, encryptAlgorithm, clientSecret, encryptAES256Iv, encryptAES256Key); + return responseMessage; + + } + private String doOutboundPreEncrypt(Object eaiBody, String encryptAlgorithm, String clientSecretKey, String encryptAES256Iv, String encryptAES256Key ) { + + String encryptedMessage = ""; + String encryptedJsonKey = ""; + + encryptedJsonKey = getJsonKey(encryptAlgorithm); + + switch (encryptAlgorithm) { + case "AES": + encryptedMessage = encrypt(eaiBody.toString()); // encrypt by jwhong + break; + case "AES128-TOSS": + try { + String key = clientSecretKey.substring(22,38); + encryptedMessage = AESCipher.encrypt(eaiBody.toString(), key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); + } + break; + case "AES128-TOGETHER": + try { + String key = clientSecretKey.substring(44,60); + encryptedMessage = AESCipher.encrypt(eaiBody.toString(), key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); + } + break; + case "AES256": + try { + String key = clientSecretKey.substring(10,42); + encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256-KAKAO": + try { + encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), encryptAES256Iv, encryptAES256Key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256-TOSS": + try { + encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), encryptAES256Iv, encryptAES256Key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256-NICEON": + try { + String key = clientSecretKey.substring(10,42); + encryptedMessage = AES256Cipher.encrypt(eaiBody.toString(), key); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256GCM": + try { + byte[] key = AES256GCMCipher.generateKey(); + AES256GCMCipher cipher = new AES256GCMCipher(key); + byte[] aad = "metadata".getBytes(); + + encryptedMessage = cipher.encrypt(eaiBody.toString(), aad); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256GCM Encryption error=" + e.getMessage()); + } + break; + default: + encryptedMessage = eaiBody.toString(); + return encryptedMessage; + //break; + } + + Map map = new HashMap<>(); + map.put(encryptedJsonKey, encryptedMessage); + JSONObject json = new JSONObject(); + json.putAll(map); + return json.toJSONString(); + //return encryptedMessage; + } + + + private byte[] doOutboundPostFilter(byte[] eaiBody, String decryptAlgorithm, String adapterName, OAuth2AccessTokenVO niceAccessToken ) { + + if ( !encryptResponseApply) { + return eaiBody; + } + + Properties properties = AdapterPropManager.getInstance().getProperties(adapterName); // jwhong + //String encryptAlgorithm = properties.getProperty("ENCRYPT_ALGORITHM"); // jwhong + //String encryptBaseKeyType = properties.getProperty("ENCRYPT_BASE_TYPE"); + String encryptClientId = properties.getProperty("ENCRYPT_CLIENT_ID"); + String encryptAES256Iv = properties.getProperty("ENCRYPT_AES256_IV"); + String encryptAES256Key = properties.getProperty("ENCRYPT_AES256_KEY"); + + // outbound encrypt 는 SecretKey 또는 NICE-auth 가 암호화 key로 사용된다. + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(encryptClientId); + String clientSecret = ""; + if ( clientDetail != null ) { + clientSecret = clientDetail.getClientSecret(); + } else { + clientSecret = encryptClientId; + } + + // Nice-auth , token 값을 substring 해서 사용한다. 나이스 지키미는 adapter token에서 추출된 token을 사용한다. + if (useAdapterToken && "AES256-NICEON".equals(decryptAlgorithm)) { + clientSecret = niceAccessToken.getAccessToken(); + } + + byte[] resPostMessage = doOutboundPostDecrypt(eaiBody, decryptAlgorithm, clientSecret, encryptAES256Iv, encryptAES256Key); + return resPostMessage; + } + + private byte[] doOutboundPostDecrypt(byte[] eaiBody, String decryptAlgorithm, String clientSecretKey, String encryptAES256Iv, String encryptAES256Key ) { + + byte[] decryptedMessage = null; + String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); + + try { + eaiStringBody = extractBodyMsg(decryptAlgorithm, eaiStringBody); + } catch (ParseException e) { + System.out.println("JSON 파싱 오류 발생 : " +e.getMessage()); + return eaiBody; + } + + //test source + System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); + System.out.println("Base64 문자열: " + eaiStringBody); + System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); + System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); + + // Base64 디코딩 테스트 + try { + byte[] decoded = Base64.getDecoder().decode(eaiStringBody); + System.out.println("디코딩 성공, 길이: " + decoded.length); + } catch (IllegalArgumentException e) { + System.out.println("Base64 디코딩 실패: " + e.getMessage()); + } + // end test source + + switch (decryptAlgorithm) { + case "AES": + decryptedMessage = decrypt(eaiBody); // encrypt by jwhong + break; + case "AES128-TOSS": + try { + String key128 = clientSecretKey.substring(22,38); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES128-TOGETHER": + try { + String key128 = clientSecretKey.substring(44,60); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES256": + try { + String key = clientSecretKey.substring(10,42); + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256-KAKAO": + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, encryptAES256Iv, encryptAES256Key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256-TOSS": + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, encryptAES256Iv, encryptAES256Key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); + } + break; + case "AES256-NICEON": + try { + String key = clientSecretKey.substring(10,42); + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256GCM": + try { + byte[] key = AES256GCMCipher.generateKey(); + AES256GCMCipher cipher = new AES256GCMCipher(key); + byte[] aad = "metadata".getBytes(); + String decryptedStrMessage = cipher.decrypt(eaiStringBody, aad); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + default: + try { + decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); + } + break; + } + + return decryptedMessage; + } + + + private String extractBodyMsg(String decryptAlgorithm, String eaiStringBody) throws ParseException { + + String decryptedJsonKey = ""; + String decryptedBodyMessage = ""; + + decryptedJsonKey = getJsonKey(decryptAlgorithm); + + try { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(eaiStringBody); + decryptedBodyMessage = (String) jsonObject.get(decryptedJsonKey); + } catch (ParseException e) { + e.printStackTrace(); + logger.error("HttpClient5AdapterServiceRest] extractBodyMsg error : " + e.getMessage()); + throw e; + } + + return decryptedBodyMessage; + + } + + private String getJsonKey(String Algorithm) { + + String jsonKey = ""; + + switch (Algorithm) { + case "AES128-TOSS": + jsonKey = "preScreeningRequest"; + break; + case "AES128-TOGETHER": + jsonKey = "obpTxData"; + break; + case "AES256": + jsonKey = "preScreeningRequest"; + break; + case "AES256-KAKAO": + jsonKey = "encrypted_data"; + break; + case "AES256-TOSS": + jsonKey = "encryptedData"; + break; + case "AES256-NICEON": + jsonKey = "preScreeningRequest"; + break; + case "AES256GCM": + break; + default: + break; + } + return jsonKey; + } + // by jwhong + private String encrypt(String plainText) { + try { + SecretKeySpec key = new SecretKeySpec("1234567890123456".getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(encrypted); + } catch (Exception e) { + // 예외 로그 출력 또는 사용자 정의 처리 + e.printStackTrace(); + return null; // 또는 에러 메시지 반환 + } + } + + + public static byte[] decrypt(byte[] encryptedBytes) { + try { + // byte[] --> Base64 문자열로 변환 + String encryptedText = new String(encryptedBytes, StandardCharsets.UTF_8).trim(); + // 암호화에 사용한 키와 동일한 키 사용 + SecretKeySpec key = new SecretKeySpec("1234567890123456".getBytes(), "AES"); + + // 암호화와 동일한 알고리즘 설정 + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, key); + + // Base64로 인코딩된 문자열을 디코딩 + byte[] decodedBytes = Base64.getDecoder().decode(encryptedText); + + // 복호화 수행 + byte[] decryptedBytes = cipher.doFinal(decodedBytes); + + // UTF-8 문자열로 변환하여 반환 + //return new String(decryptedBytes, StandardCharsets.UTF_8); + //복호화된 바이트 배열 반환 + return decryptedBytes; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + private HashMap getParameters(Object message) throws Exception { + + HashMap result = new HashMap(); + + if (message != null) { + if (message instanceof JSONObject) { + JSONObject jsonObject = (JSONObject) message; + for (Object key : jsonObject.keySet()) { + Object obj = jsonObject.get(key); + if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) { + continue; + } + result.put((String) key, getStringValue(obj)); + } + } else { + String[] messages = ((String) message).split("&"); + String[] data = null; + + for (int i = 0; i < messages.length; i++) { + data = messages[i].split("=", 2); + if (data.length == 2) { + result.put(data[0], data[1]); + } + } + } + } + + return result; + } + + public String getStringValue(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof Long) { + return Long.toString((Long) obj); + } else if (obj instanceof BigDecimal) { + return ((BigDecimal) obj).toPlainString(); + } else { + return (String) obj; + } + } + + public static Object parseJsonGeneric(String jsonData) { + if (StringUtils.isBlank(jsonData)) { + return null; + } + + try { + JSONParser parser = new JSONParser(); + Object parsedObj = parser.parse(jsonData); + return parsedObj; + } catch (ParseException e) { + e.printStackTrace(); + return null; + } + } + + @SuppressWarnings("deprecation") + private JSONObject parseJson(String message) throws Exception { + if (message == null) { + return null; + } + + return (JSONObject) JSONValue.parse(message); + } + + private Document convertXmlDocument(String message) throws Exception { + SAXReader builder = new SAXReader(); + Document document = builder.read(new StringReader(message)); + return document; + } + + @SuppressWarnings("deprecation") + private String changeUrl(String messageType, String url, String restOption, Object sendData) { + if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) { + try { + if (StringUtils.isBlank(restOption)) { + return url; + } + List urlVariableList = new ArrayList(); + JSONObject restOptionObject = parseJson(restOption); + + if (restOptionObject == null) + throw new Exception("restOption is NULL"); + + String type = (String) restOptionObject.get("type"); + String requestExtraPath = (String) restOptionObject.get("extraPath"); + url = getUrl(url, requestExtraPath); + if (TYPE_VARIABLE_URL_REQUEST.equals(type)) { + Pattern p = Pattern.compile("\\{(.*?)\\}"); + Matcher m = p.matcher(requestExtraPath); + List uriVariables = new ArrayList<>(); + while(m.find()) { + String fieldName = m.group(1); + uriVariables.add(fieldName); + } + if (MessageType.JSON.equals(messageType)) { + JSONObject jsonObject; + if (sendData instanceof JSONObject) { + jsonObject = (JSONObject) sendData; + } else { + jsonObject = (JSONObject) JSONValue.parse((String) sendData); + } + for (Object tempObject : uriVariables) { + String urlVaribleId = (String) tempObject; + String uriVariable = (String) jsonObject.get(urlVaribleId); + urlVariableList.add(uriVariable); + jsonObject.remove(urlVaribleId); + } + } else if (MessageType.XML.equals(messageType)) { + Document doc; + if (sendData instanceof Document) { + doc = (Document) sendData; + } else { + doc = convertXmlDocument((String) sendData); + } + for (Object tempObject : uriVariables) { + String urlVaribleId = (String) tempObject; + Element element = (Element) doc.selectSingleNode("//" + urlVaribleId); + urlVariableList.add(element.getText()); + if (doc.getRootElement() == element) { + doc = null; + } else { + element.getParent().remove(element); + } + } + } + if (urlVariableList.size() > 0) { + UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build(); + Object[] urls = urlVariableList.toArray(); + url = uriComponents.expand(urls).toUriString(); + logger.debug("HttpClientAdapterServiceRest] after extand url=[" + url + "] "); + } + } + } catch (Exception e) { + logger.error("Failed to change url", e); + } + } + return url; + } + + private String getUrl(String baseUrl, String extraPath) { + if (StringUtils.isBlank(extraPath)) { + return baseUrl; + } + + if (StringUtils.contains(extraPath, "http://") || StringUtils.contains(extraPath, "https://")) { + return extraPath; + } + + String targetUrl = baseUrl; + if (!targetUrl.endsWith("/")) { + targetUrl += "/"; + } + if (extraPath.startsWith("/")) { + targetUrl += extraPath.substring(1); + } else { + targetUrl += extraPath; + } + + logger.debug("HttpClientAdapterServiceRest] after concatenate url=[" + targetUrl + "] "); + return targetUrl; + } +} diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java index a989dfd..3fb84de 100644 --- a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java +++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java @@ -1,83 +1,84 @@ -package com.eactive.eai.adapter.http.dynamic; - -public interface HttpAdapterServiceKey { - // URL 파리미터 DEFAULT 이름 - static final String PARAMETER_MESSAGE = "_message_"; - - // URL 파리미터 이름 - static final String PARAMETER_NAME = "PARAMETER_NAME"; - - // Http Adapter 이름 - static final String HTTP_ADAPTER_NAME = "HTTP_ADAPTER_NAME"; - - // Http Adapter Group 이름 - static final String HTTP_ADAPTER_GROUP_NAME = "HTTP_ADAPTER_GROUP_NAME"; - - // Http Response Type 이름 - static final String RESPONSE_TYPE = "RESPONSE_TYPE"; - - public static final String RESPONSE_TYPE_SYNC = "SYNC"; - public static final String RESPONSE_TYPE_ASYNC = "ASYN"; - - // Http Encode 이름 - static final String ENCODE = "ENCODE"; - - // Http URL Decode 여부 - static final String URL_DECODE_YN = "URL_DECODE_YN"; - - // Body data 사용 여부 - static final String REQUEST_BODY_YN = "REQUEST_BODY_YN"; - - // 삭제할 데이타 길이 - static final String REMOVE_LENGTH = "REMOVE_LENGTH"; - - // 추가할 데이타 - static final String ADD_DATA = "ADD_DATA"; - - // 거래 로그 - static final String TRACE_LEVEL = "TRACE_LEVEL"; - - static final String ERROR_RESPONSE_FORMAT = "ERROR_RESPONSE_FORMAT"; - - // REST용 전달값 - static final String INBOUND_METHOD = "INBOUND_METHOD"; - static final String INBOUND_URI = "INBOUND_URI"; - static final String INBOUND_EXTURI = "INBOUND_EXTURI"; - static final String INBOUND_HEADER = "INBOUND_HEADER"; - static final String INBOUND_QUERY_STRING = "INBOUND_QUERY_STRING"; - static final String INBOUND_REWRITE_PATH = "INBOUND_REWRITE_PATH"; - static final String INBOUND_REMOTE_ADDR = "INBOUND_REMOTE_ADDR"; - static final String INBOUND_SCHEME = "INBOUND_SCHEME"; - static final String INBOUND_PATH_VARIABLES = "INBOUND_PATH_VARIABLES"; - static final String INBOUND_REQUEST_MESSAGE = "INBOUND_REQUEST_MESSAGE"; - static final String INBOUND_CLIENT_IP = "INBOUND_CLIENT_IP"; - - static final String INBOUND_SYNC_ASYNC_TYPE = "INBOUND_SYNC_ASYNC_TYPE"; - - public static final String OUTBOUND_RESPONSE_HEADERS = "OUTBOUND_RESPONSE_HEADERS"; - public static final String OUTBOUND_RESPONSE_MESSAGE = "OUTBOUND_RESPONSE_MESSAGE"; - public static final String OUTBOUND_RESPONSE_STATUS = "OUTBOUND_RESPONSE_STATUS"; - public static final String OUTBOUND_PROPERTY_MAP = "OUTBOUND_PROPERTY_MAP"; - - // API path - static final String API_PATH = "API_PATH"; - - // 요청전 수행할 필터(쉼표(,)로 구분) - static final String PRE_FILTERS = "PRE_FILTERS"; - - // 요청후 수행할 필터(쉼표(,)로 구분) - static final String POST_FILTERS = "POST_FILTERS"; - - static final String ALLOW_IP = "ALLOW_IP"; - - static final String ENC_PATHS = "ENC_PATHS"; - - static final String ENCRYPT_ALGORITHM = "ENCRYPT_ALGORITHM"; //jwhong - static final String INBOUND_TOKEN = "authorization"; // jwhong - static final String ENCRYPT_BASE_TYPE = "ENCRYPT_BASE_TYPE"; // jwhong - static final String ENCRYPT_AES256_IV = "ENCRYPT_AES256_IV"; // jwhong - static final String ENCRYPT_AES256_KEY = "ENCRYPT_AES256_KEY"; // jwhong - - //응답 처리 용 표준 전문 오브젝트 - static final String STANDARD_MESSAGE_OBJECT = "STANDARD_MESSAGE_OBJECT"; -} +package com.eactive.eai.adapter.http.dynamic; + +public interface HttpAdapterServiceKey { + // URL 파리미터 DEFAULT 이름 + static final String PARAMETER_MESSAGE = "_message_"; + + // URL 파리미터 이름 + static final String PARAMETER_NAME = "PARAMETER_NAME"; + + // Http Adapter 이름 + static final String HTTP_ADAPTER_NAME = "HTTP_ADAPTER_NAME"; + + // Http Adapter Group 이름 + static final String HTTP_ADAPTER_GROUP_NAME = "HTTP_ADAPTER_GROUP_NAME"; + + // Http Response Type 이름 + static final String RESPONSE_TYPE = "RESPONSE_TYPE"; + + public static final String RESPONSE_TYPE_SYNC = "SYNC"; + public static final String RESPONSE_TYPE_ASYNC = "ASYN"; + + // Http Encode 이름 + static final String ENCODE = "ENCODE"; + + // Http URL Decode 여부 + static final String URL_DECODE_YN = "URL_DECODE_YN"; + + // Body data 사용 여부 + static final String REQUEST_BODY_YN = "REQUEST_BODY_YN"; + + // 삭제할 데이타 길이 + static final String REMOVE_LENGTH = "REMOVE_LENGTH"; + + // 추가할 데이타 + static final String ADD_DATA = "ADD_DATA"; + + // 거래 로그 + static final String TRACE_LEVEL = "TRACE_LEVEL"; + + static final String ERROR_RESPONSE_FORMAT = "ERROR_RESPONSE_FORMAT"; + + // REST용 전달값 + static final String INBOUND_METHOD = "INBOUND_METHOD"; + static final String INBOUND_URI = "INBOUND_URI"; + static final String INBOUND_EXTURI = "INBOUND_EXTURI"; + static final String INBOUND_HEADER = "INBOUND_HEADER"; + static final String INBOUND_QUERY_STRING = "INBOUND_QUERY_STRING"; + static final String INBOUND_REWRITE_PATH = "INBOUND_REWRITE_PATH"; + static final String INBOUND_REMOTE_ADDR = "INBOUND_REMOTE_ADDR"; + static final String INBOUND_SCHEME = "INBOUND_SCHEME"; + static final String INBOUND_PATH_VARIABLES = "INBOUND_PATH_VARIABLES"; + static final String INBOUND_REQUEST_MESSAGE = "INBOUND_REQUEST_MESSAGE"; + static final String INBOUND_CLIENT_IP = "INBOUND_CLIENT_IP"; + + static final String INBOUND_SYNC_ASYNC_TYPE = "INBOUND_SYNC_ASYNC_TYPE"; + + public static final String OUTBOUND_RESPONSE_HEADERS = "OUTBOUND_RESPONSE_HEADERS"; + public static final String OUTBOUND_RESPONSE_MESSAGE = "OUTBOUND_RESPONSE_MESSAGE"; + public static final String OUTBOUND_RESPONSE_STATUS = "OUTBOUND_RESPONSE_STATUS"; + public static final String OUTBOUND_PROPERTY_MAP = "OUTBOUND_PROPERTY_MAP"; + + // API path + static final String API_PATH = "API_PATH"; + + // 요청전 수행할 필터(쉼표(,)로 구분) + static final String PRE_FILTERS = "PRE_FILTERS"; + + // 요청후 수행할 필터(쉼표(,)로 구분) + static final String POST_FILTERS = "POST_FILTERS"; + + static final String ALLOW_IP = "ALLOW_IP"; + + static final String ENC_PATHS = "ENC_PATHS"; + + static final String ENCRYPT_ALGORITHM = "ENCRYPT_ALGORITHM"; //jwhong + static final String INBOUND_TOKEN = "authorization"; // jwhong + static final String ENCRYPT_BASE_TYPE = "ENCRYPT_BASE_TYPE"; // jwhong + static final String ENCRYPT_AES256_IV = "ENCRYPT_AES256_IV"; // jwhong + static final String ENCRYPT_AES256_KEY = "ENCRYPT_AES256_KEY"; // jwhong + static final String INBOUND_REQUESTED_TIME = "INBOUND_REQUESTED_TIME"; // jwhong + + //응답 처리 용 표준 전문 오브젝트 + static final String STANDARD_MESSAGE_OBJECT = "STANDARD_MESSAGE_OBJECT"; +} diff --git a/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithBase64Header.java b/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithBase64Header.java index 6316890..295c2f3 100644 --- a/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithBase64Header.java +++ b/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithBase64Header.java @@ -1,6 +1,6 @@ package com.eactive.eai.authoutbound.client.impl; - + import com.eactive.eai.adapter.AdapterGroupVO; import com.eactive.eai.adapter.AdapterManager; import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey; diff --git a/src/main/java/com/eactive/eai/common/logger/EAILogDAO.java b/src/main/java/com/eactive/eai/common/logger/EAILogDAO.java index 4dfc052..cadab1b 100644 --- a/src/main/java/com/eactive/eai/common/logger/EAILogDAO.java +++ b/src/main/java/com/eactive/eai/common/logger/EAILogDAO.java @@ -1,982 +1,982 @@ -package com.eactive.eai.common.logger; - -import java.nio.charset.Charset; -import java.util.Properties; - -import com.eactive.eai.authserver.service.OAuth2Manager; -import com.eactive.eai.authserver.vo.ClientVO; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.eactive.eai.adapter.AdapterGroupVO; -import com.eactive.eai.adapter.AdapterManager; -import com.eactive.eai.agent.encryption.EncryptionManager; -import com.eactive.eai.common.dao.DAOException; -import com.eactive.eai.common.exception.ExceptionUtil; -import com.eactive.eai.common.logger.EAILogLogger; -import com.eactive.eai.common.logger.StatAdapterLogLogger; -import com.eactive.eai.common.logger.StatLogLogger; -import com.eactive.eai.common.logger.StatTranLogLogger; -import com.eactive.eai.common.logger.SubMessageLogLogger; -import com.eactive.eai.common.logger.mapper.StatAdapterLogMapper; -import com.eactive.eai.common.logger.mapper.StatLogMapper; -import com.eactive.eai.common.logger.mapper.StatTranLogMapper; -import com.eactive.eai.common.message.EAIMessage; -import com.eactive.eai.common.message.EAIMessageKeys; -import com.eactive.eai.common.message.MessageType; -import com.eactive.eai.common.message.ServiceMessage; -import com.eactive.eai.common.monitor.StatMonitorLogVO; -import com.eactive.eai.common.property.PropManager; - -import com.eactive.eai.common.server.EAIServerManager; -import com.eactive.eai.common.server.EAIServerVO; -import com.eactive.eai.common.server.loader.EAIServerLoader; -import com.eactive.eai.common.util.DatetimeUtil; -import com.eactive.eai.common.util.Logger; -import com.eactive.eai.common.util.MessageUtil; -import com.eactive.eai.common.util.StringUtil; -import com.eactive.eai.data.RollingTable; -import com.eactive.eai.data.entity.onl.logger.EAIErrorLog; -import com.eactive.eai.data.entity.onl.logger.EAIErrorLogId; -import com.eactive.eai.data.entity.onl.logger.EAILog; -import com.eactive.eai.data.entity.onl.logger.EAILogId; -import com.eactive.eai.data.entity.onl.logger.StatAdapterLog; -import com.eactive.eai.data.entity.onl.logger.StatLog; -import com.eactive.eai.data.entity.onl.logger.StatTranLog; -import com.eactive.eai.data.entity.onl.logger.SubMessageLog; -import com.eactive.eai.data.entity.onl.logger.SubMessageLogId; -import com.eactive.eai.message.EncodingVar; -import com.eactive.eai.message.StandardMessage; -import com.eactive.eai.message.manager.StandardMessageManager; -import com.eactive.eai.transformer.layout.Item; -import com.eactive.eai.transformer.layout.Layout; -import com.eactive.eai.transformer.transform.Transform; -import com.eactive.eai.transformer.transform.TransformManager; -import com.eactive.eai.util.HexaConverter; -import com.ext.eai.common.stdmessage.STDMessageKeys; -// safeDB -import com.eactive.ext.kjb.safedb.KjbSafedbWrapper; -import com.eactive.ext.kjb.safedb.Utils; -// until here - - -@Service -@Transactional -public class EAILogDAO { -//extends BaseDAO { - static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); - - @Autowired - private ApplicationContext applicationContext; - - @Autowired - private EAILogLogger eaiLogEntityService; - - @Autowired - private SubMessageLogLogger subMessageLogLogger; - - @Autowired - private StatLogLogger statLogLogger; - - @Autowired - private StatTranLogLogger statTranLogLogger; - - @Autowired - private StatAdapterLogLogger statAdapterLogLogger; - - @Autowired - private StatLogMapper statLogMapper; - - @Autowired - private StatTranLogMapper statTranLogMapper; - - @Autowired - private StatAdapterLogMapper statAdapterLogMapper; - - @Autowired - private EAIServerLoader eaiServerEntityService; - - public EAILogDAO() { - // empty - } - - /** - * 1. 기능 : 메시지의 Type이 EBCDIC인지 판단 2. 처리 개요 : - 로그시퀀스에 맞는 Adapter의 메시지 type을 비교 - - * EBC인지 판별 3. 주의사항 - * - * @param srcIfType String - * @param tgtIfType String - * @param logPssSno int - * @param srcAdapterMsgType String - * @param tgtAdapterMsgType String - * @return boolean - **/ - public boolean isEBC(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgType, - String tgtAdapterMsgType) { - - boolean isEBCDIC = false; - - // SS. SA Type - if (logPssSno == 100) { - if (MessageType.EBC.equals(srcAdapterMsgType)) { - isEBCDIC = true; - } - } else if (logPssSno == 200) { - if (MessageType.EBC.equals(tgtAdapterMsgType)) { - isEBCDIC = true; - } - } else if (logPssSno == 300) { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - if (MessageType.EBC.equals(srcAdapterMsgType)) { - isEBCDIC = true; - } - } else { - if (MessageType.EBC.equals(tgtAdapterMsgType)) { - isEBCDIC = true; - } - } - } - // 400 - else if (logPssSno == 400) { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - if (MessageType.EBC.equals(tgtAdapterMsgType)) { - isEBCDIC = true; - } - } else { - if (MessageType.EBC.equals(srcAdapterMsgType)) { - isEBCDIC = true; - } - } - } - // 900 - else { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - if (MessageType.EBC.equals(tgtAdapterMsgType)) { - isEBCDIC = true; - } - } else { - if (MessageType.EBC.equals(srcAdapterMsgType)) { - isEBCDIC = true; - } - } - } - return isEBCDIC; - } - - public boolean isUTF8(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgEncode, - String tgtAdapterMsgEncode) { - boolean isUTF = false; - if (logger.isInfo()) { - logger.info(String.format("EAILogDAO] isUTF8 %s %s %s %s %s", srcIfType, tgtIfType, logPssSno, - srcAdapterMsgEncode, tgtAdapterMsgEncode)); - } - - String adapterMsgEncode = ""; - // SS. SA Type - if (logPssSno == 100) { - adapterMsgEncode = srcAdapterMsgEncode; - } else if (logPssSno == 200) { - adapterMsgEncode = tgtAdapterMsgEncode; - } else if (logPssSno == 300) { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - adapterMsgEncode = srcAdapterMsgEncode; - } else { - adapterMsgEncode = tgtAdapterMsgEncode; - } - } - // 400 - else if (logPssSno == 400) { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - adapterMsgEncode = tgtAdapterMsgEncode; - } else { - adapterMsgEncode = srcAdapterMsgEncode; - } - } - // 900 - else { - if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { - adapterMsgEncode = tgtAdapterMsgEncode; - } else { - adapterMsgEncode = srcAdapterMsgEncode; - } - } - isUTF = StringUtils.equalsIgnoreCase(adapterMsgEncode, "UTF-8"); - return isUTF; - } - - /** - * 1. 기능 : EAI 서비스 로그 셋팅 2. 처리 개요 : - TSEAILG01(EAI서비스로그) 로그값 셋팅 - - * TSEAILG03(EAI로그업무데이터서브정보) insert 여부 결정 3. 주의사항 - * - * @param message EAIMessage - * @exception DAOException - **/ - public void addEAISvcLog(EAIMessage message, Properties prop) throws Exception { - String apndBwkDataYn = "N"; // 추가업무데이터 여부 - - // 개별메시지 - String bizMsg = message.getStandardMessage().getBizData(); - - ServiceMessage svcMsg = message.getCurrentSvcMsg(); - String bizMsgStr = ""; - - // transformer 적용 - String svcTsmtUsgTp = message.getSvcTsmtUsgTp(); // 기동 Syunc/Async - String psvItfTp = svcMsg.getPsvItfTp(); // 수동 Syunc/Async - int logPssSno = message.getLogPssSno(); - String rspErrCd = message.getRspErrCd(); - - // Duplication Error 방지를 위해 - // 원 로그처리일련번호를 저장 : 2009.07.13 - int orglogPssSno = logPssSno; - - int svcLogLvl = message.getSvcLogLvl(); - boolean loggingBizData = true; - - // 특정거래에 대해 업무데이터를 저외함. - if (svcLogLvl > 3) { - loggingBizData = false; - } - if (logger.isWarn()) - logger.warn("EAILogDAO] loggingBizData - " + loggingBizData); - - // 복합거래인 경우 2X1,3X1 -> 200, 2X2,3X2 -> 300 처럼 처리한다. - if ((logPssSno > 200 && logPssSno < 300) || (logPssSno > 300 && logPssSno < 400)) { - if ((logPssSno % 2) == 1) { - logPssSno = 200; - } else { - logPssSno = 300; - } - } - - // 업무테이터 처리 - // 1. Get Source, Target Adapter Group Name - String srcAdapterGroupName = message.getSngSysItfTp(); - String tgtAdapterGroupName = message.getCurrentSvcMsg().getPsvSysItfTp(); - - // 2. Get Source, Target Adapter GroupVO - AdapterManager adapterManager = AdapterManager.getInstance(); - AdapterGroupVO srcAdapterGrpVO = adapterManager.getAdapterGroupVO(srcAdapterGroupName); - AdapterGroupVO tgtAdapterGrpVO = adapterManager.getAdapterGroupVO(tgtAdapterGroupName); - - // 3. Get Source, Target Adapter Message Type - String srcAdapterMsgType = null; - String srcAdptrMsgPtrnCd = null; - String tgtAdapterMsgType = null; - String tgtAdptrMsgPtrnCd = null; - - String srcAdapterMsgEncode = null; - String tgtAdapterMsgEncode = null; - - if (srcAdapterGrpVO == null) { - srcAdapterMsgType = MessageType.ASC; - srcAdapterMsgEncode = Charset.defaultCharset().name(); - if (logger.isWarn()) { - logger.warn("EAILogDAO] Source Adapter null. eai service code=" + message.getEAISvcCd()); - } - } else { - srcAdapterMsgType = srcAdapterGrpVO.getMessageType(); - srcAdptrMsgPtrnCd = srcAdapterGrpVO.getAdptrMsgPtrnCd(); - srcAdapterMsgEncode = StringUtils.defaultIfBlank(srcAdapterGrpVO.getMessageEncode(), - Charset.defaultCharset().name()); - } - - if (tgtAdapterGrpVO == null) { - tgtAdapterMsgType = MessageType.ASC; - tgtAdapterMsgEncode = Charset.defaultCharset().name(); - if (logger.isWarn()) { - logger.warn("EAILogDAO] Target Adapter null. eai service code=" + message.getEAISvcCd()); - } - } else { - tgtAdapterMsgType = tgtAdapterGrpVO.getMessageType(); - tgtAdptrMsgPtrnCd = tgtAdapterGrpVO.getAdptrMsgPtrnCd(); - tgtAdapterMsgEncode = StringUtils.defaultIfBlank(tgtAdapterGrpVO.getMessageEncode(), - Charset.defaultCharset().name()); - } - - // SUBSTANDARD Logging - StandardMessage subMessage = message.getSubMessage(); - boolean isSubLogging = false; - if(subMessage != null) { - isSubLogging = checkSubLogging(svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno); - if (logger.isDebug()) { - logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING checkSubLogging %s-%s %s-%s %d => %s", - svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno, isSubLogging) ); - } - } - if(isSubLogging) { - String headerData = subMessage.toFixedString(false, EncodingVar.flatEncoding); - if (logger.isDebug()) { - logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING UUID: %s, LOGSEQ: %s, HEADER: %s", - message.getSvcOgNo(), logPssSno, headerData) ); - } - try { - String layoutName = StandardMessageManager.getInstance().getVersionLayoutName(); - - SubMessageLog subMessageLog = (SubMessageLog) applicationContext.getBean(RollingTable.class, SubMessageLog.class, - message.getMsgRcvTm()); - SubMessageLogId subLogId = new SubMessageLogId(); - subMessageLog.setId(subLogId); - subLogId.setEaisvcserno(message.getSvcOgNo()); - subLogId.setLogprcssserno(String.valueOf(orglogPssSno)); - subMessageLog.setLayoutname(layoutName); - subMessageLog.setHeaderdata(headerData); - subMessageLogLogger.save(subMessageLog); - } - catch(Exception ex) { - logger.error( String.format("EAILogDAO] SUBSTANDARD-LOGGING ERROR UUID: %s, LOGSEQ: %s, HEADER: %s", - message.getSvcOgNo(), logPssSno, headerData), ex); - } - } - - String bwkData = ""; - String addBwkData = ""; - String refMsgID = ""; - - if (loggingBizData) { - // --------------------------------------------------- - // LogMasking 을 위해 변환이 등록된 경우에만 - // 변환을 통해 처리하도록 수정 - // --------------------------------------------------- - boolean isMasked = false; - boolean isMasking = false; - - // 변환이 등록된 경우 - if ("1".equals(svcMsg.getCnvEn())) { - TransformManager manager = TransformManager.getManager(); - Transform info = null; - Layout l = null; - - // AA - 요청변환에서 - if (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)) { - info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명 - } - // AA이 아닌 경우 - // - 100, 200 요청변환에서 - // - 300, 400 응답변환에서 - else { - if (logPssSno == 100 || logPssSno == 200) { - info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명 - } else { - if (rspErrCd.equals(EAIMessageKeys.BWK_ERRMSG_CODE)) { // 업무에러(RIBEAI999999) - info = manager.getTransform(svcMsg.getErrRspCnvMsgID()); // 오류응답변환메시지ID명 - if (info == null) { - info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명 - } - } else if (MessageUtil.checkRspErrCd(rspErrCd)) { - info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명 - } - } - } - - // 등록된 변환이 있는 경우 - if (info != null) { - if (logger.isInfo()) - logger.info("EAILogDAO] Masking Log Message - " + message.getEAISvcCd()); - - // 변환은 등록되어 있으나 레이아웃정보가 삭제된 경우 - // 정삭적인 Case 가 아님. - try { - if (logPssSno == 100 || logPssSno == 300 || logPssSno == 900) - l = info.getSourceLayout(0); - else - l = info.getTargetLayout(); - } catch (Exception e) { - if (logger.isInfo()) - logger.info("EAILogDAO] Layout not set"); - } - - // Layout 에 Mask 필드가 없는 경우 SKIP 하도록 한다. - if (l != null) { - try { - Item root = l.getRootItem(); - isMasking = root.existMask(); - } catch (Exception e) { - if (logger.isWarn()) - logger.info("EAILogDAO] Check Masking field Error - " + e.getMessage()); - isMasking = false; - } - if (logger.isInfo()) - logger.info( - "EAILogDAO] Message has Masking field [" + l.getName() + "][ " + isMasking + "]"); - } - - if (isMasking) { - try { - bizMsgStr = LogMessageUtil.makeMaskData(message, bizMsg, l, logPssSno, tgtAdptrMsgPtrnCd, - svcTsmtUsgTp, psvItfTp); - isMasked = true; - } catch (Exception e) { - if (logger.isWarn()) - logger.warn("EAILogDAO] LogMasking Error - " + e.getMessage(), e); - isMasked = false; - } - } else { - if (logger.isInfo()) - logger.info("EAILogDAO] Masking is unnecessary - Skip Masking "); - - isMasked = false; - } - } else { - if (logger.isInfo()) - logger.info("EAILogDAO] Transform Not Found - Masking Unable"); - isMasked = false; - } - // Masking check END - } - -// boolean isUtf8 = isUTF8(svcTsmtUsgTp, psvItfTp, logPssSno, srcAdapterMsgEncode, tgtAdapterMsgEncode); - // 요청 변환이 등록되지 않은 경우 또는 Masking 처리를 실패한 경우 - if (!isMasked) { - if (bizMsg == null) { - if (logger.isInfo()) - logger.info("EAILogDAO] Message is NULL"); - bizMsgStr = ""; - } else { - if (logger.isInfo()) - logger.info("EAILogDAO] Message is String Type"); - bizMsgStr = bizMsg; - } - } - - // EAI 업무 개별부(32,000bytes) - /** - * 업무데이터에 대한정의 1. biz 데이터 2. 표준전문 JSON 데이터 3. 전장표 - */ - StringBuilder sb = new StringBuilder(); - String biz = ""; - String header = message.getStandardMessage().toFixedString(false, EncodingVar.flatEncoding); - - String mdclData = ""; - if (bizMsgStr == null) { - bizMsgStr = ""; - } - - // 암호화 - /* - Charset hexaCharset = Charset.forName("euc-kr"); - if ("Y".equalsIgnoreCase(EncryptionManager.getInstance().getEncryptYN())) { - try { - biz = HexaConverter.bytesToHexa(bizMsgStr.getBytes(hexaCharset)); - } catch (Exception e) { - logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage()); - } - try { - header = HexaConverter.bytesToHexa(header.getBytes(hexaCharset)); - } catch (Exception e) { - logger.error("EAIFileLogger] header encryption Error - " + e.getMessage()); - } - try { - mdclData = HexaConverter.bytesToHexa(mdclData.getBytes(hexaCharset)); - } catch (Exception e) { - logger.error("EAIFileLogger] mdclData encryption Error - " + e.getMessage()); - } - } else { - biz = bizMsgStr; - } - */ - - // jwhong safeDB 암호화 - - if ("Y".equalsIgnoreCase(EncryptionManager.getInstance().getEncryptYN())) { - try { - biz = EncryptSafeDb(bizMsgStr); - } catch (Exception e) { - logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage()); - biz = bizMsgStr; - } - } else { - biz = bizMsgStr; - } - - // jwhong safeDB end - - // 임시코드 시작 - String logType = PropManager.getInstance().getProperty("BIZ_LOG_TYPE"); - if (!StringUtils.isBlank(logType)) { - if ("ALL".equals(logType)) { - sb.append(header).append("|").append(biz).append("|").append(mdclData); - } else if ("HEADER".equals(logType)) { - sb.append(header).append("|").append("|"); - } else if ("BODY".equals(logType)) { - sb.append("|").append(biz).append("|"); - } else if ("NONE".equals(logType)) { - sb.append("|").append("|"); - } - } else { - sb.append(header).append("|").append(biz).append("|").append(mdclData); - } - // 임시코드 종료 - - bwkData = sb.toString(); - - String[] refMsgIDs = svcMsg.getRefMsgIDs(); - - // 입력메시지IDS 배열은 delimiter로 구분하여 200byte 만 insert - StringBuilder sbMsgIds = new StringBuilder(); - if (refMsgIDs != null && refMsgIDs.length > 0) { - for (int i = 0; i < refMsgIDs.length - 1; i++) { - sbMsgIds.append(refMsgIDs[i]).append(", "); - } - sbMsgIds.append(refMsgIDs[refMsgIDs.length - 1]); - refMsgID = sbMsgIds.toString(); - - if (refMsgID.getBytes().length > 200) { - refMsgID = StringUtil.chunkString(refMsgID, 200); - } - } - } // 업무데이터 로깅을 할 경우에만 END loggingBizData - - EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, message.getMsgRcvTm()); - - try { - // 1/1000초로 변경 - String msgPssTm = DatetimeUtil.getCurrentTime(message.getMsgPssTm()); - - String serverName = EAIServerManager.getInstance().getLocalServerName(); - String serverGroupName = EAIServerManager.getInstance().getServerType(); - - // EAI 업무 공통부(100 bytes) - EAILogId eaiLogId = new EAILogId(); - eaiLog.setId(eaiLogId); - - // EAI업무구분코드 - eaiLogId.setEaibzwkdstcd(message.getBwkCls()); - // 메시지수신시각 - eaiLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm())); - // EAI서비스일련번호 - eaiLogId.setEaisvcserno(message.getSvcOgNo()); - // 로그처리일련번호 - eaiLogId.setLogprcssserno(String.valueOf(orglogPssSno)); - // EAI서버인스탄스명 - eaiLog.setEaisevrinstncname(serverName); - - // EAI서비스명 - eaiLog.setEaisvcname(message.getEAISvcCd()); - // 서비스시각유무 - eaiLog.setSvchmseonot(message.getSvcTmEn()); - // 서비스동기사용구분코드 - eaiLog.setSvcmotivusedstcd(message.getSvcTsmtUsgTp()); - // 서비스처리구분명 - eaiLog.setSvcprcssdsticname(message.getSvcPssTp()); - // 흐름통제라우팅명 - eaiLog.setFlowctrlroutname(message.getFlwCntlRtnNm()); - - // 통합구분명 - eaiLog.setIntgradsticname(message.getUnifTp()); - // 기동서비스구분명 - eaiLog.setGstatsvcdsticname(message.getSngSvcCls()); - // 서비스처리번호 - eaiLog.setSvcprcssno(String.valueOf(message.getSvcPssSeq())); - // 서비스전컬럼로그여부 - eaiLog.setSvcbfclmnlogyn(message.getSvcWlColLogYn()); - // 표준메시지사용여부 - eaiLog.setStndmsguseyn(message.getStdMsgUsgCls()); - - // 기동시스템어댑터업무그룹명 - eaiLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp()); - // 현재메시지ID명 - eaiLog.setPrsntmsgidname(message.getLydMsgID()); - // 응답에러코드명 - eaiLog.setRspnserrcdname(message.getRspErrCd()); - // 메시지처리시각 - eaiLog.setMsgprcssyms(msgPssTm); - // 서버로그레벨번호 - eaiLog.setSevrloglvelno(String.valueOf(message.getSvrLogLvl())); - - // 서비스로그레벨번호 - eaiLog.setSvcloglvelno(String.valueOf(message.getSvcLogLvl())); - // 오류EAI서비스명 - eaiLog.setErreaisvcname(message.getErrEAISvcName()); - // 요청오류변환ID명 - eaiLog.setDmnderrchngidname(message.getDmndErrChngIDName()); - // 요청에러필드명 - eaiLog.setDmnderrfldname(message.getDmndErrFldName()); - // 응답오류변환ID명 - eaiLog.setRspnserrchngidname(message.getRspnsErrChngIDName()); - - // 응답에러필드명 - eaiLog.setRspnserrfldname(message.getRspnsErrFldName()); - // 수동인터페이스구분명 - eaiLog.setPsvintfacdsticname(svcMsg.getPsvItfTp()); - // 수동업무시스템명 - eaiLog.setPsvbzwksysname(svcMsg.getPsvBwkSysNm()); - // 수동시스템ID명 - eaiLog.setPsvsysidname(svcMsg.getPsvSysID()); - // 수동시스템서비스구분명 - eaiLog.setPsvsyssvcdsticname(svcMsg.getPsvSysSvcCd()); - - // 수동시스템어댑터업무그룹명 - eaiLog.setPsvsysadptrbzwkgroupname(svcMsg.getPsvSysItfTp()); - // 장애극복여부 - eaiLog.setFlovryn(svcMsg.getFlOvrCls()); - // 변환여부 - eaiLog.setChngyn(svcMsg.getCnvEn()); - // 변환메시지ID명 - eaiLog.setChngmsgidname(svcMsg.getCnvMsgID()); - // 입력메시지ID명 - eaiLog.setInptmsgidname(refMsgID); - - // 기본응답메시지비교내용 - eaiLog.setBascrspnsmsgcmprctnt(svcMsg.getBsRspMsgCprVl()); - // 기본응답변환여부 - eaiLog.setBascrspnschngyn(svcMsg.getBsRspCnvEn()); - // 기본응답변환메시지ID명 - eaiLog.setBascrspnschngmsgidname(svcMsg.getBsRspCnvMsgID()); - // 오류응답메시지비교내용 - eaiLog.setErrrspnsmsgcmprctnt(svcMsg.getErrRspMsgCprVl()); - // 오류응답변환여부 - eaiLog.setErrrspnschngyn(svcMsg.getErrRspCnvEn()); - - // 오류응답변환메시지ID명 - eaiLog.setErrrspnschngmsgidname(svcMsg.getErrRspCnvMsgID()); - // 다음서비스처리번호 - eaiLog.setNextsvcprcssno(String.valueOf(svcMsg.getNxtSvcPssSeq())); - // 아웃바운드라우팅명 - eaiLog.setOutbndroutname(svcMsg.getOutbRtnNm()); - // 타임아웃값 - eaiLog.setToutval(svcMsg.getTmoVl()); - // 보상서비스처리명 - eaiLog.setCmpensvcprcssname(svcMsg.getCpnsSvcPssCd()); - // 추가업무데이터여부 - eaiLog.setSupplbzwkdatayn(apndBwkDataYn); - // 키관리메시지내용 - eaiLog.setKeymgtmsgctnt(svcMsg.getKeyMgtMsgVl()); - - // SS,SA - Send - 100 - // AA - Send - 100 - // AA - Recv - 100, 300 - // AS - 100 - String telgmDmndDstcd = message.getMapper().getSendRecvDivision(message.getStandardMessage()); - if (prop != null && ((EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && logPssSno == 100) - || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp) - && STDMessageKeys.SEND_RECV_CD_RECV.equals(telgmDmndDstcd) - && (logPssSno == 100 || logPssSno == 300)) - || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp) - && STDMessageKeys.SEND_RECV_CD_SEND.equals(telgmDmndDstcd) && logPssSno == 100) - || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.SYNC_SVC.equals(psvItfTp) - && logPssSno == 100))) { - eaiLog.setTrackasiskey1ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY1)); // 추적보조키1내용 - eaiLog.setTrackasiskey2ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY2)); // 추적보조키2내용 - eaiLog.setTrackasiskey3ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY3)); // 추적보조키3내용 - eaiLog.setTrackasiskey4ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY4)); // 추적보조키4내용 - } - - // EAI서비스코드의 그룹회사코드 - eaiLog.setEaigroupcodstcd(message.getGroupCoCd()); - // PGUID - eaiLog.setPguid(message.getMapper().getOrgGuid(message.getStandardMessage())); - // 송수신구분 - eaiLog.setTrantype(message.getTranType()); - // - eaiLog.setRspnschngmsgtype(message.getRspnsChngMsgType()); - - // log level 'E' or 'F' - if ("E".equals(message.getRspErrCd().substring(1, 2)) - || "F".equals(message.getRspErrCd().substring(1, 2))) { - // EAI에러코드 - eaiLog.setEaierrcd(message.getRspErrCd()); - // EAI에러내용 - eaiLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 1000)); - } - - // 서버그룹명 - eaiLog.setSevrgroupname(serverGroupName); - // 업체코드 - eaiLog.setCompanycode(message.getCompanyCode()); - // 전문크기, add 20190404 - eaiLog.setSplizlength(message.getSplizLength()); - // index 60 - // add 20190404 // adapterNickName - eaiLog.setAdptrinsticode(message.getAdptrInstiCode()); - - // 거래ID - eaiLog.setTxid(message.getTxId()); - // 참조ID - eaiLog.setRefkey(message.getRefKey()); - // 대외업무구분코드 - eaiLog.setExtbizcd(message.getExtBizCd()); - // EAI 업무 개별부(32,000bytes) - if (bwkData == null || bwkData.equals("")) - bwkData = " "; - eaiLog.setBzwkdatactnt(bwkData); - String standardLayoutName = System.getProperty("STANDARD_LAYOUT_NAME"); - // 표준전문레이아웃 명 - eaiLog.setStdlayoutname(standardLayoutName); - - // clientId 로그에 추가 - String clientId = message.getClientId(); - eaiLog.setClientid(clientId); - - // client IP 로그에 추가 - String clientIp = message.getClientIp(); - eaiLog.setClientip(clientIp); - - /** - * CLIENT ID 있을 경우 APP, 기관정보 로그에 추가 - * TODO: ClientVO의 경우 spring security oauth의 ClientDetails를 상속받고 있어 OAUTH가 아닌 인증의 경우에 대한 처리 추가 필요 - */ - if(StringUtils.isNotBlank(clientId)) { - ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId); - if (clientVO != null) { - eaiLog.setClientname(clientVO.getClientName()); - eaiLog.setOrgid(clientVO.getOrgId()); - eaiLog.setOrgname(clientVO.getOrgName()); - } - } - - eaiLogEntityService.save(eaiLog); - - } catch (Exception e) { - logger.error( - "DB Logging[MASTER] Failed - " + message.getEAISvcCd() + "|" + orglogPssSno + "|" - + message.getSvcOgNo() + "|" + message.getMapper().getGuid(message.getStandardMessage()), - e); - - throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG001")); - } - - // 에러로그를 별도의 테이블에 저장하도록 한다. - if (!MessageUtil.checkRspErrCd(message.getRspErrCd())) { - try { - // 거래통제, 유량제어에 의한 에러는 저장하지 않도록 한다. - if (!(EAIMessageKeys.EAI_BLOCKED_CODE.equals(message.getRspErrCd()) - || EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE.equals(message.getRspErrCd()))) { - addErrorLog(message); // 에러로그 - } - } catch (Exception ex) { - logger.warn("에러로그테이블 저장 SKIP 에러발생 - " + ex.getMessage()); - } - } - - } - - public void addErrorLog(EAIMessage message) throws DAOException { - try { - String serverName = EAIServerManager.getInstance().getLocalServerName(); - - EAIErrorLog eaiErrorLog = (EAIErrorLog) applicationContext.getBean(RollingTable.class, EAIErrorLog.class, - message.getMsgRcvTm()); - - // EAI업무구분코드 - EAIErrorLogId eaiErrorLogId = new EAIErrorLogId(); - eaiErrorLog.setId(eaiErrorLogId); - - eaiErrorLogId.setEaibzwkdstcd(message.getBwkCls()); - // 메시지수신시각 - eaiErrorLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm())); - // EAI거래일련번호 - eaiErrorLogId.setEaisvcserno(message.getSvcOgNo()); - // 로그처리일련번호 - eaiErrorLogId.setLogprcssserno(String.valueOf(message.getLogPssSno())); - - // EAI서비스명 - eaiErrorLog.setEaisvcname(message.getEAISvcCd()); - // 응답에러코드명 - eaiErrorLog.setRspnserrcdname(message.getRspErrCd()); - // 기동시스템어댑터업무그룹명 - eaiErrorLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp()); - // 수동시스템어댑터업무그룹명 - eaiErrorLog.setPsvsysadptrbzwkgroupname(message.getCurrentSvcMsg().getPsvSysItfTp()); - - if ("E".equals(message.getRspErrCd().substring(1, 2)) - || "F".equals(message.getRspErrCd().substring(1, 2))) { - // EAI에러코드 - eaiErrorLog.setEaierrcd(message.getRspErrCd()); - // EAI에러내용 - eaiErrorLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 500)); - } - - // EAI서버인스턴스명 - eaiErrorLog.setEaisevrinstncname(serverName); - // 로깅시스템ID - EAIServerVO eaiServerVO = EAIServerManager.getInstance().getEAIServer(serverName); - if(eaiServerVO != null) { - eaiErrorLog.setLgingsysid(eaiServerVO.getHostName()); - } - // 메시지처리일시 - eaiErrorLog.setMsgprcssyms(DatetimeUtil.getCurrentTime(message.getMsgPssTm())); - // EAI그룹회사코드 - eaiErrorLog.setEaigroupcodstcd(message.getGroupCoCd()); - - } catch (Exception e) { - logger.error("DB Logging[ERROR_LOG] Failed - " + message.getEAISvcCd() + "|" + message.getLogPssSno() + "|" - + message.getSvcOgNo(), e); - throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); - } - } - - public void addStaticLog(StatMonitorLogVO vo) throws DAOException { - try { - StatLog statLog = statLogMapper.toEntity(vo); - statLogLogger.save(statLog); - } catch (Exception e) { - logger.error("DB Logging[STATIC_LOG] Failed - " + vo.toString(), e); - throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); - } - } - - public void addStaticTranCdLog(StatMonitorLogVO vo) throws DAOException { - try { - StatTranLog statTranLog = statTranLogMapper.toEntity(vo); - statTranLogLogger.save(statTranLog); - } catch (Exception e) { - logger.error("DB Logging[STATIC_TRANCD_LOG] Failed - " + vo.toString(), e); - throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); - } - } - - public void addStaticAdapterLog(StatMonitorLogVO vo) throws DAOException { - try { - StatAdapterLog statAdapterLog = statAdapterLogMapper.toEntity(vo); - statAdapterLogLogger.save(statAdapterLog); - } catch (Exception e) { - logger.error("DB Logging[STATIC_ADAPTER_LOG] Failed - " + vo.toString(), e); - throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); - } - } - - public boolean getCheck() throws DAOException { - return eaiServerEntityService.checkConnection(); - } - - private boolean checkSubLogging(String svcTsmtUsgTp, String psvItfTp, String srcAdptrMsgPtrnCd, String tgtAdptrMsgPtrnCd, int logPssSno) { - boolean isAsyncSvc = EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp); - boolean isSrcStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(srcAdptrMsgPtrnCd); - -// // SOURCE : AA : 100, 300, ELSE: 100, 400 - if(isSrcStandard && ( (isAsyncSvc && (logPssSno == 100 || logPssSno == 300)) || - (!isAsyncSvc && (logPssSno == 100 || logPssSno == 400)) ) ) { - return true; - } - - boolean isTgtStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(tgtAdptrMsgPtrnCd); -// // TARGET : AA : 200, 400, ELSE : 200, 300 - if (isTgtStandard && ( (isAsyncSvc && (logPssSno == 200 || logPssSno == 400)) || - (!isAsyncSvc && (logPssSno == 200 || logPssSno == 300)) ) ) { - return true; - } - return false; - } - - - private String EncryptSafeDb(String attribute) { - String originalAttribute = attribute; - if (StringUtils.isNotEmpty(attribute)) { - KjbSafedbWrapper wrapper = KjbSafedbWrapper.getInstance(); - attribute = wrapper.encryptNotRnnoString(attribute); - - if (logger.isInfo()) { - // originalAttribute 홀수 글자 마스킹 - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < originalAttribute.length(); i++) { - if (i % 2 == 0) { - sb.append(originalAttribute.charAt(i)); - } else { - sb.append("*"); - } - } - - originalAttribute = sb.toString(); - System.out.println("DB 암호화 #2 : {"+ originalAttribute +"} -> {"+attribute+"}"); - //logger.debug("DB 암호화 #2 : {} -> {}", originalAttribute, attribute); - } - } - return attribute; - - } - - public String DecryptSafeDb(String dbData) { - - String dbDataOriginal = dbData; - if (StringUtils.isNotEmpty(dbData)) { - if (this.isEncrypted(dbData)) { - KjbSafedbWrapper safeDBWrapper = KjbSafedbWrapper.getInstance(); - try { - dbData = safeDBWrapper.decryptNotRnno(dbData); - } catch (Exception e) { - // 복호화 실패시 원본 반환 - String logData = dbData.length() <= 3 ? dbData : dbData.substring(0, 3) + "..."; - logger.warn("DB 복호화 실패: 복호화하지 않고 원본 반환. dbData={} (Length : {})", logData, dbData.length()); - return dbData; - } - } else { - logger.debug("DB 복호화 경고: Base64 형식이 아님. 복호화하지 않고 원본 반환. dbData={}", dbData); - } - } - - //logger.debug("DB 복호화 #2 : {} -> {}", dbDataOriginal, dbData); - - return dbData; - } - - /** - * 암호화 여부 확인(base64 인코딩 여부로 판단, 또는 0-9, - 로 구성된 경우 암호화 되지 않은 걸로 판단(연락처)) - * @param data - * @return - */ - private boolean isEncrypted(String data) { - if (StringUtils.isEmpty(data)) { - return false; - } - - // 숫자, - 로만 구성된 경우 암호화 되지 않은 걸로 판단 (ex: 연락처) - if (data.matches("^[0-9-]+$")) { - return false; - } - - data = data.trim(); - - // Base64 형식 체크 - if (!Utils.isBase64(data)) { - return false; - } - - // Base64 길이 체크 (4의 배수) - if (data.length() % 4 != 0) { - return false; - } - - - return true; - } - - - /* - private String EncryptSafeDb(String msg) { - PropManager propManager = PropManager.getInstance(); - String safeDbPath = propManager.getProperty("SafeDB","safedb.path"); - - SimpleSafeDB safedb = SimpleSafeDB.getInstance(); - boolean loginResult = false; - if(!safedb.login()) { - loginResult = safedb.getSafeDBConfigMgr().isLoginCheck(); - } - - String userName = "SAFEDB"; - String tableName = "SAFEDB.POLICY"; - String columnName1 = "bzwkdatactnt"; - - byte[] byteMsg = msg.getBytes(StandardCharsets.UTF_8); - byte[] encryptedBytes1 = null; - - try { - encryptedBytes1 = safedb.encrypt(userName, tableName, columnName1, byteMsg); - System.out.println("Encrypted Data : [" + new String(encryptedBytes1) + "]"); - - byte[] decryptedBytes1 = safedb.decrypt(userName, tableName, columnName1, encryptedBytes1); - - } catch (SafeDBSDKException e) { - e.printStackTrace(); - - } - - String encryptedMsg = new String(encryptedBytes1, StandardCharsets.UTF_8); - return encryptedMsg; - } - */ - -} +package com.eactive.eai.common.logger; + +import java.nio.charset.Charset; +import java.util.Properties; + +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.eactive.eai.authserver.vo.ClientVO; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.eactive.eai.adapter.AdapterGroupVO; +import com.eactive.eai.adapter.AdapterManager; +import com.eactive.eai.agent.encryption.EncryptionManager; +import com.eactive.eai.common.dao.DAOException; +import com.eactive.eai.common.exception.ExceptionUtil; +import com.eactive.eai.common.logger.EAILogLogger; +import com.eactive.eai.common.logger.StatAdapterLogLogger; +import com.eactive.eai.common.logger.StatLogLogger; +import com.eactive.eai.common.logger.StatTranLogLogger; +import com.eactive.eai.common.logger.SubMessageLogLogger; +import com.eactive.eai.common.logger.mapper.StatAdapterLogMapper; +import com.eactive.eai.common.logger.mapper.StatLogMapper; +import com.eactive.eai.common.logger.mapper.StatTranLogMapper; +import com.eactive.eai.common.message.EAIMessage; +import com.eactive.eai.common.message.EAIMessageKeys; +import com.eactive.eai.common.message.MessageType; +import com.eactive.eai.common.message.ServiceMessage; +import com.eactive.eai.common.monitor.StatMonitorLogVO; +import com.eactive.eai.common.property.PropManager; + +import com.eactive.eai.common.server.EAIServerManager; +import com.eactive.eai.common.server.EAIServerVO; +import com.eactive.eai.common.server.loader.EAIServerLoader; +import com.eactive.eai.common.util.DatetimeUtil; +import com.eactive.eai.common.util.Logger; +import com.eactive.eai.common.util.MessageUtil; +import com.eactive.eai.common.util.StringUtil; +import com.eactive.eai.data.RollingTable; +import com.eactive.eai.data.entity.onl.logger.EAIErrorLog; +import com.eactive.eai.data.entity.onl.logger.EAIErrorLogId; +import com.eactive.eai.data.entity.onl.logger.EAILog; +import com.eactive.eai.data.entity.onl.logger.EAILogId; +import com.eactive.eai.data.entity.onl.logger.StatAdapterLog; +import com.eactive.eai.data.entity.onl.logger.StatLog; +import com.eactive.eai.data.entity.onl.logger.StatTranLog; +import com.eactive.eai.data.entity.onl.logger.SubMessageLog; +import com.eactive.eai.data.entity.onl.logger.SubMessageLogId; +import com.eactive.eai.message.EncodingVar; +import com.eactive.eai.message.StandardMessage; +import com.eactive.eai.message.manager.StandardMessageManager; +import com.eactive.eai.transformer.layout.Item; +import com.eactive.eai.transformer.layout.Layout; +import com.eactive.eai.transformer.transform.Transform; +import com.eactive.eai.transformer.transform.TransformManager; +import com.eactive.eai.util.HexaConverter; +import com.ext.eai.common.stdmessage.STDMessageKeys; +// safeDB +import com.eactive.ext.kjb.safedb.KjbSafedbWrapper; +import com.eactive.ext.kjb.safedb.Utils; +// until here + + +@Service +@Transactional +public class EAILogDAO { +//extends BaseDAO { + static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private EAILogLogger eaiLogEntityService; + + @Autowired + private SubMessageLogLogger subMessageLogLogger; + + @Autowired + private StatLogLogger statLogLogger; + + @Autowired + private StatTranLogLogger statTranLogLogger; + + @Autowired + private StatAdapterLogLogger statAdapterLogLogger; + + @Autowired + private StatLogMapper statLogMapper; + + @Autowired + private StatTranLogMapper statTranLogMapper; + + @Autowired + private StatAdapterLogMapper statAdapterLogMapper; + + @Autowired + private EAIServerLoader eaiServerEntityService; + + public EAILogDAO() { + // empty + } + + /** + * 1. 기능 : 메시지의 Type이 EBCDIC인지 판단 2. 처리 개요 : - 로그시퀀스에 맞는 Adapter의 메시지 type을 비교 - + * EBC인지 판별 3. 주의사항 + * + * @param srcIfType String + * @param tgtIfType String + * @param logPssSno int + * @param srcAdapterMsgType String + * @param tgtAdapterMsgType String + * @return boolean + **/ + public boolean isEBC(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgType, + String tgtAdapterMsgType) { + + boolean isEBCDIC = false; + + // SS. SA Type + if (logPssSno == 100) { + if (MessageType.EBC.equals(srcAdapterMsgType)) { + isEBCDIC = true; + } + } else if (logPssSno == 200) { + if (MessageType.EBC.equals(tgtAdapterMsgType)) { + isEBCDIC = true; + } + } else if (logPssSno == 300) { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + if (MessageType.EBC.equals(srcAdapterMsgType)) { + isEBCDIC = true; + } + } else { + if (MessageType.EBC.equals(tgtAdapterMsgType)) { + isEBCDIC = true; + } + } + } + // 400 + else if (logPssSno == 400) { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + if (MessageType.EBC.equals(tgtAdapterMsgType)) { + isEBCDIC = true; + } + } else { + if (MessageType.EBC.equals(srcAdapterMsgType)) { + isEBCDIC = true; + } + } + } + // 900 + else { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + if (MessageType.EBC.equals(tgtAdapterMsgType)) { + isEBCDIC = true; + } + } else { + if (MessageType.EBC.equals(srcAdapterMsgType)) { + isEBCDIC = true; + } + } + } + return isEBCDIC; + } + + public boolean isUTF8(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgEncode, + String tgtAdapterMsgEncode) { + boolean isUTF = false; + if (logger.isInfo()) { + logger.info(String.format("EAILogDAO] isUTF8 %s %s %s %s %s", srcIfType, tgtIfType, logPssSno, + srcAdapterMsgEncode, tgtAdapterMsgEncode)); + } + + String adapterMsgEncode = ""; + // SS. SA Type + if (logPssSno == 100) { + adapterMsgEncode = srcAdapterMsgEncode; + } else if (logPssSno == 200) { + adapterMsgEncode = tgtAdapterMsgEncode; + } else if (logPssSno == 300) { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + adapterMsgEncode = srcAdapterMsgEncode; + } else { + adapterMsgEncode = tgtAdapterMsgEncode; + } + } + // 400 + else if (logPssSno == 400) { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + adapterMsgEncode = tgtAdapterMsgEncode; + } else { + adapterMsgEncode = srcAdapterMsgEncode; + } + } + // 900 + else { + if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) { + adapterMsgEncode = tgtAdapterMsgEncode; + } else { + adapterMsgEncode = srcAdapterMsgEncode; + } + } + isUTF = StringUtils.equalsIgnoreCase(adapterMsgEncode, "UTF-8"); + return isUTF; + } + + /** + * 1. 기능 : EAI 서비스 로그 셋팅 2. 처리 개요 : - TSEAILG01(EAI서비스로그) 로그값 셋팅 - + * TSEAILG03(EAI로그업무데이터서브정보) insert 여부 결정 3. 주의사항 + * + * @param message EAIMessage + * @exception DAOException + **/ + public void addEAISvcLog(EAIMessage message, Properties prop) throws Exception { + String apndBwkDataYn = "N"; // 추가업무데이터 여부 + + // 개별메시지 + String bizMsg = message.getStandardMessage().getBizData(); + + ServiceMessage svcMsg = message.getCurrentSvcMsg(); + String bizMsgStr = ""; + + // transformer 적용 + String svcTsmtUsgTp = message.getSvcTsmtUsgTp(); // 기동 Syunc/Async + String psvItfTp = svcMsg.getPsvItfTp(); // 수동 Syunc/Async + int logPssSno = message.getLogPssSno(); + String rspErrCd = message.getRspErrCd(); + + // Duplication Error 방지를 위해 + // 원 로그처리일련번호를 저장 : 2009.07.13 + int orglogPssSno = logPssSno; + + int svcLogLvl = message.getSvcLogLvl(); + boolean loggingBizData = true; + + // 특정거래에 대해 업무데이터를 저외함. + if (svcLogLvl > 3) { + loggingBizData = false; + } + if (logger.isWarn()) + logger.warn("EAILogDAO] loggingBizData - " + loggingBizData); + + // 복합거래인 경우 2X1,3X1 -> 200, 2X2,3X2 -> 300 처럼 처리한다. + if ((logPssSno > 200 && logPssSno < 300) || (logPssSno > 300 && logPssSno < 400)) { + if ((logPssSno % 2) == 1) { + logPssSno = 200; + } else { + logPssSno = 300; + } + } + + // 업무테이터 처리 + // 1. Get Source, Target Adapter Group Name + String srcAdapterGroupName = message.getSngSysItfTp(); + String tgtAdapterGroupName = message.getCurrentSvcMsg().getPsvSysItfTp(); + + // 2. Get Source, Target Adapter GroupVO + AdapterManager adapterManager = AdapterManager.getInstance(); + AdapterGroupVO srcAdapterGrpVO = adapterManager.getAdapterGroupVO(srcAdapterGroupName); + AdapterGroupVO tgtAdapterGrpVO = adapterManager.getAdapterGroupVO(tgtAdapterGroupName); + + // 3. Get Source, Target Adapter Message Type + String srcAdapterMsgType = null; + String srcAdptrMsgPtrnCd = null; + String tgtAdapterMsgType = null; + String tgtAdptrMsgPtrnCd = null; + + String srcAdapterMsgEncode = null; + String tgtAdapterMsgEncode = null; + + if (srcAdapterGrpVO == null) { + srcAdapterMsgType = MessageType.ASC; + srcAdapterMsgEncode = Charset.defaultCharset().name(); + if (logger.isWarn()) { + logger.warn("EAILogDAO] Source Adapter null. eai service code=" + message.getEAISvcCd()); + } + } else { + srcAdapterMsgType = srcAdapterGrpVO.getMessageType(); + srcAdptrMsgPtrnCd = srcAdapterGrpVO.getAdptrMsgPtrnCd(); + srcAdapterMsgEncode = StringUtils.defaultIfBlank(srcAdapterGrpVO.getMessageEncode(), + Charset.defaultCharset().name()); + } + + if (tgtAdapterGrpVO == null) { + tgtAdapterMsgType = MessageType.ASC; + tgtAdapterMsgEncode = Charset.defaultCharset().name(); + if (logger.isWarn()) { + logger.warn("EAILogDAO] Target Adapter null. eai service code=" + message.getEAISvcCd()); + } + } else { + tgtAdapterMsgType = tgtAdapterGrpVO.getMessageType(); + tgtAdptrMsgPtrnCd = tgtAdapterGrpVO.getAdptrMsgPtrnCd(); + tgtAdapterMsgEncode = StringUtils.defaultIfBlank(tgtAdapterGrpVO.getMessageEncode(), + Charset.defaultCharset().name()); + } + + // SUBSTANDARD Logging + StandardMessage subMessage = message.getSubMessage(); + boolean isSubLogging = false; + if(subMessage != null) { + isSubLogging = checkSubLogging(svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno); + if (logger.isDebug()) { + logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING checkSubLogging %s-%s %s-%s %d => %s", + svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno, isSubLogging) ); + } + } + if(isSubLogging) { + String headerData = subMessage.toFixedString(false, EncodingVar.flatEncoding); + if (logger.isDebug()) { + logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING UUID: %s, LOGSEQ: %s, HEADER: %s", + message.getSvcOgNo(), logPssSno, headerData) ); + } + try { + String layoutName = StandardMessageManager.getInstance().getVersionLayoutName(); + + SubMessageLog subMessageLog = (SubMessageLog) applicationContext.getBean(RollingTable.class, SubMessageLog.class, + message.getMsgRcvTm()); + SubMessageLogId subLogId = new SubMessageLogId(); + subMessageLog.setId(subLogId); + subLogId.setEaisvcserno(message.getSvcOgNo()); + subLogId.setLogprcssserno(String.valueOf(orglogPssSno)); + subMessageLog.setLayoutname(layoutName); + subMessageLog.setHeaderdata(headerData); + subMessageLogLogger.save(subMessageLog); + } + catch(Exception ex) { + logger.error( String.format("EAILogDAO] SUBSTANDARD-LOGGING ERROR UUID: %s, LOGSEQ: %s, HEADER: %s", + message.getSvcOgNo(), logPssSno, headerData), ex); + } + } + + String bwkData = ""; + String addBwkData = ""; + String refMsgID = ""; + + if (loggingBizData) { + // --------------------------------------------------- + // LogMasking 을 위해 변환이 등록된 경우에만 + // 변환을 통해 처리하도록 수정 + // --------------------------------------------------- + boolean isMasked = false; + boolean isMasking = false; + + // 변환이 등록된 경우 + if ("1".equals(svcMsg.getCnvEn())) { + TransformManager manager = TransformManager.getManager(); + Transform info = null; + Layout l = null; + + // AA - 요청변환에서 + if (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)) { + info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명 + } + // AA이 아닌 경우 + // - 100, 200 요청변환에서 + // - 300, 400 응답변환에서 + else { + if (logPssSno == 100 || logPssSno == 200) { + info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명 + } else { + if (rspErrCd.equals(EAIMessageKeys.BWK_ERRMSG_CODE)) { // 업무에러(RIBEAI999999) + info = manager.getTransform(svcMsg.getErrRspCnvMsgID()); // 오류응답변환메시지ID명 + if (info == null) { + info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명 + } + } else if (MessageUtil.checkRspErrCd(rspErrCd)) { + info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명 + } + } + } + + // 등록된 변환이 있는 경우 + if (info != null) { + if (logger.isInfo()) + logger.info("EAILogDAO] Masking Log Message - " + message.getEAISvcCd()); + + // 변환은 등록되어 있으나 레이아웃정보가 삭제된 경우 + // 정삭적인 Case 가 아님. + try { + if (logPssSno == 100 || logPssSno == 300 || logPssSno == 900) + l = info.getSourceLayout(0); + else + l = info.getTargetLayout(); + } catch (Exception e) { + if (logger.isInfo()) + logger.info("EAILogDAO] Layout not set"); + } + + // Layout 에 Mask 필드가 없는 경우 SKIP 하도록 한다. + if (l != null) { + try { + Item root = l.getRootItem(); + isMasking = root.existMask(); + } catch (Exception e) { + if (logger.isWarn()) + logger.info("EAILogDAO] Check Masking field Error - " + e.getMessage()); + isMasking = false; + } + if (logger.isInfo()) + logger.info( + "EAILogDAO] Message has Masking field [" + l.getName() + "][ " + isMasking + "]"); + } + + if (isMasking) { + try { + bizMsgStr = LogMessageUtil.makeMaskData(message, bizMsg, l, logPssSno, tgtAdptrMsgPtrnCd, + svcTsmtUsgTp, psvItfTp); + isMasked = true; + } catch (Exception e) { + if (logger.isWarn()) + logger.warn("EAILogDAO] LogMasking Error - " + e.getMessage(), e); + isMasked = false; + } + } else { + if (logger.isInfo()) + logger.info("EAILogDAO] Masking is unnecessary - Skip Masking "); + + isMasked = false; + } + } else { + if (logger.isInfo()) + logger.info("EAILogDAO] Transform Not Found - Masking Unable"); + isMasked = false; + } + // Masking check END + } + +// boolean isUtf8 = isUTF8(svcTsmtUsgTp, psvItfTp, logPssSno, srcAdapterMsgEncode, tgtAdapterMsgEncode); + // 요청 변환이 등록되지 않은 경우 또는 Masking 처리를 실패한 경우 + if (!isMasked) { + if (bizMsg == null) { + if (logger.isInfo()) + logger.info("EAILogDAO] Message is NULL"); + bizMsgStr = ""; + } else { + if (logger.isInfo()) + logger.info("EAILogDAO] Message is String Type"); + bizMsgStr = bizMsg; + } + } + + // EAI 업무 개별부(32,000bytes) + /** + * 업무데이터에 대한정의 1. biz 데이터 2. 표준전문 JSON 데이터 3. 전장표 + */ + StringBuilder sb = new StringBuilder(); + String biz = ""; + String header = message.getStandardMessage().toFixedString(false, EncodingVar.flatEncoding); + + String mdclData = ""; + if (bizMsgStr == null) { + bizMsgStr = ""; + } + + // 암호화 + /* + Charset hexaCharset = Charset.forName("euc-kr"); + if ("Y".equalsIgnoreCase(EncryptionManager.getInstance().getEncryptYN())) { + try { + biz = HexaConverter.bytesToHexa(bizMsgStr.getBytes(hexaCharset)); + } catch (Exception e) { + logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage()); + } + try { + header = HexaConverter.bytesToHexa(header.getBytes(hexaCharset)); + } catch (Exception e) { + logger.error("EAIFileLogger] header encryption Error - " + e.getMessage()); + } + try { + mdclData = HexaConverter.bytesToHexa(mdclData.getBytes(hexaCharset)); + } catch (Exception e) { + logger.error("EAIFileLogger] mdclData encryption Error - " + e.getMessage()); + } + } else { + biz = bizMsgStr; + } + */ + + // jwhong safeDB 암호화 + + if ("Y".equalsIgnoreCase(EncryptionManager.getInstance().getEncryptYN())) { + try { + biz = EncryptSafeDb(bizMsgStr); + } catch (Exception e) { + logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage()); + biz = bizMsgStr; + } + } else { + biz = bizMsgStr; + } + + // jwhong safeDB end + + // 임시코드 시작 + String logType = PropManager.getInstance().getProperty("BIZ_LOG_TYPE"); + if (!StringUtils.isBlank(logType)) { + if ("ALL".equals(logType)) { + sb.append(header).append("|").append(biz).append("|").append(mdclData); + } else if ("HEADER".equals(logType)) { + sb.append(header).append("|").append("|"); + } else if ("BODY".equals(logType)) { + sb.append("|").append(biz).append("|"); + } else if ("NONE".equals(logType)) { + sb.append("|").append("|"); + } + } else { + sb.append(header).append("|").append(biz).append("|").append(mdclData); + } + // 임시코드 종료 + + bwkData = sb.toString(); + + String[] refMsgIDs = svcMsg.getRefMsgIDs(); + + // 입력메시지IDS 배열은 delimiter로 구분하여 200byte 만 insert + StringBuilder sbMsgIds = new StringBuilder(); + if (refMsgIDs != null && refMsgIDs.length > 0) { + for (int i = 0; i < refMsgIDs.length - 1; i++) { + sbMsgIds.append(refMsgIDs[i]).append(", "); + } + sbMsgIds.append(refMsgIDs[refMsgIDs.length - 1]); + refMsgID = sbMsgIds.toString(); + + if (refMsgID.getBytes().length > 200) { + refMsgID = StringUtil.chunkString(refMsgID, 200); + } + } + } // 업무데이터 로깅을 할 경우에만 END loggingBizData + + EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, message.getMsgRcvTm()); + + try { + // 1/1000초로 변경 + String msgPssTm = DatetimeUtil.getCurrentTime(message.getMsgPssTm()); + + String serverName = EAIServerManager.getInstance().getLocalServerName(); + String serverGroupName = EAIServerManager.getInstance().getServerType(); + + // EAI 업무 공통부(100 bytes) + EAILogId eaiLogId = new EAILogId(); + eaiLog.setId(eaiLogId); + + // EAI업무구분코드 + eaiLogId.setEaibzwkdstcd(message.getBwkCls()); + // 메시지수신시각 + eaiLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm())); + // EAI서비스일련번호 + eaiLogId.setEaisvcserno(message.getSvcOgNo()); + // 로그처리일련번호 + eaiLogId.setLogprcssserno(String.valueOf(orglogPssSno)); + // EAI서버인스탄스명 + eaiLog.setEaisevrinstncname(serverName); + + // EAI서비스명 + eaiLog.setEaisvcname(message.getEAISvcCd()); + // 서비스시각유무 + eaiLog.setSvchmseonot(message.getSvcTmEn()); + // 서비스동기사용구분코드 + eaiLog.setSvcmotivusedstcd(message.getSvcTsmtUsgTp()); + // 서비스처리구분명 + eaiLog.setSvcprcssdsticname(message.getSvcPssTp()); + // 흐름통제라우팅명 + eaiLog.setFlowctrlroutname(message.getFlwCntlRtnNm()); + + // 통합구분명 + eaiLog.setIntgradsticname(message.getUnifTp()); + // 기동서비스구분명 + eaiLog.setGstatsvcdsticname(message.getSngSvcCls()); + // 서비스처리번호 + eaiLog.setSvcprcssno(String.valueOf(message.getSvcPssSeq())); + // 서비스전컬럼로그여부 + eaiLog.setSvcbfclmnlogyn(message.getSvcWlColLogYn()); + // 표준메시지사용여부 + eaiLog.setStndmsguseyn(message.getStdMsgUsgCls()); + + // 기동시스템어댑터업무그룹명 + eaiLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp()); + // 현재메시지ID명 + eaiLog.setPrsntmsgidname(message.getLydMsgID()); + // 응답에러코드명 + eaiLog.setRspnserrcdname(message.getRspErrCd()); + // 메시지처리시각 + eaiLog.setMsgprcssyms(msgPssTm); + // 서버로그레벨번호 + eaiLog.setSevrloglvelno(String.valueOf(message.getSvrLogLvl())); + + // 서비스로그레벨번호 + eaiLog.setSvcloglvelno(String.valueOf(message.getSvcLogLvl())); + // 오류EAI서비스명 + eaiLog.setErreaisvcname(message.getErrEAISvcName()); + // 요청오류변환ID명 + eaiLog.setDmnderrchngidname(message.getDmndErrChngIDName()); + // 요청에러필드명 + eaiLog.setDmnderrfldname(message.getDmndErrFldName()); + // 응답오류변환ID명 + eaiLog.setRspnserrchngidname(message.getRspnsErrChngIDName()); + + // 응답에러필드명 + eaiLog.setRspnserrfldname(message.getRspnsErrFldName()); + // 수동인터페이스구분명 + eaiLog.setPsvintfacdsticname(svcMsg.getPsvItfTp()); + // 수동업무시스템명 + eaiLog.setPsvbzwksysname(svcMsg.getPsvBwkSysNm()); + // 수동시스템ID명 + eaiLog.setPsvsysidname(svcMsg.getPsvSysID()); + // 수동시스템서비스구분명 + eaiLog.setPsvsyssvcdsticname(svcMsg.getPsvSysSvcCd()); + + // 수동시스템어댑터업무그룹명 + eaiLog.setPsvsysadptrbzwkgroupname(svcMsg.getPsvSysItfTp()); + // 장애극복여부 + eaiLog.setFlovryn(svcMsg.getFlOvrCls()); + // 변환여부 + eaiLog.setChngyn(svcMsg.getCnvEn()); + // 변환메시지ID명 + eaiLog.setChngmsgidname(svcMsg.getCnvMsgID()); + // 입력메시지ID명 + eaiLog.setInptmsgidname(refMsgID); + + // 기본응답메시지비교내용 + eaiLog.setBascrspnsmsgcmprctnt(svcMsg.getBsRspMsgCprVl()); + // 기본응답변환여부 + eaiLog.setBascrspnschngyn(svcMsg.getBsRspCnvEn()); + // 기본응답변환메시지ID명 + eaiLog.setBascrspnschngmsgidname(svcMsg.getBsRspCnvMsgID()); + // 오류응답메시지비교내용 + eaiLog.setErrrspnsmsgcmprctnt(svcMsg.getErrRspMsgCprVl()); + // 오류응답변환여부 + eaiLog.setErrrspnschngyn(svcMsg.getErrRspCnvEn()); + + // 오류응답변환메시지ID명 + eaiLog.setErrrspnschngmsgidname(svcMsg.getErrRspCnvMsgID()); + // 다음서비스처리번호 + eaiLog.setNextsvcprcssno(String.valueOf(svcMsg.getNxtSvcPssSeq())); + // 아웃바운드라우팅명 + eaiLog.setOutbndroutname(svcMsg.getOutbRtnNm()); + // 타임아웃값 + eaiLog.setToutval(svcMsg.getTmoVl()); + // 보상서비스처리명 + eaiLog.setCmpensvcprcssname(svcMsg.getCpnsSvcPssCd()); + // 추가업무데이터여부 + eaiLog.setSupplbzwkdatayn(apndBwkDataYn); + // 키관리메시지내용 + eaiLog.setKeymgtmsgctnt(svcMsg.getKeyMgtMsgVl()); + + // SS,SA - Send - 100 + // AA - Send - 100 + // AA - Recv - 100, 300 + // AS - 100 + String telgmDmndDstcd = message.getMapper().getSendRecvDivision(message.getStandardMessage()); + if (prop != null && ((EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && logPssSno == 100) + || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp) + && STDMessageKeys.SEND_RECV_CD_RECV.equals(telgmDmndDstcd) + && (logPssSno == 100 || logPssSno == 300)) + || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp) + && STDMessageKeys.SEND_RECV_CD_SEND.equals(telgmDmndDstcd) && logPssSno == 100) + || (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.SYNC_SVC.equals(psvItfTp) + && logPssSno == 100))) { + eaiLog.setTrackasiskey1ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY1)); // 추적보조키1내용 + eaiLog.setTrackasiskey2ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY2)); // 추적보조키2내용 + eaiLog.setTrackasiskey3ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY3)); // 추적보조키3내용 + eaiLog.setTrackasiskey4ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY4)); // 추적보조키4내용 + } + + // EAI서비스코드의 그룹회사코드 + eaiLog.setEaigroupcodstcd(message.getGroupCoCd()); + // PGUID + eaiLog.setPguid(message.getMapper().getOrgGuid(message.getStandardMessage())); + // 송수신구분 + eaiLog.setTrantype(message.getTranType()); + // + eaiLog.setRspnschngmsgtype(message.getRspnsChngMsgType()); + + // log level 'E' or 'F' + if ("E".equals(message.getRspErrCd().substring(1, 2)) + || "F".equals(message.getRspErrCd().substring(1, 2))) { + // EAI에러코드 + eaiLog.setEaierrcd(message.getRspErrCd()); + // EAI에러내용 + eaiLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 1000)); + } + + // 서버그룹명 + eaiLog.setSevrgroupname(serverGroupName); + // 업체코드 + eaiLog.setCompanycode(message.getCompanyCode()); + // 전문크기, add 20190404 + eaiLog.setSplizlength(message.getSplizLength()); + // index 60 + // add 20190404 // adapterNickName + eaiLog.setAdptrinsticode(message.getAdptrInstiCode()); + + // 거래ID + eaiLog.setTxid(message.getTxId()); + // 참조ID + eaiLog.setRefkey(message.getRefKey()); + // 대외업무구분코드 + eaiLog.setExtbizcd(message.getExtBizCd()); + // EAI 업무 개별부(32,000bytes) + if (bwkData == null || bwkData.equals("")) + bwkData = " "; + eaiLog.setBzwkdatactnt(bwkData); + String standardLayoutName = System.getProperty("STANDARD_LAYOUT_NAME"); + // 표준전문레이아웃 명 + eaiLog.setStdlayoutname(standardLayoutName); + + // clientId 로그에 추가 + String clientId = message.getClientId(); + eaiLog.setClientid(clientId); + + // client IP 로그에 추가 + String clientIp = message.getClientIp(); + eaiLog.setClientip(clientIp); + + /** + * CLIENT ID 있을 경우 APP, 기관정보 로그에 추가 + * TODO: ClientVO의 경우 spring security oauth의 ClientDetails를 상속받고 있어 OAUTH가 아닌 인증의 경우에 대한 처리 추가 필요 + */ + if(StringUtils.isNotBlank(clientId)) { + ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId); + if (clientVO != null) { + eaiLog.setClientname(clientVO.getClientName()); + eaiLog.setOrgid(clientVO.getOrgId()); + eaiLog.setOrgname(clientVO.getOrgName()); + } + } + + eaiLogEntityService.save(eaiLog); + + } catch (Exception e) { + logger.error( + "DB Logging[MASTER] Failed - " + message.getEAISvcCd() + "|" + orglogPssSno + "|" + + message.getSvcOgNo() + "|" + message.getMapper().getGuid(message.getStandardMessage()), + e); + + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG001")); + } + + // 에러로그를 별도의 테이블에 저장하도록 한다. + if (!MessageUtil.checkRspErrCd(message.getRspErrCd())) { + try { + // 거래통제, 유량제어에 의한 에러는 저장하지 않도록 한다. + if (!(EAIMessageKeys.EAI_BLOCKED_CODE.equals(message.getRspErrCd()) + || EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE.equals(message.getRspErrCd()))) { + addErrorLog(message); // 에러로그 + } + } catch (Exception ex) { + logger.warn("에러로그테이블 저장 SKIP 에러발생 - " + ex.getMessage()); + } + } + + } + + public void addErrorLog(EAIMessage message) throws DAOException { + try { + String serverName = EAIServerManager.getInstance().getLocalServerName(); + + EAIErrorLog eaiErrorLog = (EAIErrorLog) applicationContext.getBean(RollingTable.class, EAIErrorLog.class, + message.getMsgRcvTm()); + + // EAI업무구분코드 + EAIErrorLogId eaiErrorLogId = new EAIErrorLogId(); + eaiErrorLog.setId(eaiErrorLogId); + + eaiErrorLogId.setEaibzwkdstcd(message.getBwkCls()); + // 메시지수신시각 + eaiErrorLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm())); + // EAI거래일련번호 + eaiErrorLogId.setEaisvcserno(message.getSvcOgNo()); + // 로그처리일련번호 + eaiErrorLogId.setLogprcssserno(String.valueOf(message.getLogPssSno())); + + // EAI서비스명 + eaiErrorLog.setEaisvcname(message.getEAISvcCd()); + // 응답에러코드명 + eaiErrorLog.setRspnserrcdname(message.getRspErrCd()); + // 기동시스템어댑터업무그룹명 + eaiErrorLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp()); + // 수동시스템어댑터업무그룹명 + eaiErrorLog.setPsvsysadptrbzwkgroupname(message.getCurrentSvcMsg().getPsvSysItfTp()); + + if ("E".equals(message.getRspErrCd().substring(1, 2)) + || "F".equals(message.getRspErrCd().substring(1, 2))) { + // EAI에러코드 + eaiErrorLog.setEaierrcd(message.getRspErrCd()); + // EAI에러내용 + eaiErrorLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 500)); + } + + // EAI서버인스턴스명 + eaiErrorLog.setEaisevrinstncname(serverName); + // 로깅시스템ID + EAIServerVO eaiServerVO = EAIServerManager.getInstance().getEAIServer(serverName); + if(eaiServerVO != null) { + eaiErrorLog.setLgingsysid(eaiServerVO.getHostName()); + } + // 메시지처리일시 + eaiErrorLog.setMsgprcssyms(DatetimeUtil.getCurrentTime(message.getMsgPssTm())); + // EAI그룹회사코드 + eaiErrorLog.setEaigroupcodstcd(message.getGroupCoCd()); + + } catch (Exception e) { + logger.error("DB Logging[ERROR_LOG] Failed - " + message.getEAISvcCd() + "|" + message.getLogPssSno() + "|" + + message.getSvcOgNo(), e); + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); + } + } + + public void addStaticLog(StatMonitorLogVO vo) throws DAOException { + try { + StatLog statLog = statLogMapper.toEntity(vo); + statLogLogger.save(statLog); + } catch (Exception e) { + logger.error("DB Logging[STATIC_LOG] Failed - " + vo.toString(), e); + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); + } + } + + public void addStaticTranCdLog(StatMonitorLogVO vo) throws DAOException { + try { + StatTranLog statTranLog = statTranLogMapper.toEntity(vo); + statTranLogLogger.save(statTranLog); + } catch (Exception e) { + logger.error("DB Logging[STATIC_TRANCD_LOG] Failed - " + vo.toString(), e); + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); + } + } + + public void addStaticAdapterLog(StatMonitorLogVO vo) throws DAOException { + try { + StatAdapterLog statAdapterLog = statAdapterLogMapper.toEntity(vo); + statAdapterLogLogger.save(statAdapterLog); + } catch (Exception e) { + logger.error("DB Logging[STATIC_ADAPTER_LOG] Failed - " + vo.toString(), e); + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003")); + } + } + + public boolean getCheck() throws DAOException { + return eaiServerEntityService.checkConnection(); + } + + private boolean checkSubLogging(String svcTsmtUsgTp, String psvItfTp, String srcAdptrMsgPtrnCd, String tgtAdptrMsgPtrnCd, int logPssSno) { + boolean isAsyncSvc = EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp); + boolean isSrcStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(srcAdptrMsgPtrnCd); + +// // SOURCE : AA : 100, 300, ELSE: 100, 400 + if(isSrcStandard && ( (isAsyncSvc && (logPssSno == 100 || logPssSno == 300)) || + (!isAsyncSvc && (logPssSno == 100 || logPssSno == 400)) ) ) { + return true; + } + + boolean isTgtStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(tgtAdptrMsgPtrnCd); +// // TARGET : AA : 200, 400, ELSE : 200, 300 + if (isTgtStandard && ( (isAsyncSvc && (logPssSno == 200 || logPssSno == 400)) || + (!isAsyncSvc && (logPssSno == 200 || logPssSno == 300)) ) ) { + return true; + } + return false; + } + + + private String EncryptSafeDb(String attribute) { + String originalAttribute = attribute; + if (StringUtils.isNotEmpty(attribute)) { + KjbSafedbWrapper wrapper = KjbSafedbWrapper.getInstance(); + attribute = wrapper.encryptNotRnnoString(attribute); + + if (logger.isInfo()) { + // originalAttribute 홀수 글자 마스킹 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < originalAttribute.length(); i++) { + if (i % 2 == 0) { + sb.append(originalAttribute.charAt(i)); + } else { + sb.append("*"); + } + } + + originalAttribute = sb.toString(); + System.out.println("DB 암호화 #2 : {"+ originalAttribute +"} -> {"+attribute+"}"); + //logger.debug("DB 암호화 #2 : {} -> {}", originalAttribute, attribute); + } + } + return attribute; + + } + + public String DecryptSafeDb(String dbData) { + + String dbDataOriginal = dbData; + if (StringUtils.isNotEmpty(dbData)) { + if (this.isEncrypted(dbData)) { + KjbSafedbWrapper safeDBWrapper = KjbSafedbWrapper.getInstance(); + try { + dbData = safeDBWrapper.decryptNotRnno(dbData); + } catch (Exception e) { + // 복호화 실패시 원본 반환 + String logData = dbData.length() <= 3 ? dbData : dbData.substring(0, 3) + "..."; + logger.warn("DB 복호화 실패: 복호화하지 않고 원본 반환. dbData={} (Length : {})", logData, dbData.length()); + return dbData; + } + } else { + logger.debug("DB 복호화 경고: Base64 형식이 아님. 복호화하지 않고 원본 반환. dbData={}", dbData); + } + } + + //logger.debug("DB 복호화 #2 : {} -> {}", dbDataOriginal, dbData); + + return dbData; + } + + /** + * 암호화 여부 확인(base64 인코딩 여부로 판단, 또는 0-9, - 로 구성된 경우 암호화 되지 않은 걸로 판단(연락처)) + * @param data + * @return + */ + private boolean isEncrypted(String data) { + if (StringUtils.isEmpty(data)) { + return false; + } + + // 숫자, - 로만 구성된 경우 암호화 되지 않은 걸로 판단 (ex: 연락처) + if (data.matches("^[0-9-]+$")) { + return false; + } + + data = data.trim(); + + // Base64 형식 체크 + if (!Utils.isBase64(data)) { + return false; + } + + // Base64 길이 체크 (4의 배수) + if (data.length() % 4 != 0) { + return false; + } + + + return true; + } + + + /* + private String EncryptSafeDb(String msg) { + PropManager propManager = PropManager.getInstance(); + String safeDbPath = propManager.getProperty("SafeDB","safedb.path"); + + SimpleSafeDB safedb = SimpleSafeDB.getInstance(); + boolean loginResult = false; + if(!safedb.login()) { + loginResult = safedb.getSafeDBConfigMgr().isLoginCheck(); + } + + String userName = "SAFEDB"; + String tableName = "SAFEDB.POLICY"; + String columnName1 = "bzwkdatactnt"; + + byte[] byteMsg = msg.getBytes(StandardCharsets.UTF_8); + byte[] encryptedBytes1 = null; + + try { + encryptedBytes1 = safedb.encrypt(userName, tableName, columnName1, byteMsg); + System.out.println("Encrypted Data : [" + new String(encryptedBytes1) + "]"); + + byte[] decryptedBytes1 = safedb.decrypt(userName, tableName, columnName1, encryptedBytes1); + + } catch (SafeDBSDKException e) { + e.printStackTrace(); + + } + + String encryptedMsg = new String(encryptedBytes1, StandardCharsets.UTF_8); + return encryptedMsg; + } + */ + +} diff --git a/src/main/java/com/eactive/eai/common/util/JMSSender.java b/src/main/java/com/eactive/eai/common/util/JMSSender.java index c775498..73b15d6 100644 --- a/src/main/java/com/eactive/eai/common/util/JMSSender.java +++ b/src/main/java/com/eactive/eai/common/util/JMSSender.java @@ -1,5 +1,5 @@ package com.eactive.eai.common.util; - + import java.util.Iterator; import java.util.Properties; @@ -69,6 +69,7 @@ public class JMSSender { throw new Exception("qconFactory not found -" + connectionFactory); queue = locator.getQueue(destination); + logger.info("resolved quene name is:" + "["+ queue + "]"); qsender = qsession.createSender(queue); ObjectMessage msg = qsession.createObjectMessage(); diff --git a/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java b/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java index 0aba908..0e814c3 100644 --- a/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java +++ b/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java @@ -58,7 +58,7 @@ import org.json.simple.JSONObject; import java.util.HashMap; import java.util.Map; //import org.apache.commons.lang3.StringUtils; -//import org.springframework.http.HttpStatus; +//import org.springframework.http.HttpStatus; //import java.util.Calendar; //import java.util.Properties; diff --git a/src/main/java/com/eactive/eai/outbound/RESTProcess.java b/src/main/java/com/eactive/eai/outbound/RESTProcess.java index 1b2eb51..9d739f6 100644 --- a/src/main/java/com/eactive/eai/outbound/RESTProcess.java +++ b/src/main/java/com/eactive/eai/outbound/RESTProcess.java @@ -1,5 +1,5 @@ package com.eactive.eai.outbound; - + import java.net.SocketTimeoutException; import java.util.Properties; @@ -439,6 +439,7 @@ public class RESTProcess extends HTTPProcess { PropertiesUtil.copyPropertyIfPresent(this.callProp, this.tempProp, HttpAdapterServiceKey.INBOUND_PATH_VARIABLES); PropertiesUtil.copyPropertyIfPresent(this.callProp, this.tempProp, HttpAdapterServiceKey.INBOUND_REMOTE_ADDR); PropertiesUtil.copyPropertyIfPresent(this.callProp, this.tempProp, HttpAdapterServiceKey.INBOUND_SCHEME); + PropertiesUtil.copyPropertyIfPresent(this.callProp, this.tempProp, HttpAdapterServiceKey.INBOUND_REQUESTED_TIME); // jwhong String svcName = getServiceId(this.reqEaiMsg); if (svcName == null) {