async response message 추가

This commit is contained in:
25W0075
2025-11-17 16:56:25 +09:00
parent 8af9e48478
commit 733efee741
2 changed files with 1051 additions and 570 deletions
@@ -1,190 +1,253 @@
package com.eactive.eai.adapter.controller; package com.eactive.eai.adapter.controller;
import java.util.Date; import java.util.Date;
import java.util.Properties; import java.util.Properties;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.eactive.eai.adapter.AdapterGroupVO; import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager; import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager; import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO; import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.http.HttpStatusException; import com.eactive.eai.adapter.http.HttpStatusException;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager; import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri; import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri;
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
import com.eactive.eai.adapter.service.ApiAdapterService; import com.eactive.eai.adapter.service.ApiAdapterService;
import com.eactive.eai.common.TransactionContextKeys; import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.exception.ExceptionUtil; import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.server.EAIServerManager; import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.DatetimeUtil; import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.InboundErrorLogger; import com.eactive.eai.common.util.InboundErrorLogger;
import com.eactive.eai.common.util.Logger; import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil; import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.common.util.UUIDGenerator; import com.eactive.eai.common.util.UUIDGenerator;
import com.eactive.eai.inbound.error.InboundErrorInfoVO; import com.eactive.eai.inbound.error.InboundErrorInfoVO;
import com.kjbank.encrypt.exchange.crypto.AES256Cipher;
@RestController import com.kjbank.encrypt.exchange.crypto.AES256GCMCipher;
public class ApiAdapterController implements HttpAdapterServiceKey { import com.kjbank.encrypt.exchange.crypto.AESCipher;
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
// jwhong
@Autowired import org.json.simple.JSONObject;
ApiAdapterService service; import java.util.HashMap;
import java.util.Map;
/** import java.sql.Timestamp;
* KBANK 요구사항으로 /api/v1/oauth/token 과 같은 형태로 토큰 발급거래를 수행해야해서 예외처리함
* @See com.eactive.eai.authserver.config.AuthorizationServerConfig.configure(AuthorizationServerEndpointsConfigurer endpoints) @RestController
*/ public class ApiAdapterController implements HttpAdapterServiceKey {
@RequestMapping(value = {"/api/*", "/api/*/{path:^(?!.*oauth).*$}/**"}) static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
// @RequestMapping(value = {"/api/**"})
public ResponseEntity<String> callApi(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception { @Autowired
// /ONLWeb/api/v1/public/getUserInfo.svc ApiAdapterService service;
String apiUri = servletRequest.getRequestURI();
// /api/v1/public/getUserInfo.svc /**
apiUri = StringUtils.removeStart(apiUri, servletRequest.getContextPath()); * KBANK 요구사항으로 /api/v1/oauth/token 과 같은 형태로 토큰 발급거래를 수행해야해서 예외처리함
apiUri = StringUtils.removeEnd(apiUri, "/"); * @See com.eactive.eai.authserver.config.AuthorizationServerConfig.configure(AuthorizationServerEndpointsConfigurer endpoints)
HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance()); */
@RequestMapping(value = {"/api/*", "/mapi/*", "/api/*/{path:^(?!.*oauth).*$}/**", "/mapi/*/{path:^(?!.*oauth).*$}/**"})
if (logger.isDebug()) { // @RequestMapping(value = {"/api/**"})
logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI()); public ResponseEntity<String> callApi(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception {
} // /ONLWeb/api/v1/public/getUserInfo.svc
String apiUri = servletRequest.getRequestURI();
if (adptUri == null) { // /api/v1/public/getUserInfo.svc
logError(servletRequest); apiUri = StringUtils.removeStart(apiUri, servletRequest.getContextPath());
// throw new Exception("can not find Adapter Uri"); apiUri = StringUtils.removeEnd(apiUri, "/");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("can not find Adapter Uri"); HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance());
}
//Received time , jwhong
long receivedTimeMillis = System.currentTimeMillis();
String adapterGroupName = adptUri.getAdptGrpName(); String receivedTimeStr = String.valueOf(receivedTimeMillis);
String adapterName = adptUri.getAdptName();
AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName); System.out.println("현재 시간 밀리초(long): " + receivedTimeMillis);
AdapterVO adapterVO = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName); System.out.println("현재 시간 밀리초(String): " + receivedTimeStr);
if (adapterVO == null) { //Timestamp timestamp = new Timestamp(System.currentTimeMillis());
// throw new Exception("Adapter not found error"); //System.out.println("현재 Timestamp: " + timestamp);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Adapter not found error");
} if (logger.isDebug()) {
logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI());
Properties httpProp = AdapterPropManager.getInstance().getProperties(adapterVO.getPropGroupName()); }
String adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); if (adptUri == null) {
String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); logError(servletRequest);
MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode); // throw new Exception("can not find Adapter Uri");
String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("can not find Adapter Uri");
}
String responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC");
ResponseEntity responseEntity = null;
Properties transactionProp = new Properties(); String adapterGroupName = adptUri.getAdptGrpName();
try { String adapterName = adptUri.getAdptName();
String responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO, transactionProp); AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
if (RESPONSE_TYPE_ASYNC.equals(responseType)) { AdapterVO adapterVO = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName);
responseEntity = ResponseEntity.ok("dummy"); if (adapterVO == null) {
} else { // throw new Exception("Adapter not found error");
// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Adapter not found error");
// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정 }
// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24
int httpStatus = servletResponse.getStatus(); Properties httpProp = AdapterPropManager.getInstance().getProperties(adapterVO.getPropGroupName());
if (httpStatus != 200) {
responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData); String adptMsgType = adapterVO.getAdapterGroupVO().getMessageType();
} else { String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8");
responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode);
} String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT);
}
} catch (HttpStatusException e) { String responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC");
logger.warn("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage()); ResponseEntity responseEntity = null;
String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), Properties transactionProp = new Properties();
e.getMessage(), errorResponseFormat); //transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeMillis); // jwhong, put api received time
responseEntity = ResponseEntity.status(e.getStatus()).contentType(mediaType).body(errorMsg); transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeStr);
} catch (JwtAuthException e) {
logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); try {
String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), String responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO, transactionProp);
e.getMessage(), errorResponseFormat); // if (RESPONSE_TYPE_ASYNC.equals(responseType)) { // table의 값이 ASYNC 로 들어가 있는데 response_type_async는 ASYN 로 되어 있어 아래처럼 비교함 jwhong 2025
responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).contentType(mediaType).body(errorMsg); if ("ASYNC".equals(responseType)) {
} catch (Exception e) { //responseEntity = ResponseEntity.ok("dummy"); // comment by jwhong
logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); servletResponse.addHeader("traceId", responseData); // uuid를 response header에
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType).body(e); int httpStatus = servletResponse.getStatus();
} finally { if (httpStatus == 200) {
/** // 업체별 aync response message 가 다르다.
* 로깅 인터셉터에 데이터를 전달하기 위한 처리 String asyncMsgStyle = httpProp.getProperty("ASYNC_RTNMSG_TYPE", "").toUpperCase();
* 이미 거래처리가 끝나서 영향도가 없을만한 servletRequest에 Attribute로 전달 String responseBody = makeResponseBodyMsg(asyncMsgStyle);
* 추후 더 좋은방법이 생길경우 개선 요망 responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseBody);
*/ // jwhong
servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp); } else {
} responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
return responseEntity; }
} } else {
// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정
// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24
/** int httpStatus = servletResponse.getStatus();
* url에서 뒤쪽 /이후를 제거하면서 찾는다.<br> if (httpStatus != 200) {
* /api/v1/public/getUserInfo.svc responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
* } else {
* @param apiUri responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
* @return }
*/ }
private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager) { } catch (HttpStatusException e) {
if (StringUtils.isBlank(apiUri)) { logger.warn("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage());
return null; String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(),
} e.getMessage(), errorResponseFormat);
responseEntity = ResponseEntity.status(e.getStatus()).contentType(mediaType).body(errorMsg);
for (int i = 0; i < 10; i++) { } catch (JwtAuthException e) {
HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
if (adptUri != null) { String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(),
return adptUri; e.getMessage(), errorResponseFormat);
} responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).contentType(mediaType).body(errorMsg);
} catch (Exception e) {
// /api/v1/public logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
apiUri = StringUtils.substringBeforeLast(apiUri, "/"); responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType).body(e);
if (apiUri.length() < 4) { // /api } finally {
return null; /**
} * 로깅 인터셉터에 데이터를 전달하기 위한 처리
} * 이미 거래처리가 끝나서 영향도가 없을만한 servletRequest에 Attribute로 전달
* 추후 더 좋은방법이 생길경우 개선 요망
return null; */
} servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp);
}
private void logError(HttpServletRequest request) { return responseEntity;
InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO(); }
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
String serverName = eaiServerManager.getLocalServerName();
String uuid = null; /**
StringBuffer sb = new StringBuffer(); * url에서 뒤쪽 /이후를 제거하면서 찾는다.<br>
* /api/v1/public/getUserInfo.svc
String instanceid1 = serverName.substring(0, 2); *
String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length()); * @param apiUri
String instid = instanceid1 + instanceid2; * @return
uuid = instid + UUIDGenerator.getUUID(); */
private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager) {
String[] msgArgs = new String[1]; if (StringUtils.isBlank(apiUri)) {
msgArgs[0] = request.getRequestURI(); return null;
}
String errorCode = "RECEAIIRP010";
String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs); for (int i = 0; i < 10; i++) {
HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri);
errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호 if (adptUri != null) {
errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명 return adptUri;
errorInfoVO.setErrCd(errorCode); // 에러코드 }
errorInfoVO.setErrTxt(errorMsg); // 에러내용
errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각 // /api/v1/public
errorInfoVO.setErrDstcd(" "); apiUri = StringUtils.substringBeforeLast(apiUri, "/");
sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ") if (apiUri.length() < 4) { // /api
.append(request.getRequestURI()); return null;
errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용 }
errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명 }
InboundErrorLogger.error(errorInfoVO); return null;
} }
private void logError(HttpServletRequest request) {
InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
String serverName = eaiServerManager.getLocalServerName();
String uuid = null;
StringBuffer sb = new StringBuffer();
String instanceid1 = serverName.substring(0, 2);
String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length());
String instid = instanceid1 + instanceid2;
uuid = instid + UUIDGenerator.getUUID();
String[] msgArgs = new String[1];
msgArgs[0] = request.getRequestURI();
String errorCode = "RECEAIIRP010";
String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs);
errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호
errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명
errorInfoVO.setErrCd(errorCode); // 에러코드
errorInfoVO.setErrTxt(errorMsg); // 에러내용
errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각
errorInfoVO.setErrDstcd(" ");
sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ")
.append(request.getRequestURI());
errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용
errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
InboundErrorLogger.error(errorInfoVO);
}
private String makeResponseBodyMsg(String asyncMsgStyle) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("result", 1);
Map<String, Object> map = new HashMap<>();
switch (asyncMsgStyle) {
case "TB_SUC":
map.put("rspCode", "TB_SUC_000");
map.put("rspMsg", "정상");
map.put("data", dataMap);
break;
case "ONLYDATA":
map.put("data", dataMap);
map.put("success", "true");
break;
default:
map.put("code", "200");
map.put("data", dataMap);
map.put("message", "정상 처리 되었습니다.");
break;
}
JSONObject json = new JSONObject();
json.putAll(map);
return json.toJSONString();
}
} }
File diff suppressed because it is too large Load Diff