나이스 CI 연계 REST API 방식 서비스추가
parent
51b8e4f048
commit
a1e4bac731
@ -0,0 +1,57 @@
|
||||
package cokr.xit.ci.api.service.support.rest;
|
||||
|
||||
import com.google.gson.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
public class MapDeserailizer implements JsonDeserializer<Map<String, Object>> {
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public Map<String, Object> deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
return (Map<String, Object>) read(json);
|
||||
}
|
||||
|
||||
public Object read(JsonElement in) {
|
||||
if(in.isJsonArray()){ //JsonArray 이면...
|
||||
//JsonArray인 경우
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
JsonArray arr = in.getAsJsonArray();
|
||||
for (JsonElement anArr : arr) {
|
||||
//JsonPrimitive 나올 떄까지 for문
|
||||
list.add(read(anArr));
|
||||
}
|
||||
return list;
|
||||
}else if(in.isJsonObject()){ //JsonObject 이면...
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
JsonObject obj = in.getAsJsonObject();
|
||||
Set<Map.Entry<String, JsonElement>> entitySet = obj.entrySet();
|
||||
for(Map.Entry<String, JsonElement> entry: entitySet){
|
||||
//JsonPrimitive 나올 떄까지 for문
|
||||
map.put(entry.getKey(), read(entry.getValue()));
|
||||
}
|
||||
return map;
|
||||
}else if( in.isJsonPrimitive()){ //원시 Json 데이터 이면..
|
||||
JsonPrimitive prim = in.getAsJsonPrimitive();
|
||||
if(prim.isBoolean()){
|
||||
//true , fales 형으로
|
||||
return prim.getAsBoolean();
|
||||
}else if(prim.isString()){
|
||||
//String으로
|
||||
return prim.getAsString();
|
||||
}else if(prim.isNumber()){
|
||||
Number num = prim.getAsNumber();
|
||||
//Math.ceil 소수점을 올림한다.
|
||||
if(Math.ceil(num.doubleValue()) == num.longValue())
|
||||
//소수점 버림, Int형으로.
|
||||
return num.longValue();
|
||||
else{
|
||||
//소수점 안버림, Double 형으로
|
||||
return num.doubleValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,567 @@
|
||||
package cokr.xit.ci.api.service.support.rest;
|
||||
|
||||
import cokr.xit.ci.api.code.ErrCd;
|
||||
import cokr.xit.ci.api.model.ResponseVO;
|
||||
import cokr.xit.ci.api.service.support.rest.code.NiceCiApiCd;
|
||||
import cokr.xit.ci.api.service.support.rest.model.*;
|
||||
import cokr.xit.ci.core.utils.DateUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.logging.log4j.util.Base64Util;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
//public class NiceCiApi implements NiceCiApiStruct {
|
||||
public class NiceCiApi {
|
||||
|
||||
private final String PRODUCT_ID = "2101466024";
|
||||
@Value("${nice.ci.api.host}")
|
||||
private String HOST;
|
||||
@Value("${nice.ci.api.generate-token}")
|
||||
private String API_GENERATE_TOKEN;
|
||||
@Value("${nice.ci.api.revoke-token}")
|
||||
private String API_REVOKE_TOKEN;
|
||||
@Value("${nice.ci.api.publickey}")
|
||||
private String API_PUBLICKEY;
|
||||
@Value("${nice.ci.api.symmetrickey}")
|
||||
private String API_SYMMETRICKEY;
|
||||
@Value("${nice.ci.api.ci}")
|
||||
private String API_CI;
|
||||
|
||||
|
||||
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).disableHtmlEscaping().create();
|
||||
|
||||
//@Override
|
||||
public ResponseVO<GenerateTokenRespDTO> generateToken(String clientId, String clientSecret) {
|
||||
ErrCd errCd = ErrCd.ERR999;
|
||||
String errMsg = ErrCd.ERR999.getCodeNm();
|
||||
try {
|
||||
/* ==============================================================================
|
||||
* 유효성 확인
|
||||
============================================================================== */
|
||||
if (StringUtils.isEmpty(clientId)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트ID는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(clientSecret)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트비밀번호는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* HEADER 설정
|
||||
============================================================================== */
|
||||
String authorizationToken = Base64Util.encode(String.format("%s:%s", clientId, clientSecret));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
|
||||
headers.set("Authorization", String.format("Basic %s", authorizationToken));
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* URL 설정
|
||||
============================================================================== */
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(this.HOST)
|
||||
.append(API_GENERATE_TOKEN);
|
||||
Map<String, String> mParam = new HashMap<>();
|
||||
mParam.put("grant_type", "client_credentials");
|
||||
mParam.put("scope", "default");
|
||||
String jsonStr = gson.toJson(mParam);
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* API 호출
|
||||
============================================================================== */
|
||||
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
|
||||
log.info("==================================================================================");
|
||||
log.info("==== 토큰 생성 ====");
|
||||
log.info("[Headers]: " + resp.getHeaders().toString());
|
||||
log.info("[Body]: " + resp.getBody());
|
||||
log.info("==================================================================================");
|
||||
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* 결과 확인
|
||||
============================================================================== */
|
||||
if (!"1200".equals(resp.getHeaders().get("GW_RSLT_CD").get(0))) {
|
||||
errCd = ErrCd.ERR620;
|
||||
errMsg = String.format("[%s] %s.%s", resp.getHeaders().get("GW_RSLT_CD").get(0), resp.getHeaders().get("GW_RSLT_MSG").get(0), resp.getBody());
|
||||
throw new RuntimeException("응답 오류(GW_RSLT_CD) 입니다.");
|
||||
}
|
||||
// Map<String, Object> resultInfo = gson.fromJson(resp.getBody(), Map.class);
|
||||
// String accessToken = (String) resultInfo.get("access_token"); //사용자 엑세스 토큰 값(모든 API 요청시 헤더에 access_token을 포함하여 전송)
|
||||
// Long expiresIn = (Long) resultInfo.get("expires_in"); //access token 만료까지 남은시간(초)
|
||||
// String tokenType = (String) resultInfo.get("token_type"); //bearer로 고정
|
||||
// String scope = (String) resultInfo.get("scope"); //요청한 scope값(기본 default)
|
||||
// String expiredDt = DateUtil.absTimeSecToDate(expiresIn, "yyyyMMddHHmmss");
|
||||
// log.info("[엑세스토큰]: " + accessToken);
|
||||
// log.info("[엑세스토큰 만료시간]: " + expiredDt);
|
||||
GenerateTokenRespDTO resultInfo = gson.fromJson(resp.getBody(), GenerateTokenRespDTO.class);
|
||||
resultInfo.setExpiredDt(DateUtil.absTimeSecToDate(resultInfo.getExpiresIn(), "yyyyMMddHHmmss"));
|
||||
log.info("[응답데이터]: " + resultInfo.toString());
|
||||
|
||||
|
||||
return ResponseVO.<GenerateTokenRespDTO>builder().errCode(ErrCd.OK).errMsg(ErrCd.OK.getCodeNm()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.<GenerateTokenRespDTO>builder().errCode(errCd).errMsg(errMsg + " " + errMsg).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@Override
|
||||
public ResponseVO<RevokeTokenRespDTO> revokeToken(String accessToken, String clientId) {
|
||||
ErrCd errCd = ErrCd.ERR999;
|
||||
String errMsg = ErrCd.ERR999.getCodeNm();
|
||||
try {
|
||||
/* ==============================================================================
|
||||
* 유효성 확인
|
||||
============================================================================== */
|
||||
if (StringUtils.isEmpty(accessToken)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "엑세스토큰은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(clientId)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트ID는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* HEADER 설정
|
||||
============================================================================== */
|
||||
String bearerToken = Base64Util.encode(String.format("%s:%s:%s", accessToken, (new Date().getTime() / 1000), clientId));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
|
||||
headers.set("Authorization", String.format("bearer %s", bearerToken));
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* URL 설정
|
||||
============================================================================== */
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(this.HOST)
|
||||
.append(API_REVOKE_TOKEN);
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* API 호출
|
||||
============================================================================== */
|
||||
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), null, headers);
|
||||
log.info("==================================================================================");
|
||||
log.info("==== 토큰 폐기 ====");
|
||||
log.info("[Headers]: " + resp.getHeaders().toString());
|
||||
log.info("[Body]: " + resp.getBody());
|
||||
log.info("==================================================================================");
|
||||
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* 결과 확인
|
||||
============================================================================== */
|
||||
if (!"1200".equals(resp.getHeaders().get("GW_RSLT_CD").get(0))) {
|
||||
errCd = ErrCd.ERR620;
|
||||
errMsg = String.format("[%s] %s.%s", resp.getHeaders().get("GW_RSLT_CD").get(0), resp.getHeaders().get("GW_RSLT_MSG").get(0), resp.getBody());
|
||||
throw new RuntimeException("응답 오류 입니다. ");
|
||||
}
|
||||
RevokeTokenRespDTO resultInfo = gson.fromJson(resp.getBody(), RevokeTokenRespDTO.class);
|
||||
log.info("[응답데이터]: " + resultInfo.toString());
|
||||
|
||||
|
||||
return ResponseVO.<RevokeTokenRespDTO>builder().errCode(ErrCd.OK).errMsg(ErrCd.OK.getCodeNm()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.<RevokeTokenRespDTO>builder().errCode(errCd).errMsg(e.getMessage() + " " + errMsg).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@Override
|
||||
public ResponseVO<PublickeyRespDTO> generatePublickey(String accessToken, String clientId, String pubkeyVersion, String symkeyRegInfo) {
|
||||
ErrCd errCd = ErrCd.ERR999;
|
||||
String errMsg = ErrCd.ERR999.getCodeNm();
|
||||
try {
|
||||
/* ==============================================================================
|
||||
* 유효성 확인
|
||||
============================================================================== */
|
||||
if (StringUtils.isEmpty(accessToken)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "엑세스토큰은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(clientId)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트ID는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(pubkeyVersion)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "공개키버전은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(symkeyRegInfo)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "공개키암호화 값(대칭키를 공개키로 암호화)은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* HEADER 설정
|
||||
============================================================================== */
|
||||
String bearerToken = Base64Util.encode(String.format("%s:%s:%s", accessToken, (new Date().getTime() / 1000), clientId));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
|
||||
headers.set("Authorization", String.format("bearer %s", bearerToken));
|
||||
headers.set("client_id", clientId);
|
||||
headers.set("productID", PRODUCT_ID);
|
||||
headers.set("CNTY_CD", "ko"); //이용언어: ko, en, cn...
|
||||
// headers.set("TRAN_ID", ); //API통신구간에서 요청에 대한 응답을 확인하기 위한 고유번호
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* URL 설정
|
||||
============================================================================== */
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(this.HOST)
|
||||
.append(API_PUBLICKEY);
|
||||
Map<String, String> mParam = new HashMap<>();
|
||||
mParam.put("req_dtim", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
|
||||
String jsonStr = gson.toJson(mParam);
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* API 호출
|
||||
============================================================================== */
|
||||
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
|
||||
log.info("==================================================================================");
|
||||
log.info("==== 공개키 요청 ====");
|
||||
log.info("[Headers]: " + resp.getHeaders().toString());
|
||||
log.info("[Body]: " + resp.getBody());
|
||||
log.info("==================================================================================");
|
||||
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* 결과 확인
|
||||
============================================================================== */
|
||||
if (!"1200".equals(resp.getHeaders().get("GW_RSLT_CD").get(0))) {
|
||||
errCd = ErrCd.ERR620;
|
||||
errMsg = String.format("[%s] %s.%s", resp.getHeaders().get("GW_RSLT_CD").get(0), resp.getHeaders().get("GW_RSLT_MSG").get(0), resp.getBody());
|
||||
throw new RuntimeException("응답 오류(GW_RSLT_CD) 입니다.");
|
||||
}
|
||||
PublickeyRespDTO resultInfo = gson.fromJson(resp.getBody(), PublickeyRespDTO.class);
|
||||
log.info("[응답데이터]: " + resultInfo.toString());
|
||||
if (!"P000".equals(resultInfo.getRspCd())) {
|
||||
errCd = ErrCd.ERR601;
|
||||
errMsg = String.format("[%s]%s", resultInfo.getRspCd(), NiceCiApiCd.valueOfEnum(resultInfo.getRspCd()).getCodeNm());
|
||||
throw new RuntimeException("응답코드(rsp_cd) 오류.");
|
||||
}
|
||||
if (!"0000".equals(resultInfo.getResultCd())) {
|
||||
errCd = ErrCd.ERR601;
|
||||
errMsg = String.format("[%s]%s", resultInfo.getResultCd(), NiceCiApiCd.valueOfEnum("DRSLT_" + resultInfo.getResultCd()).getCodeNm());
|
||||
throw new RuntimeException("상세결과코드(result_cd) 오류.");
|
||||
}
|
||||
|
||||
|
||||
return ResponseVO.<PublickeyRespDTO>builder().errCode(ErrCd.OK).errMsg(ErrCd.OK.getCodeNm()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.<PublickeyRespDTO>builder().errCode(errCd).errMsg(e.getMessage() + " " + errMsg).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@Override
|
||||
public ResponseVO<SymmetrickeyRespDTO> generateSymmetrickey(String accessToken, String clientId, String pubkeyVersion, String symkeyRegInfo) {
|
||||
ErrCd errCd = ErrCd.ERR999;
|
||||
String errMsg = ErrCd.ERR999.getCodeNm();
|
||||
try {
|
||||
/* ==============================================================================
|
||||
* 유효성 확인
|
||||
============================================================================== */
|
||||
if (StringUtils.isEmpty(accessToken)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "엑세스토큰은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(clientId)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트ID는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(pubkeyVersion)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "공개키버전은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(symkeyRegInfo)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "JSON암호화값은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* HEADER 설정
|
||||
============================================================================== */
|
||||
String bearerToken = Base64Util.encode(String.format("%s:%s:%s", accessToken, (new Date().getTime() / 1000), clientId));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
|
||||
headers.set("Authorization", String.format("bearer %s", bearerToken));
|
||||
headers.set("client_id", clientId);
|
||||
headers.set("productID", PRODUCT_ID);
|
||||
headers.set("CNTY_CD", "ko"); //이용언어: ko, en, cn...
|
||||
// headers.set("TRAN_ID", ); //API통신구간에서 요청에 대한 응답을 확인하기 위한 고유번호
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* URL 설정
|
||||
============================================================================== */
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(this.HOST)
|
||||
.append(API_PUBLICKEY);
|
||||
Map<String, String> mParam = new HashMap<>();
|
||||
mParam.put("pubkey_version", pubkeyVersion);
|
||||
mParam.put("symkey_reg_info", symkeyRegInfo);
|
||||
String jsonStr = gson.toJson(mParam);
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* API 호출
|
||||
============================================================================== */
|
||||
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
|
||||
log.info("==================================================================================");
|
||||
log.info("==== 대칭키 요청 ====");
|
||||
log.info("[Headers]: " + resp.getHeaders().toString());
|
||||
log.info("[Body]: " + resp.getBody());
|
||||
log.info("==================================================================================");
|
||||
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* 결과 확인
|
||||
============================================================================== */
|
||||
if (!"1200".equals(resp.getHeaders().get("GW_RSLT_CD").get(0))) {
|
||||
errCd = ErrCd.ERR620;
|
||||
errMsg = String.format("[%s] %s.%s", resp.getHeaders().get("GW_RSLT_CD").get(0), resp.getHeaders().get("GW_RSLT_MSG").get(0), resp.getBody());
|
||||
throw new RuntimeException("API 응답 오류 입니다.");
|
||||
}
|
||||
SymmetrickeyRespDTO resultInfo = gson.fromJson(resp.getBody(), SymmetrickeyRespDTO.class);
|
||||
log.info("[응답데이터]: " + resultInfo.toString());
|
||||
if (!"P000".equals(resultInfo.getRspCd())) {
|
||||
errCd = ErrCd.ERR601;
|
||||
errMsg = String.format("[%s]%s", resultInfo.getRspCd(), NiceCiApiCd.valueOfEnum(resultInfo.getRspCd()).getCodeNm());
|
||||
throw new RuntimeException("응답코드(rsp_cd) 오류.");
|
||||
}
|
||||
if (!"0000".equals(resultInfo.getResultCd())) {
|
||||
errCd = ErrCd.ERR601;
|
||||
errMsg = String.format("[%s]%s", resultInfo.getResultCd(), NiceCiApiCd.valueOfEnum("DRSLT_" + resultInfo.getResultCd()).getCodeNm());
|
||||
throw new RuntimeException("상세결과코드(result_cd) 오류.");
|
||||
}
|
||||
|
||||
|
||||
return ResponseVO.<SymmetrickeyRespDTO>builder().errCode(ErrCd.OK).errMsg(ErrCd.OK.getCodeNm()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.<SymmetrickeyRespDTO>builder().errCode(errCd).errMsg(e.getMessage() + " " + errMsg).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@Override
|
||||
public ResponseVO<CiRespDTO> getCi(String clientId, String clientSecret, String symkeyVersion, String encData, String integrityValue) {
|
||||
ErrCd errCd = ErrCd.ERR999;
|
||||
String errMsg = ErrCd.ERR999.getCodeNm();
|
||||
try {
|
||||
/* ==============================================================================
|
||||
* 유효성 확인
|
||||
============================================================================== */
|
||||
if (StringUtils.isEmpty(clientId)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트ID는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(clientSecret)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "클라이언트비밀번호는 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(symkeyVersion)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "대칭키 버전 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(encData)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "JSON암호화 값은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
if (StringUtils.isEmpty(integrityValue)) {
|
||||
errCd = ErrCd.ERR401;
|
||||
errMsg = "무결성 체크 값은 필수 입력값 입니다.";
|
||||
throw new RuntimeException("유효성 검증 실패.");
|
||||
}
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* HEADER 설정
|
||||
============================================================================== */
|
||||
// String authorizationToken = Base64.getEncoder().encodeToString(String.format("%s:%s", clientId, clientSecret).getBytes(StandardCharsets.UTF_8));
|
||||
String authorizationToken = Base64Util.encode(String.format("%s:%s", clientId, clientSecret));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
|
||||
headers.set("Authorization", String.format("Basic %s", authorizationToken));
|
||||
headers.set("productID", PRODUCT_ID);
|
||||
headers.set("CNTY_CD", "ko"); //이용언어: ko, en, cn...
|
||||
// headers.set("TRAN_ID", ); //API통신구간에서 요청에 대한 응답을 확인하기 위한 고유번호
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* URL 설정
|
||||
============================================================================== */
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(this.HOST)
|
||||
.append(API_CI);
|
||||
Map<String, String> mParam = new HashMap<>();
|
||||
mParam.put("symkey_version", symkeyVersion);
|
||||
mParam.put("enc_data", encData);
|
||||
mParam.put("integrity_value", integrityValue);
|
||||
String jsonStr = gson.toJson(mParam);
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* API 호출
|
||||
============================================================================== */
|
||||
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
|
||||
log.info("==================================================================================");
|
||||
log.info("==== CI조회 ====");
|
||||
log.info("[Headers]: " + resp.getHeaders().toString());
|
||||
log.info("[Body]: " + resp.getBody());
|
||||
log.info("==================================================================================");
|
||||
|
||||
|
||||
|
||||
/* ==============================================================================
|
||||
* 결과 확인
|
||||
============================================================================== */
|
||||
if (!"1200".equals(resp.getHeaders().get("GW_RSLT_CD").get(0))) {
|
||||
errCd = ErrCd.ERR620;
|
||||
errMsg = String.format("[%s] %s.%s", resp.getHeaders().get("GW_RSLT_CD").get(0), resp.getHeaders().get("GW_RSLT_MSG").get(0), resp.getBody());
|
||||
throw new RuntimeException("응답 오류(GW_RSLT_CD) 입니다.");
|
||||
}
|
||||
CiRespDTO resultInfo = gson.fromJson(resp.getBody(), CiRespDTO.class);
|
||||
log.info("[응답데이터]: " + resultInfo.toString());
|
||||
|
||||
|
||||
return ResponseVO.<CiRespDTO>builder().errCode(ErrCd.OK).errMsg(ErrCd.OK.getCodeNm()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResponseVO.<CiRespDTO>builder().errCode(errCd).errMsg(e.getMessage() + " " + errMsg).build();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: API 호출
|
||||
* </pre>
|
||||
*
|
||||
* @param method
|
||||
* @param url
|
||||
* @param body
|
||||
* @param headers
|
||||
* @return ResponseEntity 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
*/
|
||||
private ResponseEntity<String> callApi(HttpMethod method, String url, String body, HttpHeaders headers) {
|
||||
log.debug("param =======================");
|
||||
log.debug(body);
|
||||
|
||||
|
||||
ResponseEntity<String> responseEntity = null;
|
||||
try {
|
||||
//uri 및 entity(param) 설정
|
||||
HttpEntity<?> entity = null;
|
||||
UriComponents uri = null;
|
||||
switch (method) {
|
||||
case GET:
|
||||
entity = new HttpEntity<>(headers);
|
||||
uri = UriComponentsBuilder
|
||||
.fromHttpUrl(String.format("%s?%s", url, body == null ? "" : body))
|
||||
// .encode(StandardCharsets.UTF_8) //"%"기호가 "%25"로 인코딩 발생하여 주석처리 함.
|
||||
.build(false);
|
||||
break;
|
||||
case POST:
|
||||
entity = new HttpEntity<>(body, headers);
|
||||
uri = UriComponentsBuilder
|
||||
.fromHttpUrl(url)
|
||||
.encode(StandardCharsets.UTF_8)
|
||||
.build();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//api 호출
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
|
||||
factory.setConnectTimeout(3000); //커넥션타임아웃 설정 3초
|
||||
factory.setReadTimeout(3000);//타임아웃 설정 3초
|
||||
RestTemplate restTemplate = new RestTemplate(factory);
|
||||
System.out.println(" url => " + uri.toString());
|
||||
System.out.println(" method => " + method);
|
||||
System.out.println(" headers => " + entity.getHeaders().toString());
|
||||
System.out.println(" body => " + entity.getBody());
|
||||
responseEntity = restTemplate.exchange(URI.create(uri.toString()), method, entity, String.class); //이 한줄의 코드로 API를 호출해 String타입으로 전달 받는다.
|
||||
|
||||
/*
|
||||
* HttpStatus 정보 확인 방법
|
||||
* -.코드: responseEntity.getStatusCodeValue()
|
||||
* -.메시지: responseEntity.getStatusCode()
|
||||
*/
|
||||
|
||||
} catch (HttpServerErrorException e) {
|
||||
responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
|
||||
log.error(String.format("call API 서버오류[url =>%s param => %s error => %s]", url, body, e.getMessage()));
|
||||
} catch (HttpClientErrorException e) {
|
||||
responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
|
||||
log.error(String.format("call API 클라이언트오류[url =>%s param => %s error => %s]", url, body, e.getMessage()));
|
||||
} catch (RestClientException e) { //timeout 발생 또는 기타 오류...
|
||||
responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.REQUEST_TIMEOUT);
|
||||
log.error(String.format("RestAPI 호출 오류[url =>%s param => %s error => %s]", url, body, e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
log.error(String.format("call API 기타오류[url =>%s param => %s error => %s]", url, body, e.getMessage()));
|
||||
}
|
||||
|
||||
//결과 응답
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cokr.xit.ci.api.service.support.rest;
|
||||
|
||||
import cokr.xit.ci.api.model.ResponseVO;
|
||||
|
||||
public interface NiceCiApiStruct {
|
||||
|
||||
/**
|
||||
* 1. 토큰발급 API
|
||||
*/
|
||||
ResponseVO generateToken();
|
||||
|
||||
/**
|
||||
* 2. 토큰폐기 API
|
||||
*/
|
||||
ResponseVO revokeToken();
|
||||
|
||||
/**
|
||||
* 공개키요청 API
|
||||
* -.대칭키 암호화를 위한 공개키 요청
|
||||
*/
|
||||
ResponseVO generatePublickey();
|
||||
|
||||
/**
|
||||
* 대칭키요청 API
|
||||
* -.데이터 암호화를 위한 대칭키 요청
|
||||
*/
|
||||
ResponseVO generateSymmetrickey();
|
||||
|
||||
/**
|
||||
* CI 조회
|
||||
*/
|
||||
ResponseVO getCi();
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package cokr.xit.ci.api.service.support.rest.code;
|
||||
|
||||
public enum NiceCiApiCd {
|
||||
|
||||
UNKNOWN("알수없음")
|
||||
/* =======================================================================
|
||||
* HTTP 응답코드
|
||||
* -. HTTP의 코드값을 열거형 상수로 선언하기 위해 prefix "HTTP_"를 추가 함
|
||||
======================================================================= */
|
||||
, HTTP_200("No Error")
|
||||
, HTTP_400("Bad Request or Inavalid Token")
|
||||
, HTTP_401("Authorized required")
|
||||
, HTTP_402("unAuthorized")
|
||||
, HTTP_403("service Disabled")
|
||||
, HTTP_404("Service Not Found")
|
||||
, HTTP_500("Internal Server Error")
|
||||
, HTTP_501("Access Denied by Protected Service")
|
||||
, HTTP_502("Bad Response from Protected Service")
|
||||
, HTTP_503("Service Temporarily Unavailable")
|
||||
|
||||
/* =======================================================================
|
||||
* APIM 결과코드 (dataHeader)
|
||||
* -. Data Header의 코드값을 열거형 상수로 선언하기 위해 prefix "HEAD_"를 추가 함
|
||||
======================================================================= */
|
||||
, HEAD_1200("오류 없음 (정상)")
|
||||
, HEAD_1300("request body가 비었습니다.")
|
||||
, HEAD_1400("잘못된 요청")
|
||||
, HEAD_1401("인증 필요")
|
||||
, HEAD_1402("권한없음")
|
||||
, HEAD_1403("서비스 사용 중지됨")
|
||||
, HEAD_1404("서비스를 찾을 수 없음")
|
||||
, HEAD_1500("서버 내부 오류")
|
||||
, HEAD_1501("보호된 서비스에서 엑세스가 거부되었습니다.")
|
||||
, HEAD_1502("보호된 서비스에서 응답이 잘못되었습니다.")
|
||||
, HEAD_1503("일시적으로 사용할 수 없는 서비스")
|
||||
, HEAD_1700("엑세스가 허용되지 않습니다. - Client ID")
|
||||
, HEAD_1701("엑세스가 허용되지 않습니다. - Service URI")
|
||||
, HEAD_1702("엑세스가 허용되지 않습니다. - Client ID + Client IP")
|
||||
, HEAD_1703("엑세스가 허용되지 않습니다. - Client ID + Service URI")
|
||||
, HEAD_1705("엑세스가 허용되지 않습니다. - Client ID + Black List Client IP")
|
||||
, HEAD_1706("액세스가 허용되지 않습니다 - Client ID + Product Code")
|
||||
, HEAD_1711("거래제한된 요일입니다.")
|
||||
, HEAD_1712("거래제한된 시간입니다.")
|
||||
, HEAD_1713("거래제한된 요일/시간입니다.")
|
||||
, HEAD_1714("거래제한된 일자입니다.")
|
||||
, HEAD_1715("거래제한된 일자/시간입니다.")
|
||||
, HEAD_1716("공휴일 거래가 제한된 서비스입니다.")
|
||||
, HEAD_1717("SQL인젝션, XSS방어")
|
||||
, HEAD_1800("잘못된 토큰")
|
||||
, HEAD_1801("잘못된 클라이언트 정보")
|
||||
, HEAD_1900("초과된 연결 횟수")
|
||||
, HEAD_1901("초과 된 토큰 조회 실패")
|
||||
, HEAD_1902("초과된 토큰 체크 실패")
|
||||
, HEAD_1903("초과된 접속자 수 ")
|
||||
, HEAD_1904("전송 크기 초과")
|
||||
, HEAD_1905("접속량이 너무 많음")
|
||||
, HEAD_1906("상품이용 한도 초과")
|
||||
, HEAD_1907("API 이용 주기 초과")
|
||||
, HEAD_1908("상품 이용 주기 초과")
|
||||
|
||||
|
||||
/* =======================================================================
|
||||
* 응답코드(rsp_cd)
|
||||
======================================================================= */
|
||||
, P000("정상응답")
|
||||
, S603("내부 DB 오류")
|
||||
, P013("이용기관 개시상태 아님")
|
||||
, E998("서비스 권한 오류")
|
||||
, E999("내부시스템 오류")
|
||||
, Exxx("기타시스템 오류")
|
||||
|
||||
|
||||
/* =======================================================================
|
||||
* APIM 결과코드 (dataBody)
|
||||
======================================================================= */
|
||||
, EAPI2500("맵핑정보 없음 - {0}")
|
||||
, EAPI2510("요청맵핑 데이터가 없습니다.")
|
||||
, EAPI2530("응답전문 맵핑 오류")
|
||||
, EAPI2540("대응답 정보 없음")
|
||||
, EAPI2550("숫자타입 입력 오류")
|
||||
, EAPI2560("실수타입 입력 오류")
|
||||
, EAPI2561("실수형 타입 길이정보 문법 에러 ( 형식 : \"전체길이,실수부길이\")")
|
||||
, EAPI2562("실수형 타입 논리 에러 ( 전체 길이는 소수부 길이보다 커야합니다. )")
|
||||
, EAPI2563("실수형 타입 파싱 에러( 입력값을 실수값으로 변환할 수 없습니다. )")
|
||||
, EAPI2564("실수형 타입 정수부 길이 에러")
|
||||
, EAPI2565("실수형 타입 소수부 길이 에러")
|
||||
, EAPI2600("내부 시스템 오류")
|
||||
, EAPI2700("외부 시스템 연동 오류")
|
||||
, EAPI2701("타임아웃이 발생하였습니다.")
|
||||
, EAPI2702("DISCONNECTION_OK")
|
||||
, EAPI2703("DISCONNECTION_FAIL")
|
||||
, EAPI2704("RESULT_OK")
|
||||
, EAPI2705("RESULT_FAIL")
|
||||
, EAPI2892("반복부 카운터 에러(지정된 건수보다 크거나 작습니다)")
|
||||
, EAPI5001("schema 검증 정보가 없습니다.")
|
||||
, EAPI5002("schema 검증 실패")
|
||||
|
||||
|
||||
/* =======================================================================
|
||||
* 상세 결과코드
|
||||
* -. 상세결과 코드값을 열거형 상수로 선언하기 위해 prefix "DRSLT_"를 추가 함
|
||||
======================================================================= */
|
||||
, DRSLT_0000("공개키 발급")
|
||||
, DRSLT_0001("필수입력값 오류")
|
||||
, DRSLT_0003("공개키 발급 대상 회원사 아님")
|
||||
, DRSLT_0099("기타오류")
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
private final String code; //코드
|
||||
private final String codeNm; //코드명
|
||||
NiceCiApiCd(String codeNm) {
|
||||
this.code = this.name();
|
||||
this.codeNm = codeNm;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getCodeNm() {
|
||||
return this.codeNm;
|
||||
}
|
||||
|
||||
|
||||
public static NiceCiApiCd valueOfEnum(String code){
|
||||
if(code == null)
|
||||
return NiceCiApiCd.UNKNOWN;
|
||||
|
||||
NiceCiApiCd ensErrCd = null;
|
||||
try {
|
||||
ensErrCd = NiceCiApiCd.valueOf(code);
|
||||
} catch (IllegalArgumentException e){
|
||||
ensErrCd = NiceCiApiCd.UNKNOWN;
|
||||
}
|
||||
return ensErrCd;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
import cokr.xit.ci.api.service.support.rest.model.conf.EncData;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class CiRespDTO implements TransDTO {
|
||||
|
||||
@JsonAlias({"rsp_cd"})
|
||||
private String rspCd; //dataBody 정상처리여부 (P000 성공, 이외 모두 오류)
|
||||
|
||||
@JsonAlias({"res_msg"})
|
||||
private String resMsg; //rsp_cd가 "EAPI"로 시작될 경우 오류 메시지 세팅
|
||||
|
||||
@JsonAlias({"enc_data"})
|
||||
private EncData encData; //JSON암호화값(rsp_cd가 P000일 때 나감) - 응답정보를 회원사에서 요청시 전달한 대칭키로 암호화한 값
|
||||
|
||||
@JsonAlias({"integrity_value"})
|
||||
private String integrityValue; //무결성체크를 위해 enc_data를 HMAC처리 후, BASE64 인코딩한 값
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class GenerateTokenRespDTO implements TransDTO {
|
||||
|
||||
@JsonAlias({"access_token"})
|
||||
private String accessToken; //사용자 엑세스 토큰 값(모든 API 요청시 헤더에 access_token을 포함하여 전송)
|
||||
|
||||
@JsonAlias({"expires_in"})
|
||||
private Long expiresIn; //access token 만료까지 남은시간(초)
|
||||
|
||||
@JsonAlias({"token_type"})
|
||||
private String tokenType; //bearer로 고정
|
||||
|
||||
@JsonAlias({"scope"})
|
||||
private String scope; //요청한 scope값(기본 default)
|
||||
|
||||
@Setter
|
||||
private String expiredDt; //access token 만료시간(yyyyMmddHHmmss)
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class PublickeyRespDTO implements TransDTO {
|
||||
|
||||
@JsonAlias({"rsp_cd"})
|
||||
private String rspCd; //dataBody 정상처리여부 (P000 성공, 이외 모두 오류)
|
||||
|
||||
@JsonAlias({"res_msg"})
|
||||
private String resMsg; //rsp_cd가 "EAPI"로 시작될 경우 오류 메시지 세팅
|
||||
|
||||
@JsonAlias({"result_cd"})
|
||||
private String resultCd; //rsp_cd가 P000일 때 상세결과코드(0000:공개키발급, 0001:필수입력값 오류, 0003:공개키 발급 대상 회원사 아님, 0099: 기타오류)
|
||||
|
||||
@JsonAlias({"site_code"})
|
||||
private String siteCode; //사이트코드
|
||||
|
||||
@JsonAlias({"key_version"})
|
||||
private String keyVersion; //공개키 버전
|
||||
|
||||
@JsonAlias({"public_key"})
|
||||
private String publicKey; //공개키
|
||||
|
||||
@JsonAlias({"valid_dtim"})
|
||||
private String validDtim; //공개키 만료일시(YYYYMMDDHH24MISS)
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class RevokeTokenRespDTO implements TransDTO {
|
||||
|
||||
@JsonAlias({"result"})
|
||||
private Boolean result; //폐기여부(true: 폐기 성공, false: 폐기 실패)
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
import cokr.xit.ci.api.service.support.rest.model.conf.SymkeyStatInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class SymmetrickeyRespDTO implements TransDTO {
|
||||
|
||||
@JsonAlias({"rsp_cd"})
|
||||
private String rspCd; //dataBody 정상처리여부 (P000 성공, 이외 모두 오류)
|
||||
|
||||
@JsonAlias({"res_msg"})
|
||||
private String resMsg; //rsp_cd가 "EAPI"로 시작될 경우 오류 메시지 세팅
|
||||
|
||||
@JsonAlias({"result_cd"})
|
||||
private String resultCd; //rsp_cd가 P000일 때 상세결과코드(0000:대칭키발급, 0001:공개키기간만료, 0002:공개키를 찾을 수 없음, 0003:공개키를 발급한 회원사 아님, 0004:복호화 오류, 0005:필수입력값 오류(key_version, key_info 필수값 확인), 0006:대칭키 등록 가능 회원사 아님, 0007:key 중복 오류(현재 및 직전에 사용한 Key 사용 불가), 0008:요청사이트코드와 공개키발급 사이트코드 다름, 0099: 기타오류)
|
||||
|
||||
@JsonAlias({"symkey_stat_info"})
|
||||
private SymkeyStatInfo symkeyStatInfo; //JSON값(회원사에 생성되어 있는 대칭키 버전별 유효기간(result_cd 가 0000, 0007일 경우에 나감)
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model;
|
||||
|
||||
public interface TransDTO
|
||||
{
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model.conf;
|
||||
|
||||
import cokr.xit.ci.api.service.support.rest.model.TransDTO;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class EncData implements TransDTO {
|
||||
|
||||
@JsonAlias({"result_cd"})
|
||||
private String resultCd; //rsp_cd가 P000일때 상세결과코드(0000:처리완료, 0001:대칭키 기간 만료, 0002:대칭키를 찾을 수 없음, 0003:대칭키를 발급한 회원사 아님, 0004:복호화 오류, 0005:필수입력값 오류(integrity_value, enc_data 내 필수값 확인), 0006:데이터 무결성 오류(hmac값 불일치), 0007:정보요청유형 입력값 오류(info_req_type이 1 아님), 0008:주민번호 유효성 오류(생년월일 유효성 및 숫자 아님), 0009:거래요청시간 포멧오류(req_dtim 자릿수 및 숫자 아님), 0099:기타오류)
|
||||
|
||||
@JsonAlias({"ci1"})
|
||||
private String ci1; //연계정보1(Connection Info로 다른 웹사이트간 고객확인용으로 사용)
|
||||
|
||||
@JsonAlias({"ci2"})
|
||||
private String ci2; //연계정보2(연계정보1의 Key 유출에 대비한 예비값)
|
||||
|
||||
@JsonAlias({"updt_cnt"})
|
||||
private String updtCnt; //갱신횟수(연계정보 Key 유출될 경우 갱신 횟수(초기값 1세팅))
|
||||
|
||||
@JsonAlias({"tx_unique_no"})
|
||||
private String txUniqueNo; //거래고유번호(result_cd가 0000일 경우 NICE에서 제공하는 거래일련번호)
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cokr.xit.ci.api.service.support.rest.model.conf;
|
||||
|
||||
import cokr.xit.ci.api.service.support.rest.model.TransDTO;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Builder
|
||||
public class SymkeyStatInfo implements TransDTO {
|
||||
|
||||
@JsonAlias({"cur_symkey_version"})
|
||||
private String curSymkeyVersion; //현재 등록요청한 대칭키 버전
|
||||
|
||||
@JsonAlias({"cur_valid_dtim"})
|
||||
private String curValidDtim; //현재 등록된 대칭키 만료일시(YYYYMMDDHH24MISS)
|
||||
|
||||
@JsonAlias({"bef_symkey_version"})
|
||||
private String befSymkeyVersion; //이전 등록된 대칭키 버전
|
||||
|
||||
@JsonAlias({"bef_valid_dtim"})
|
||||
private String befValidDtim; //이전 등록된 대칭키 만료일시(YYYYMMDDHH24MISS)
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
|
||||
package cokr.xit.ci.core.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
public class DateUtil {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: 절대시간(단위: second)을 현재 시간으로 반환 한다.</pre>
|
||||
* @param sec
|
||||
* @param fmt
|
||||
* @return String 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static String absTimeSecToDate(int sec, String fmt) {
|
||||
return absTimeSecToDate(sec * 1L, fmt);
|
||||
}
|
||||
/**
|
||||
* <pre>메소드 설명: 절대시간(단위: second)을 현재 시간으로 반환 한다.</pre>
|
||||
* @param sec
|
||||
* @param fmt
|
||||
* @return String 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static String absTimeSecToDate(Long sec, String fmt) {
|
||||
if(sec==null)
|
||||
return null;
|
||||
return absTimeToDate(sec * 1000L, fmt);
|
||||
}
|
||||
/**
|
||||
* <pre>메소드 설명: 절대시간(단위: ms)을 현재 시간으로 반환 한다.</pre>
|
||||
* @param millionSec
|
||||
* @param fmt
|
||||
* @return String 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static String absTimeToDate(Long millionSec, String fmt) {
|
||||
if(fmt == null || "".equals(fmt)) fmt = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
Date date = new Date(millionSec);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fmt);
|
||||
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: 시간을 절대시간(단위: sec)로 반환 한다.</pre>
|
||||
* @param expireDt 만료일시(yyyyMMddHHmmss)
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static Long dateToAbsTimeSec(String expireDt) {
|
||||
return dateToAbsTime(expireDt)/1000;
|
||||
}
|
||||
/**
|
||||
* <pre>메소드 설명: 시간을 절대시간(단위: sec)로 반환 한다.</pre>
|
||||
* @param year
|
||||
* @param month
|
||||
* @param day
|
||||
* @param hour
|
||||
* @param minute
|
||||
* @param sec
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static Long dateToAbsTimeSec(int year, int month, int day, int hour, int minute, int sec) {
|
||||
return dateToAbsTime(year, month, day, hour, minute, sec)/1000;
|
||||
}
|
||||
/**
|
||||
* <pre>메소드 설명: 시간을 절대시간(단위: ms)로 반환 한다.</pre>
|
||||
* @param expireDt 만료일시(yyyyMMddHHmmss)
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
@SuppressWarnings("finally")
|
||||
public static Long dateToAbsTime(String expireDt) {
|
||||
if(expireDt==null)
|
||||
return 0L;
|
||||
|
||||
expireDt = expireDt.replaceAll("[^0-9]", "");
|
||||
if("".equals(expireDt))
|
||||
return 0L;
|
||||
|
||||
int year, month, day, hour, minute, sec;
|
||||
year = month = day = hour = minute = sec = 0;
|
||||
try {
|
||||
year = Integer.parseInt(expireDt.substring(0,4));
|
||||
month = Integer.parseInt(expireDt.substring(4,6));
|
||||
day = Integer.parseInt(expireDt.substring(6,8));
|
||||
hour = Integer.parseInt(expireDt.substring(8,10));
|
||||
minute = Integer.parseInt(expireDt.substring(10,12));
|
||||
sec = Integer.parseInt(expireDt.substring(12,14));
|
||||
} catch(Exception e) {
|
||||
log.error(String.format("dateToAbsTime fail... expireDt is [%s]", expireDt));
|
||||
} finally {
|
||||
return dateToAbsTime(year, month, day, hour, minute, sec);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* <pre>메소드 설명: 시간을 절대시간(단위: ms)로 반환 한다.</pre>
|
||||
* @param year
|
||||
* @param month
|
||||
* @param day
|
||||
* @param hour
|
||||
* @param minute
|
||||
* @param sec
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Long dateToAbsTime(int year, int month, int day, int hour, int minute, int sec) {
|
||||
if(month < 0) month = 1;
|
||||
if(month > 11) month = 12;
|
||||
if(day < 1 || day > 31) day = 1;
|
||||
if(hour < 0 || hour > 23) hour = 0;
|
||||
if(minute < 0 || minute > 59) minute = 0;
|
||||
if(sec < 0 || sec > 59) sec = 0;
|
||||
|
||||
Date curDate = new Date (year-1900, month-1, day, hour, minute, sec);
|
||||
return curDate.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: 일수를 상대시간(단위: ms)로 반환 한다.</pre>
|
||||
* @param days
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2021. 11. 19.
|
||||
*/
|
||||
public static Long daysToRelTime(int days) {
|
||||
if(days<0) days=0;
|
||||
return days * 24L * 60L * 60L * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: 일시(yyyyMMddHHmmss)를 LocalDateTime 으로 반환 한다.</pre>
|
||||
* @param yyyyMMddHHmmss
|
||||
* @return Long 요청처리 후 응답객체
|
||||
* @author: 박민규
|
||||
* @date: 2022. 3. 15.
|
||||
*/
|
||||
public static LocalDateTime toLocalDateTime(String yyyyMMddHHmmss){
|
||||
String date = Optional.ofNullable(yyyyMMddHHmmss).orElseGet(()->null);
|
||||
|
||||
if(date==null) return null;
|
||||
|
||||
date = date.replaceAll("[^0-9]", "");
|
||||
if(date.length()!=14)
|
||||
return null;
|
||||
|
||||
|
||||
return LocalDateTime.of(
|
||||
Integer.parseInt(date.substring(0,4))
|
||||
, Integer.parseInt(date.substring(4,6))
|
||||
, Integer.parseInt(date.substring(6,8))
|
||||
, Integer.parseInt(date.substring(8,10))
|
||||
, Integer.parseInt(date.substring(10,12))
|
||||
, Integer.parseInt(date.substring(12,14))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue