Merge branch 'jenkins_with_weblogic' of ssh://git@192.168.240.178:18081/eapim/eapim-online.git into jenkins_with_weblogic
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# 레이아웃 조건부 처리 (RefValue)
|
||||
|
||||
FlatReader에서 GROUP/GRID 항목의 조건부 처리를 위한 RefValue 설정 방법
|
||||
|
||||
## 지원 조건
|
||||
|
||||
| 표현식 | 의미 | 설명 |
|
||||
|--------|------|------|
|
||||
| `NM` | EQUALS | 값이 NM과 일치하는 경우 |
|
||||
| `NM\|EM` | OR | 값이 NM 또는 EM과 일치하는 경우 |
|
||||
| `!EM` | NOT | 값이 EM이 아닌 경우 |
|
||||
| `!NM\|EM` | NOT OR | 값이 NM도 아니고 EM도 아닌 경우 |
|
||||
|
||||
## 레이아웃 설정 예시
|
||||
|
||||
| 항목명 | 설명 | Depth | Type | Node | OccMin | Length | OccMax | RefPath | RefValue |
|
||||
|--------|------|-------|------|------|--------|--------|--------|---------|----------|
|
||||
| Message | 메시지부 | 1 | 3 | 0 | 1 | 0 | 1 | Message.Msg_Header.MSG_HEDR_KNCD | NM\|EM |
|
||||
| Msg_Header | 메시지헤더 | 2 | 3 | 0 | 1 | 0 | 1 | | |
|
||||
| MSG_HEDR_KNCD | 메시지헤더종류코드 | 3 | 2 | 1 | 1 | 2 | 1 | | NM |
|
||||
|
||||
## 동작 설명
|
||||
|
||||
위 예시에서 `Message` 항목은 `MSG_HEDR_KNCD` 값이 `NM` 또는 `EM`일 때만 처리됩니다.
|
||||
|
||||
- `MSG_HEDR_KNCD = "NM"` → Message 처리됨
|
||||
- `MSG_HEDR_KNCD = "EM"` → Message 처리됨
|
||||
- `MSG_HEDR_KNCD = "XX"` → Message 스킵됨
|
||||
|
||||
## 변경 파일
|
||||
|
||||
- `elink-online-common/src/main/java/com/eactive/eai/message/parser/FlatReader.java`
|
||||
@@ -138,11 +138,12 @@ public class ApiAdapterController implements HttpAdapterServiceKey {
|
||||
// if (RESPONSE_TYPE_ASYNC.equals(responseType)) { // table의 값이 ASYNC 로 들어가 있는데 response_type_async는 ASYN 로 되어 있어 아래처럼 비교함 jwhong 2025
|
||||
if ("ASYNC".equals(responseType)) {
|
||||
//responseEntity = ResponseEntity.ok("dummy"); // comment by jwhong
|
||||
servletResponse.addHeader("traceId", responseData); // uuid를 response header에
|
||||
//servletResponse.addHeader("traceId", responseData); // uuid를 response header에
|
||||
servletResponse.addHeader("traceId", transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID)); // uuid를 response header에
|
||||
int httpStatus = servletResponse.getStatus();
|
||||
if (httpStatus == 200) {
|
||||
// 업체별 aync response message 가 다르다.
|
||||
String asyncMsgStyle = httpProp.getProperty("ASYNC_RTNMSG_TYPE", "").toUpperCase();
|
||||
String asyncMsgStyle = httpProp.getProperty("ASYNC_RTNMSG_TYPE", "");
|
||||
String responseBody ="";
|
||||
if (asyncMsgStyle == null || asyncMsgStyle.trim().isEmpty()) {
|
||||
responseBody = makeResponseBodyMsg();
|
||||
@@ -158,6 +159,8 @@ public class ApiAdapterController implements HttpAdapterServiceKey {
|
||||
// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
|
||||
// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정
|
||||
// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24
|
||||
|
||||
servletResponse.addHeader("traceId", transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID)); // uuid를 response header에
|
||||
int httpStatus = servletResponse.getStatus();
|
||||
if (httpStatus != 200) {
|
||||
responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
|
||||
|
||||
@@ -1,85 +1,150 @@
|
||||
package com.eactive.eai.adapter.controller;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import com.eactive.eai.adapter.AdapterGroupVO;
|
||||
import com.eactive.eai.adapter.AdapterManager;
|
||||
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
|
||||
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri;
|
||||
import com.eactive.eai.common.stdmessage.STDMessageManager;
|
||||
import com.eactive.eai.common.stdmessage.STDMsgInfoAddOnVO;
|
||||
|
||||
|
||||
public class ApiRequestBodyFilter extends OncePerRequestFilter {
|
||||
|
||||
static final String KJB_ROOTLESS_ARRAY = "{ \"KJB_ROOTLESS_ARRAY\" : ";
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
|
||||
// 1. 필터 대상
|
||||
|
||||
String encoding = getInboundGroupAdapterEncoding(request);
|
||||
|
||||
if (!isTarget(request)) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 요청 전문 읽기
|
||||
String body = readBody(request);
|
||||
if (body == null || body.isEmpty()) {
|
||||
//원본 바디를 byte[]로 읽기 (개행 포함 그대로) 왜? 뒤에 필터에서 HMAC값 계산할수도 있어서 변조되면 안됨. 개행문자도 그대로 가야함.
|
||||
byte[] rawBody = readBodyAsBytes(request);
|
||||
|
||||
if (rawBody == null || rawBody.length == 0) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String modifiedBody = body;
|
||||
byte[] finalBody = rawBody;
|
||||
|
||||
try {
|
||||
Object json = JSONValue.parse(body);
|
||||
|
||||
// 3. 예제: ROOTLESS ARRAY 보정
|
||||
String bodyStr = new String(rawBody, encoding);
|
||||
Object json = JSONValue.parse(bodyStr);
|
||||
|
||||
if (json instanceof JSONArray) {
|
||||
JSONObject wrap = new JSONObject();
|
||||
wrap.put("KJB_ROOTLESS_ARRAY", json);
|
||||
modifiedBody = wrap.toJSONString();
|
||||
bodyStr = KJB_ROOTLESS_ARRAY + bodyStr + "}";
|
||||
finalBody = bodyStr.getBytes(encoding);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// 변조 실패 → 원본 유지
|
||||
modifiedBody = body;
|
||||
// JSON 파싱 실패 시 원본 유지
|
||||
finalBody = rawBody;
|
||||
}
|
||||
|
||||
byte[] bytes = modifiedBody.getBytes(request.getCharacterEncoding() != null ? request.getCharacterEncoding() : Charset.defaultCharset().name() );
|
||||
|
||||
// 5. Wrapper로 재주입
|
||||
// Wrapper로 재주입
|
||||
HttpServletRequest wrapped =
|
||||
new CachedBodyHttpServletRequest(request, bytes);
|
||||
new CachedBodyHttpServletRequest(request, finalBody);
|
||||
|
||||
filterChain.doFilter(wrapped, response);
|
||||
}
|
||||
|
||||
private boolean isTarget(HttpServletRequest request) {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
|
||||
return ("POST".equals(request.getMethod()) || "PUT".equals(request.getMethod()))
|
||||
&& (uri.startsWith("/api") || uri.startsWith("/mapi") ) && !uri.startsWith("/mapi/oauth2/token");
|
||||
&& (uri.startsWith("/api") || uri.startsWith("/mapi"))
|
||||
&& !uri.startsWith("/mapi/oauth2/token");
|
||||
}
|
||||
|
||||
private String readBody(HttpServletRequest request) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader br = request.getReader()) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
|
||||
private byte[] readBodyAsBytes(HttpServletRequest request) throws IOException {
|
||||
try (ServletInputStream is = request.getInputStream();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int len;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, len);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
private String getInboundGroupAdapterEncoding(HttpServletRequest request) {
|
||||
String apiUri = request.getRequestURI();
|
||||
apiUri = StringUtils.removeStart(apiUri, request.getContextPath());
|
||||
apiUri = StringUtils.removeEnd(apiUri, "/");
|
||||
|
||||
String methodAndUri = request.getMethod() + "|" + apiUri;
|
||||
String adapterGrpName;
|
||||
HttpDynamicInAdapterUri adptUri = null;
|
||||
|
||||
try {
|
||||
STDMessageManager manager = STDMessageManager.getInstance();
|
||||
STDMsgInfoAddOnVO stdMsgInfo = manager.getStdMsgInfoAddOn(methodAndUri);
|
||||
adapterGrpName = stdMsgInfo.gAdapterGroupName();
|
||||
|
||||
adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance(), adapterGrpName);
|
||||
} catch (Exception e) {
|
||||
adptUri = null;
|
||||
}
|
||||
|
||||
AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO( adptUri.getAdptGrpName());
|
||||
|
||||
if( adapterGroupVO == null ) {
|
||||
return Charset.defaultCharset().name();
|
||||
}
|
||||
|
||||
return StringUtils.isNotBlank(adapterGroupVO.getMessageEncode()) ? adapterGroupVO.getMessageEncode() : Charset.defaultCharset().name(); //서버 jvm file.encoding 확인, file.encoding=utf-8 주고있음.
|
||||
|
||||
}
|
||||
|
||||
private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager, String adapterGrpName) throws Exception {
|
||||
if (StringUtils.isBlank(apiUri)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri);
|
||||
if (adptUri != null) {
|
||||
if (adptUri.getAdptGrpName().equals(adapterGrpName)) {
|
||||
return adptUri;
|
||||
}
|
||||
}
|
||||
|
||||
apiUri = StringUtils.substringBeforeLast(apiUri, "/");
|
||||
if (apiUri.length() < 4) { // /api
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
static final String KJB_ROOTLESS_ARRAY = "{ \"KJB_ROOTLESS_ARRAY\" : ";
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
@@ -34,6 +36,7 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
}
|
||||
|
||||
String removeRootlessArrayKeyFormResponseBody(String body) {
|
||||
|
||||
try {
|
||||
Object root = JSONValue.parse(body);
|
||||
|
||||
|
||||
@@ -239,8 +239,12 @@ public class ApiAdapterService extends HttpAdapterServiceSupport {
|
||||
|
||||
if (paramValue == null) { // parameter가 없는 경우때문에 처리
|
||||
paramValue = "";
|
||||
}
|
||||
else { // jwhong decrypt
|
||||
}
|
||||
// 순수한 Body값을 저장을 위해 위치 변경.
|
||||
transactionProp.put(INBOUND_REQUEST_MESSAGE, paramValue);
|
||||
|
||||
// paramValue가 null이 아닌 빈문자열(""," ")인 경우에 대비하여 조건 수정.
|
||||
if (StringUtils.isNotBlank(paramValue)) { // jwhong decrypt
|
||||
paramValue = doPreDecryption(paramValue, transactionProp, request);
|
||||
}
|
||||
|
||||
@@ -296,7 +300,8 @@ public class ApiAdapterService extends HttpAdapterServiceSupport {
|
||||
message = "";
|
||||
}
|
||||
|
||||
transactionProp.put(INBOUND_REQUEST_MESSAGE, message);
|
||||
// 위치변경 : 가공되지 않은 Body값을 저장하기 위하여 위쪽으로 이동.
|
||||
// transactionProp.put(INBOUND_REQUEST_MESSAGE, message);
|
||||
// 로컬 서비스 호출 ,encoding 처리 추가
|
||||
String result = (String) service(adptGrpName, adptName, message, transactionProp, request, response);
|
||||
|
||||
|
||||
+8
@@ -14,6 +14,7 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS
|
||||
|
||||
public static final String X_TRACE_ID = "partnerTraceId";
|
||||
public static final String TRACE_ID = "traceId";
|
||||
|
||||
|
||||
@Override
|
||||
public Object doPreFilter(String adptGrpName, String adptName, Properties prop, Object message, Properties tempProp)
|
||||
@@ -21,6 +22,7 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS
|
||||
|
||||
logger.debug("AsyncReponseFilter] PreFilter Processing Start!!");
|
||||
String traceId = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID, "");
|
||||
String xloanToken = tempProp.getProperty(TransactionContextKeys.X_LOAN_TOKEN, "");
|
||||
|
||||
Properties filterHeaders = (Properties) tempProp.get("FILTERHEADER");
|
||||
if (filterHeaders == null) {
|
||||
@@ -35,7 +37,13 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS
|
||||
filterHeaders.put(X_TRACE_ID, inboundHeaderMap.get(X_TRACE_ID));
|
||||
logger.debug("AsyncReponseFilter] Processing Key ["+X_TRACE_ID+"], value ["+inboundHeaderMap.get(X_TRACE_ID)+"]");
|
||||
}
|
||||
|
||||
if (inboundHeaderMap.containsKey(TransactionContextKeys.X_LOAN_TOKEN)||inboundHeaderMap.containsKey(TransactionContextKeys.X_LOAN_TOKEN.toLowerCase())) {
|
||||
filterHeaders.put(TransactionContextKeys.X_LOAN_TOKEN, inboundHeaderMap.get(TransactionContextKeys.X_LOAN_TOKEN));
|
||||
logger.debug("AsyncReponseFilter] Processing Key ["+TransactionContextKeys.X_LOAN_TOKEN+"], value ["+inboundHeaderMap.get(TransactionContextKeys.X_LOAN_TOKEN)+"]");
|
||||
}
|
||||
}
|
||||
|
||||
filterHeaders.setProperty(TRACE_ID, traceId);
|
||||
logger.debug("AsyncReponseFilter] Processing Key ["+TRACE_ID+"], value ["+traceId+"]");
|
||||
|
||||
|
||||
+3
@@ -24,6 +24,9 @@ public class HttpClient5AdapterFilterFactory {
|
||||
case SIMPLEFRAMEWORK:
|
||||
filter = new SimpleFrameworkFilter();
|
||||
break;
|
||||
case SIMPLEFRAMEWORKBODY:
|
||||
filter = new SimpleframeworkBodyFilter();
|
||||
break;
|
||||
case JBOBP:
|
||||
filter = new JBOBPFilter();
|
||||
break;
|
||||
|
||||
+1
@@ -2,6 +2,7 @@ package com.eactive.eai.custom.kjb.adapter.http.client.filter;
|
||||
|
||||
public enum HttpClient5AdapterFilterType {
|
||||
SIMPLEFRAMEWORK,
|
||||
SIMPLEFRAMEWORKBODY,
|
||||
JBOBP,
|
||||
KFTCFACE,
|
||||
KFTCP2P,
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.eactive.eai.custom.kjb.adapter.http.client.filter;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import com.eactive.eai.common.TransactionContextKeys;
|
||||
|
||||
public class SimpleframeworkBodyFilter extends SimpleFrameworkFilter {
|
||||
@Override
|
||||
public Object doPreFilter(String adptGrpName, String adptName, Properties prop, Object message, Properties tempProp)
|
||||
throws Exception {
|
||||
|
||||
Object returnMessage = super.doPreFilter(adptGrpName, adptName, prop, message, tempProp);
|
||||
|
||||
JSONObject bizJsonStr = null;
|
||||
|
||||
if ( returnMessage instanceof String ) {
|
||||
bizJsonStr = (JSONObject) JSONValue.parse( (String)returnMessage);
|
||||
bizJsonStr.put("GUID", tempProp.get(TransactionContextKeys.GUID));
|
||||
}
|
||||
|
||||
return bizJsonStr != null ? bizJsonStr.toJSONString() : returnMessage;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzY3zugQeOrTkol2fHIhD
|
||||
/S8FqvNX6ijrU7v8wEnaIYVG1ay6ehAmlg6dc7J0Bvf1Ed5EvbDEI+4sa8n6egWa
|
||||
zHSL4GXQXj9QFZGvRRah6nPhYiAvbLqHPwvG4QreIwx1Yt4tx63m8gFid6QjEsZP
|
||||
DbWeX6bXW1scR+qtztkq2CGvOHlej5JHsdP350hH3Hq2sxdmTHurVwFJdfzBwDkU
|
||||
MJlLwIEkkbACK1hrQhrEf1uKX8HtxrozSS8sso4wFrOPe8u/ykqYmSPlSfUsPvNr
|
||||
cK/VroyX63RAE+giH84Y8mSHLr+mfEG3AhdJ1+ZqB9jBunTZDiGKn00mT4jJLwgr
|
||||
BwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhXoqB4PrgZpJISjBe9ht
|
||||
Y1R3Ne9ehxugWucwA4cBWAnYwvmrRAK0p8p+HuDikdZPq2hyAG02ucNt9xoru+Va
|
||||
K4spNGieORbh0hmLRdvVBBM7Ureia3WhKED5abNnnPQw+jCLZNVYtO9rbtRhpUEG
|
||||
t73sN1+0bOZlVBkbLenvWKJs2+tyE0gHhwgS8Fzrb++LHYN/c0KoTm+G9ITuPWoM
|
||||
Vu/iME5WHqR95TkLKpx6s5J/le4BvncQDmkvKFIX9/DFN57orXQVB2lzDF8fMeWC
|
||||
xaaHXtgfo2ercKKEdHQ5GFIgWN8+j2ZgU2JqfucazJpOpOGcizHiQKzh//NE7beD
|
||||
IwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8M6NO6KfKRTwwOfZ/slx
|
||||
fT/4vPzr1zXvgTHoVq/dyoCk8OeVS0OOJXln7ZqDPkKSlfd1X1fdDaEOfLJXfvPC
|
||||
Hz7AOTBdr1/Y+Ro4slflO8d9/HbNkUZQTsbS/JqnpD20isP+sSJXHVOq5zEa4bbC
|
||||
tGcpDIwoOIWqoCAA++jUSKhMZEiag5hWKUBi3wpLLjHiKtk9NZxvfCJO6GMJpN1c
|
||||
O37cnudSan+oDGn3Twb579pK+gG3UZejQABhrqkv63MhMLrl74tXbHL9HX9shJjQ
|
||||
zq8SQn2k/RbwLVE+USuDmN8BZkVmtQZRirr3d8yT+BlpgodeqMX8PYcztV+4VTvl
|
||||
swIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCW0auFk5bqt7OZ2AtFw
|
||||
xa/se93/hgNwDNC1kxKZpnvNM5YVj5gjlf0jOSVGNJlFTVvjIBcyPC7s1zlFDhgm
|
||||
ebUKplRuw82lkIkS7mPjsqfPvMQlFjjLgrnECQ3AD86EkRcUT/bVliOtwLY6YJUa
|
||||
5/1eqZCIRfLPVxOApSHuQLJ9JmSPhttwfKwTED3G2dB85D+QN5+Nre5nnWDjMScT
|
||||
KOcyUZHOLO6m0UupBYU94XGJG4EEMwzSE/Lq1eJ49/wUsvaKY6Kz5G30d/ANwRZI
|
||||
ex82Wp91ZPOasKKOB6vnQ/LNcMhhyYf6IzCliMUUFl53YeheXmvfWX6VLfWgjlLk
|
||||
HQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Reference in New Issue
Block a user