feat: Nice CI API 추가

- 기관용 토큰 발급 / 폐기
dev
gitea-관리자 1 year ago
parent 1b55a58e39
commit c6a3166183

@ -45,10 +45,20 @@ public class SpringDocsApiConfig {
.build();
}
@Bean
public GroupedOpenApi niceCi() {
return GroupedOpenApi.builder()
.group("3. Nice CI API")
.pathsToMatch(
"/api/nice/v1/**"
)
.build();
}
@Bean
public GroupedOpenApi bizDoc() {
return GroupedOpenApi.builder()
.group("3. 전자고지 카카오문서 확인 API")
.group("6. 전자고지 문서 확인 API")
.pathsToMatch(
"/api/ens/v1/**"
)

@ -1,13 +1,10 @@
package kr.xit.ens.support.cmm.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@ -17,11 +14,10 @@ import javax.validation.Validator;
import kr.xit.biz.ens.model.cmm.CmmEnsFileDTO.FmcExcel;
import kr.xit.biz.ens.model.cmm.CmmEnsFileDTO.FmcExcelUpload;
import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.spring.util.ApiWebClient;
import kr.xit.core.spring.util.ApiWebClientUtil;
import kr.xit.core.support.xlsx.StreamingReader;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
@ -51,7 +47,7 @@ public class CmmEnsFileService extends EgovAbstractServiceImpl implements ICmmEn
private final static int FMC_EXCEL_DATA_START_ROW = 3;
private final static int FMC_EXCEL_CELL_CNT = 7;
private final ApiWebClient webClient;
private final ApiWebClientUtil webClient;
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
@Override

@ -0,0 +1,24 @@
package kr.xit.ens.support.nice.service;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
/**
* <pre>
* description :
*
* packageName : kr.xit.ens.support.nice.service
* fileName : INiceCiService
* author : limju
* date : 2023-09-06
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-06 limju
*
* </pre>
*/
public interface INiceCiService {
TokenResponse generateToken(final TokenRequest reqDTO);
TokenResponse revokeToken(final String token);
}

@ -0,0 +1,84 @@
package kr.xit.ens.support.nice.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
import kr.xit.core.spring.util.ApiWebClientUtil;
import kr.xit.core.support.utils.JsonUtils;
import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.util.Base64Util;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* <pre>
* description :
*
* packageName : kr.xit.ens.support.nice.service
* fileName : NiceCiService
* author : limju
* date : 2023-09-06
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-06 limju
*
* </pre>
*/
@RequiredArgsConstructor
@Service
public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiService {
@Value("${contract.nice.host}")
private String HOST;
@Value("${contract.nice.client-id}")
private String CLIENT_ID;
@Value("${contract.nice.client-secret}")
private String CLIENT_SECRET;
@Value("${contract.nice.api.generate-token}")
private String API_GENERATE_TOKEN;
@Value("${contract.nice.api.revoke-token}")
private String API_REVOKE_TOKEN;
@Value("${contract.nice.api.publickey}")
private String API_PUBLICKEY;
@Value("${contract.nice.api.symmetrickey}")
private String API_SYMMETRICKEY;
@Value("${contract.nice.api.ci}")
private String API_CI;
private final ApiWebClientUtil webClient;
public TokenResponse generateToken(final TokenRequest reqDTO){
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, JsonUtils.toJson(reqDTO), TokenResponse.class, getHeaderMap());
}
public TokenResponse revokeToken(final String token){
Map<String,String> map = new HashMap<>();
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
map.put(HttpHeaders.AUTHORIZATION, String.format("Basic %s", Base64Util.encode(String.format("%s:%s:%s", token, (new Date().getTime() / 1000), this.CLIENT_SECRET))));
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, null, TokenResponse.class, getHeaderMap());
}
//-------------------------------------------------------------------------------
private Map<String,String> getHeaderMap(){
Map<String,String> map = new HashMap<>();
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
map.put(HttpHeaders.AUTHORIZATION, String.format("Basic %s", Base64Util.encode(String.format("%s:%s", this.CLIENT_ID, this.CLIENT_SECRET))));
return map;
}
}

@ -0,0 +1,54 @@
package kr.xit.ens.support.nice.web;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.xit.biz.ens.model.kakao.KkopayDocDTO.ValidTokenRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.ens.support.nice.service.INiceCiService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* <pre>
* description :
*
* packageName : kr.xit.ens.support.nice.web
* fileName : NiceCiController
* author : limju
* date : 2023-09-06
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-06 limju
*
* </pre>
*/
@Tag(name = "NiceCiController", description = "Nice CI API")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api/nice/v1")
public class NiceCiController {
private final INiceCiService service;
@Operation(summary = "기관용 토큰 발급 요청", description = "기관용 토큰 발급 요청")
@PostMapping(value = "/generateToken", produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResponseDTO<?> generateToken(
@RequestBody final TokenRequest reqDTO
) {
return ApiResponseDTO.success(service.generateToken(reqDTO));
}
@Operation(summary = "기관용 토큰 폐기", description = "기관용 토큰 폐기")
@PostMapping(value = "/revokeToken", produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResponseDTO<?> revokeToken(
@RequestParam final String accessToken
) {
return ApiResponseDTO.success(service.revokeToken(accessToken));
}
}

@ -0,0 +1,205 @@
package kr.xit.biz.ens.model.nice;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import kr.xit.biz.common.ApiConstants;
import kr.xit.core.model.IApiResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* <pre>
* description : Nice CI DTO
*
* packageName : kr.xit.biz.ens.model.nice
* fileName : NiceCiDTO
* author : limju
* date : 2023-09-06
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-06 limju
*
* </pre>
*/
public class NiceCiDTO {
/**
* <pre>
* Token(50 )
* url : /digital/niceid/oauth/oauth/token
* content-type : application/x-www-form-urlencoded
* Authorization : Basic + Base64Encoding(access_token:current_timestamp:client_id)
* - access_token : access_token
* - client_id : access_token client_id
* - current_timestamp
* Date currentDate = new Date();
* long current_timestamp = currentDate.getTime() /1000
* </pre>
*/
@Schema(name = "Token", description = "기관용 Token(50년 유효) 발급 요청 파라메터 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class TokenRequest {
/**
* default
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "scope", example = "default")
@NotBlank(message = "scope는 필수입니다")
private String scope;
/**
* clinet_credentials
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "grant_type", example = "clinet_credentials")
@NotBlank(message = "grant_type은 필수입니다")
private String grant_type;
}
/**
* <pre>
* Token(50 )
* url : /digital/niceid/oauth/oauth/token
* content-type : application/json
* </pre>
*/
@Schema(name = "TokenResponse", description = "기관용 Token(50년 유효) 발급 요청 결과 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class TokenResponse implements IApiResponse {
@Schema(requiredMode = RequiredMode.REQUIRED)
private DataHeader dataHeader;
@Schema(requiredMode = RequiredMode.REQUIRED)
private DataBody dataBody;
}
/**
* <pre>
* Token
*
* url : /digital/niceid/oauth/oauth/token/revokeById
* Authorization : Basic + Base64Encoding(access_token:current_timestamp:client_id)
* - access_token : access_token
* - client_id : access_token client_id
* - current_timestamp
* Date currentDate = new Date();
* long current_timestamp = currentDate.getTime() /1000
* </pre>
*/
@Schema(name = "TokenRevokeResponse", description = "기관용 Token 폐기 요청 결과 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class TokenRevokeResponse implements IApiResponse {
@Schema(requiredMode = RequiredMode.REQUIRED)
private DataHeader dataHeader;
}
/**
* dataHeader
*/
@Schema(name = "DataHeader", description = "TokenResponse dataHeader DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class DataHeader {
/**
*
* : 1200,
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "응답코드", example = "1200")
@NotBlank
private String GW_RSLT_CD;
/**
*
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "응답메세지", example = "오류없음")
@NotBlank
private String GW_RSLT_MSG;
/**
* TRAN_ID
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "TRAN_ID", example = "20230906120000")
private String TRAN_ID;
}
/**
* dataHeader
*/
@Schema(name = "DataBody", description = "TokenResponse dataBody DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class DataBody {
//-----------------------------------------------------------------------
// 토근 발급 요청시 필수
//-----------------------------------------------------------------------
/**
* : token
* API access_token
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "사용자 엑세스 토큰 값", example = " ")
@NotBlank
private String access_token;
/**
* token_type : token
* bearer
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "token_type", example = "bearer")
@NotBlank
private String token_type;
/**
* access () : token
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "access 토큰 만료 시간(초)", example = "1.57698305E9")
@NotBlank
private int expires_in;
/**
* scope : token
* : default
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "요청한 scope 값", example = "default")
@NotBlank
private String scope;
//-----------------------------------------------------------------------
// 토큰 폐기 요청시 필수
//-----------------------------------------------------------------------
/**
* token
* true or false
*/
@Schema(requiredMode = RequiredMode.AUTO)
@NotBlank
private boolean result;
}
}

@ -0,0 +1,52 @@
package kr.xit.core.support.utils;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import kr.xit.core.exception.BizRuntimeException;
/**
* <pre>
* description :
*
* packageName : kr.xit.core.support.utils
* fileName : SecureUtils
* author : limju
* date : 2023-09-06
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-06 limju
*
* </pre>
*/
public class SecureUtils {
/**
* sha256
*
* @param text
* @return
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static String hexSha256(String text) {
StringBuffer sbuf = new StringBuffer();
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-256");
mDigest.update(text.getBytes());
byte[] msgStr = mDigest.digest();
for(int i = 0; i < msgStr.length; i++) {
byte tmpStrByte = msgStr[i];
String tmpEncTxt = Integer.toString((tmpStrByte & 0xff) + 0x100, 16).substring(1);
sbuf.append(tmpEncTxt);
}
} catch (NoSuchAlgorithmException nae){
throw BizRuntimeException.create(nae.getMessage());
}
return sbuf.toString();
}
}
Loading…
Cancel
Save