refactor: API에서 batch모듈 제거

dev
gitea-관리자 1 year ago
parent 6d05fcaf45
commit dccf7a2fb7

@ -83,6 +83,19 @@
<artifactId>spring-boot-starter-jta-atomikos</artifactId> <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency> </dependency>
<!-- cache: caffeine -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<!-- <version>3.1.1</version>-->
</dependency>
<!-- cache: caffeine -->
</dependencies> </dependencies>

@ -1,38 +0,0 @@
package kr.xit.core.biz.batch;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
/**
* <pre>
* description : Spring Boot 2.0.x
* => Job
* Spring Boot 2.1.0
* => Job
* --> run.id
* .incrementer(new RunIdIncrementer()) -> .incrementer(new UniqueRunIdIncrementer())
*
* packageName : kr.xit.core.biz.batch
* fileName : CustomRunIdIncrementer
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
public class CustomRunIdIncrementer extends RunIdIncrementer {
private static final String RUN_ID = "run.id";
@Override
public JobParameters getNext(JobParameters parameters) {
JobParameters params = (parameters == null) ? new JobParameters() : parameters;
return new JobParametersBuilder()
.addLong(RUN_ID, params.getLong(RUN_ID, 0L) + 1)
.toJobParameters();
}
}

@ -1,37 +0,0 @@
package kr.xit.core.biz.batch;
import java.util.List;
/**
* <pre>
* description : ItemReaderAdapter List<T> read()
* -> ItemReader read
* ItemReaderAdapter targetObject
* -> ItemReaderAdapter.setTargetObject(Object o)
* : new ListReader<>(- )
* : new ListReader<>(loggingService.findLogging(null))
* packageName : kr.xit.core.biz.batch
* fileName : ListReader
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
public class ListReader<T> {
private List<T> list;
public ListReader(List<T> list){
this.list = list;
}
public T read() {
if(list.isEmpty()){
return null;
}
return list.remove(0);
}
}

@ -1,48 +0,0 @@
package kr.xit.core.biz.batch.listener;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : Chunk
*
* packageName : kr.xit.core.biz.batch.listener
* fileName : CustomChunkListener
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
@Slf4j
@Component
public class CustomChunkListener {
@Bean
public ChunkListener chunkListener() {
return new ChunkListener() {
@Override
public void beforeChunk(ChunkContext context) {
log.info("↓ Chunk start");
}
@Override
public void afterChunk(ChunkContext context) {
log.info("↑ Chunk end");
}
@Override
public void afterChunkError(ChunkContext context) {
// Do nothing
}
};
}
}

@ -1,29 +0,0 @@
package kr.xit.core.biz.batch.listener;
import java.util.List;
import org.springframework.batch.core.listener.ItemListenerSupport;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CustomItemListner extends ItemListenerSupport {
public void onReadError(Exception ex) {
log.error("onReadError", ex);
}
@Override
public void onProcessError(Object item, Exception e) {
log.error("onProcessError", e);
super.onProcessError(item, e);
}
@Override
public void onWriteError(Exception ex, List item) {
log.error("onWriteError", ex);
}
}

@ -1,41 +0,0 @@
package kr.xit.core.biz.batch.listener;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : Job
*
* packageName : kr.xit.core.biz.batch.listener
* fileName : CustomJobListener
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
@Slf4j
public class CustomJobListener extends JobExecutionListenerSupport {
@Override
public void beforeJob(JobExecution jobExecution) {
log.info("\n");
log.info("====================================================");
log.info("========== ↓ [{}] Job start ===========", jobExecution.getJobInstance().getJobName());
log.info("====================================================");
}
@Override
public void afterJob(JobExecution jobExecution) {
log.info("===============================================================");
log.info("========== ↑ [{}] Job end :: {} ==========", jobExecution.getJobInstance().getJobName(), jobExecution.getStatus());
log.info("===============================================================");
log.info("\n");
}
}

@ -1,40 +0,0 @@
package kr.xit.core.biz.batch.listener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : step
*
* packageName : kr.xit.core.biz.batch.listener
* fileName : CustomStepListener
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
@Slf4j
public class CustomStepListener extends StepExecutionListenerSupport {
@Override
public void beforeStep(StepExecution stepExecution) {
log.info("##### ↓ [{}] Step start", stepExecution.getStepName());
//log.info("##### [{}-{}] Step is start", stepExecution.getJobExecution().getJobInstance().getJobName(), stepExecution.getStepName());
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
log.info("##### ↑ [{}] Step end :: {}", stepExecution.getStepName(), stepExecution.getStatus());
//log.info("##### [{}-{}] Step is completed {}", stepExecution.getJobExecution().getJobInstance().getJobName(), stepExecution.getStepName(), stepExecution.getStatus());
return stepExecution.getExitStatus();
}
}

@ -1,16 +0,0 @@
package kr.xit.core.biz.batch.listener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
public class NoWorkFoundStepListener extends StepExecutionListenerSupport {
public ExitStatus afterStep(StepExecution stepExecution) {
if (stepExecution.getReadCount() == 0) {
return ExitStatus.FAILED;
}
return null;
}
}

@ -1,32 +0,0 @@
package kr.xit.core.biz.batch.mapper;
import java.util.Optional;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
/**
* <pre>
* description :
*
* packageName : kr.xit.core.biz.batch.mapper
* fileName : IBatchCmmMapper
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
*/
@Mapper
public interface IBatchCmmMapper {
Optional<BatchCmmDTO> selectBatchLockByInstanceId(final String instanceId);
int insertBatchLock(final BatchCmmDTO dto);
int updateBatchLock(final BatchCmmDTO dto);
int insertBatchLog(final BatchCmmDTO dto);
int updateBatchLog(final BatchCmmDTO dto);
}

@ -1,68 +0,0 @@
package kr.xit.core.biz.batch.model;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <pre>
* description :
*
* packageName : kr.xit.core.biz.batch.model
* fileName : BatchCmmDTO
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
* 2023-06-15 limju
*
* </pre>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BatchCmmDTO {
/**
* ID
*/
private String batchLogId;
/**
* ID
*/
private String instanceId;
/**
* API trace ID
*/
private String traceId;
/**
*
*/
private String result;
/**
*
*/
private String message;
/**
*
*/
private String useYn;
//@Convert(converter = Jsr310.LocalDateTimeConverter.class)
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss.SSS")
private LocalDateTime registDt;
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss.SSS")
private LocalDateTime updateDt;
}

@ -1,65 +0,0 @@
package kr.xit.core.biz.batch.service;
import java.util.Optional;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import kr.xit.core.biz.batch.mapper.IBatchCmmMapper;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
/**
* <pre>
* description :
*
* packageName : kr.xit.core.biz.service
* fileName : BatchLockService
* author : limju
* date : 2023-05-18
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-18 limju
*
* </pre>
*/
@Service
public class BatchCmmService extends EgovAbstractServiceImpl implements IBatchCmmService {
private final IBatchCmmMapper mapper;
public BatchCmmService(IBatchCmmMapper mapper) {
this.mapper = mapper;
}
@Override
@Transactional(readOnly = true)
public Optional<BatchCmmDTO> findById(final String instanceId) {
return mapper.selectBatchLockByInstanceId(instanceId);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addBatchLock(final BatchCmmDTO dto) {
mapper.insertBatchLock(dto);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void modifyBatchLock(final BatchCmmDTO dto) {
mapper.updateBatchLock(dto);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addBatchLog(final BatchCmmDTO dto) {
mapper.insertBatchLog(dto);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void modifyBatchLog(final BatchCmmDTO dto) {
mapper.updateBatchLog(dto);
}
}

@ -1,29 +0,0 @@
package kr.xit.core.biz.batch.service;
import java.util.Optional;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
/**
* <pre>
* description :
*
* packageName : kr.xit.core.biz.service
* fileName : IBatchCmmService
* author : limju
* date : 2023-05-18
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-18 limju
*
* </pre>
*/
public interface IBatchCmmService {
Optional<BatchCmmDTO> findById(final String instanceId);
void addBatchLock(final BatchCmmDTO dto);
void modifyBatchLock(final BatchCmmDTO dto);
void addBatchLog(final BatchCmmDTO dto);
void modifyBatchLog(final BatchCmmDTO dto);
}

@ -1,57 +0,0 @@
package kr.xit.core.biz.batch.task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : lock table update
* (use_yn) (N)
*
* packageName : kr.xit.core.biz.batch.task
* fileName : BatchEndTasklet
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
* @see kr.xit.core.aop.TraceLoggerAspect
*/
@Slf4j
public class BatchEndTasklet implements Tasklet {
private final IBatchCmmService batchCmmService;
public BatchEndTasklet(IBatchCmmService batchCmmService) {
this.batchCmmService = batchCmmService;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
String jobName = contribution.getStepExecution().getJobExecution().getJobInstance().getJobName();
contribution.setExitStatus(ExitStatus.COMPLETED);
BatchCmmDTO dto = BatchCmmDTO
.builder()
.instanceId(jobName)
.result(contribution.getExitStatus().getExitCode())
.useYn("N")
.batchLogId(MDC.get("batch_log_id"))
.traceId(StringUtils.defaultString(MDC.get("request_trace_id"), MDC.get("request_trace_batch_id")))
.build();
log.info("@@@@@@@@@@@@@{}", MDC.getCopyOfContextMap());
batchCmmService.modifyBatchLock(dto);
batchCmmService.modifyBatchLog(dto);
return RepeatStatus.FINISHED;
}
}

@ -1,59 +0,0 @@
package kr.xit.core.biz.batch.task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : lock table update
* (use_yn) (N)
*
* packageName : kr.xit.core.biz.batch.task
* fileName : BatchEndTasklet
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
*
* </pre>
* @see kr.xit.core.aop.TraceLoggerAspect
*/
@Slf4j
public class BatchFailEndTasklet implements Tasklet {
private final IBatchCmmService batchCmmService;
public BatchFailEndTasklet(IBatchCmmService batchCmmService) {
this.batchCmmService = batchCmmService;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
String jobName = contribution.getStepExecution().getJobExecution().getJobInstance().getJobName();
contribution.setExitStatus(ExitStatus.FAILED);
BatchCmmDTO dto = BatchCmmDTO
.builder()
.instanceId(jobName)
.result(contribution.getExitStatus().getExitCode())
.useYn("N")
.batchLogId(MDC.get("batch_log_id"))
.traceId(StringUtils.defaultString(MDC.get("request_trace_id"), MDC.get("request_trace_batch_id")))
.build();
log.info("@@@@@@@@@@@@@{}", MDC.getCopyOfContextMap());
batchCmmService.modifyBatchLock(dto);
batchCmmService.modifyBatchLog(dto);
return RepeatStatus.FINISHED;
}
}

@ -1,75 +0,0 @@
package kr.xit.core.biz.batch.task;
import org.slf4j.MDC;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import kr.xit.core.biz.batch.model.BatchCmmDTO;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import kr.xit.core.support.utils.Checks;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : lock table insert or update
* (use_yn) (Y) ()
* -> (Y)
*
* packageName : kr.xit.core.biz.batch.task
* fileName : BatchStartTasklet
* author : limju
* date : 2023-05-16
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-16 limju
* 2023-08-21 limju lock release :
* </pre>
* @see kr.xit.core.aop.TraceLoggerAspect
*/
@Slf4j
public class BatchStartTasklet implements Tasklet {
private final IBatchCmmService batchCmmService;
public BatchStartTasklet(IBatchCmmService batchCmmService) {
this.batchCmmService = batchCmmService;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
String jobName = contribution.getStepExecution().getJobExecution().getJobInstance().getJobName();
BatchCmmDTO dto = batchCmmService.findById(jobName)
.orElseGet(()-> BatchCmmDTO
.builder()
.build());
if(Checks.isEmpty(dto.getInstanceId())){
dto.setInstanceId(jobName);
dto.setResult(null);
dto.setUseYn("Y");
batchCmmService.addBatchLock(dto);
batchCmmService.addBatchLog(dto);
MDC.put("batch_log_id", dto.getBatchLogId());
}else{
if("Y".equals(dto.getUseYn())){
log.error("======= [{}] 배치 실행(사용) 중으로 종료 =======", jobName);
contribution.setExitStatus(ExitStatus.FAILED);
dto.setResult("배치 실행(사용) 중으로 종료");
// lock이 걸린 경우 reset : 2023-08-21
dto.setUseYn("N");
batchCmmService.modifyBatchLock(dto);
batchCmmService.addBatchLog(dto);
}else{
dto.setUseYn("Y");
dto.setResult(null);
batchCmmService.modifyBatchLock(dto);
batchCmmService.addBatchLog(dto);
MDC.put("batch_log_id", dto.getBatchLogId());
}
}
return RepeatStatus.FINISHED;
}
}

@ -38,9 +38,9 @@ import javax.sql.DataSource;
@Configuration @Configuration
@MapperScan( @MapperScan(
basePackages = { basePackages = {
"kr.xit.core.biz.mapper", "kr.xit.core.**.mapper",
"kr.xit.core.biz.batch.mapper", "kr.xit.biz.**.mapper",
"kr.xit.biz.ens.mapper", "kr.xit.ens.**.mapper",
}, },
sqlSessionFactoryRef = Constants.PRIMARY_SQL_SESSION sqlSessionFactoryRef = Constants.PRIMARY_SQL_SESSION
) )

@ -4,7 +4,6 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import kr.xit.core.spring.config.support.ApplicationContextProvider; import kr.xit.core.spring.config.support.ApplicationContextProvider;
import kr.xit.core.support.slack.SlackWebhookPush; import kr.xit.core.support.slack.SlackWebhookPush;

@ -0,0 +1,27 @@
package kr.xit.ens.support.cmm.mapper;
import kr.xit.biz.ens.model.nice.NiceCiDTO.CrtfInfo;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
/**
* <pre>
* description : mapper
* - cache: CaffeineCache use
*
* packageName : kr.xit.ens.support.cmm.mapper
* fileName : ICmmEnsMapper
* author : limju
* date : 2023-09-12
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-12 limju
*
* </pre>
*/
@Mapper
public interface ICmmEnsMapper {
CrtfInfo selectNiceCrtfInfo(final CrtfInfo dto);
int updateNiceCrtfPublickey(final CrtfInfo dto);
}

@ -0,0 +1,60 @@
package kr.xit.ens.support.cmm.service;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import kr.xit.biz.ens.model.nice.NiceCiDTO.CrtfInfo;
import kr.xit.ens.support.cmm.mapper.ICmmEnsMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@RequiredArgsConstructor
@Service
public class CmmEnsCacheService implements ICmmEnsCacheService {
private final ICmmEnsMapper cmmEnsMapper;
private final CacheManager cacheManager;
/**
* GET Nice CI
* @param signguCode
* @param ffnlgCode
* @param clientId
* @return CrtfInfo
*/
@Transactional(readOnly = true)
@Cacheable(cacheNames = "niceCrtfInfo", keyGenerator = "cacheKeyGenerator")
public CrtfInfo getNiceCrtfInfoCache(final String signguCode, final String ffnlgCode, final String clientId) {
return cmmEnsMapper.selectNiceCrtfInfo(CrtfInfo.builder()
.signguCode(signguCode)
.ffnlgCode(ffnlgCode)
.clientId(clientId)
.build());
}
@Transactional(readOnly = true)
@CacheEvict(cacheNames = "niceCrtfInfo", keyGenerator = "cacheKeyGenerator")
public void removeNiceCrtfInfoCache(final String signguCode, final String ffnlgCode, final String clientId) {
}
public void logCache(){
if(!log.isDebugEnabled()) {
for(String cacheName : cacheManager.getCacheNames()) {
Cache cache = ((CaffeineCache) cacheManager.getCache(cacheName)).getNativeCache();
for(Object key : cache.asMap().keySet()) {
Object value = cache.getIfPresent(key);
log.info("key: {} - value: {}", key, value.toString());
}
CacheStats stats = cache.stats();
log.info("cache '{}' - stats : {}", cacheName, stats.toString());
}
}
}
}

@ -0,0 +1,28 @@
package kr.xit.ens.support.cmm.service;
import kr.xit.biz.ens.model.nice.NiceCiDTO.CrtfInfo;
import org.springframework.cache.annotation.CacheEvict;
/**
* <pre>
* description : CaffeineCache
*
* packageName : kr.xit.ens.support.cmm.service
* fileName : ICmmEnsCacheService
* author : limju
* date : 2023-09-12
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-09-12 limju
*
* </pre>
*/
public interface ICmmEnsCacheService {
CrtfInfo getNiceCrtfInfoCache(final String signguCode, final String ffnlgCode, final String clientId);
void removeNiceCrtfInfoCache(final String signguCode, final String ffnlgCode, final String clientId);
void logCache();
}

@ -2,6 +2,9 @@ package kr.xit.ens.support.nice.service;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResponse; import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResponse;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegResDataBody;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegResponse;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse; import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
@ -37,4 +40,12 @@ public interface INiceCiService {
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// 공개키(Publickey) // 공개키(Publickey)
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
SymmetrickeyRegResponse requestRegSymmetrickey(SymmetrickeyRegRequest reqDTO);
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
} }

@ -1,6 +1,8 @@
package kr.xit.ens.support.nice.service; package kr.xit.ens.support.nice.service;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -24,13 +26,13 @@ import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.spring.annotation.TraceLogging; import kr.xit.core.spring.annotation.TraceLogging;
import kr.xit.core.spring.util.ApiWebClientUtil; import kr.xit.core.spring.util.ApiWebClientUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.util.Base64Util;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl; import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
/** /**
* <pre> * <pre>
@ -51,12 +53,15 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class NiceCiDummyTestService extends EgovAbstractServiceImpl { public class NiceCiDummyTestService extends EgovAbstractServiceImpl {
@Value("${contract.nice.host}") @Value("${contract.nice.signgu-code}")
private String HOST; private String SIGNGU_CODE;
@Value("${contract.nice.ffnlg-code}")
private String FFNLG_CODE;
@Value("${contract.nice.client-id}") @Value("${contract.nice.client-id}")
private String CLIENT_ID; private String CLIENT_ID;
@Value("${contract.nice.client-secret}")
private String CLIENT_SECRET; @Value("${contract.nice.host}")
private String HOST;
@Value("${contract.nice.api.generate-token}") @Value("${contract.nice.api.generate-token}")
private String API_GENERATE_TOKEN; private String API_GENERATE_TOKEN;
@Value("${contract.nice.api.revoke-token}") @Value("${contract.nice.api.revoke-token}")
@ -88,7 +93,13 @@ public class NiceCiDummyTestService extends EgovAbstractServiceImpl {
validate(reqDTO); validate(reqDTO);
Map<String,String> map = new HashMap<>(); Map<String,String> map = new HashMap<>();
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
map.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", AUTH_TYPE_BASIC, Base64Util.encode(String.format("%s:%s", this.CLIENT_ID, this.CLIENT_SECRET)))); map.put(HttpHeaders.AUTHORIZATION,
String.format("%s %s", AUTH_TYPE_BASIC,
Base64Utils.encodeToString(
Base64Utils.encode(String.format("%s:%s", this.CLIENT_ID, "this.CLIENT_SECRET").getBytes(StandardCharsets.UTF_8))
)
)
);
return TokenResponse.builder() return TokenResponse.builder()
.dataHeader(ResponseDataHeader.builder() .dataHeader(ResponseDataHeader.builder()
@ -170,11 +181,12 @@ public class NiceCiDummyTestService extends EgovAbstractServiceImpl {
HttpHeaders.AUTHORIZATION, HttpHeaders.AUTHORIZATION,
String.format("%s %s", String.format("%s %s",
type, type,
Base64Util.encode( Base64Utils.encodeToString(
String.format("%s:%s:%s", Base64Utils.encode(
"accessToken", String.format("%s:%s:%s",
(new Date().getTime() / 1000), "accessToken",
this.CLIENT_ID) (new Date().getTime() / 1000),
this.CLIENT_ID).getBytes(StandardCharsets.UTF_8))
) )
) )
); );

@ -1,42 +1,54 @@
package kr.xit.ens.support.nice.service; 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.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolation;
import javax.validation.Validation; import javax.validation.Validation;
import javax.validation.Validator; import javax.validation.Validator;
import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses; import kr.xit.biz.ens.model.nice.NiceCiDTO.CrtfInfo;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyReqDataBody;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResDataBody;
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResponse; import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResponse;
import kr.xit.biz.ens.model.nice.NiceCiDTO.ResponseDataHeader; import kr.xit.biz.ens.model.nice.NiceCiDTO.RequestDataHeader;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegResponse;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResDataBody;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse; import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.spring.annotation.TraceLogging; import kr.xit.core.spring.annotation.TraceLogging;
import kr.xit.core.spring.util.ApiWebClientUtil; import kr.xit.core.spring.util.ApiWebClientUtil;
import kr.xit.core.support.utils.DateUtils;
import kr.xit.core.support.utils.JsonUtils; import kr.xit.core.support.utils.JsonUtils;
import kr.xit.ens.support.cmm.mapper.ICmmEnsMapper;
import kr.xit.ens.support.cmm.service.CmmEnsCacheService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.util.Base64Util; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl; import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.Base64Utils;
import org.springframework.util.MultiValueMap;
/** /**
* <pre> * <pre>
@ -54,15 +66,19 @@ import org.springframework.util.MultiValueMap;
* </pre> * </pre>
*/ */
//FIXME : client_id, client_secret, access_token DB 처리후 반영 필요 //FIXME : client_id, client_secret, access_token DB 처리후 반영 필요
@Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiService { public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiService {
@Value("${contract.nice.host}") @Value("${contract.nice.signgu-code}")
private String HOST; private String SIGNGU_CODE;
@Value("${contract.nice.ffnlg-code}")
private String FFNLG_CODE;
@Value("${contract.nice.client-id}") @Value("${contract.nice.client-id}")
private String CLIENT_ID; private String CLIENT_ID;
@Value("${contract.nice.client-secret}")
private String CLIENT_SECRET; @Value("${contract.nice.host}")
private String HOST;
@Value("${contract.nice.api.generate-token}") @Value("${contract.nice.api.generate-token}")
private String API_GENERATE_TOKEN; private String API_GENERATE_TOKEN;
@Value("${contract.nice.api.revoke-token}") @Value("${contract.nice.api.revoke-token}")
@ -76,9 +92,15 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
private static final String AUTH_TYPE_BASIC = "Basic"; private static final String AUTH_TYPE_BASIC = "Basic";
private static final String AUTH_TYPE_BEARER = "bearer"; private static final String AUTH_TYPE_BEARER = "bearer";
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
private final ApiWebClientUtil webClient; private final ApiWebClientUtil webClient;
private final CmmEnsCacheService cacheService;
private final ICmmEnsMapper cmmEnsMapper;
private final CacheManager cacheManager; // Bean 주입
private static int AAA = 0;
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// 기관용 Token // 기관용 Token
@ -96,7 +118,8 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
Map<String,String> map = new HashMap<>(); Map<String,String> map = new HashMap<>();
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
map.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", AUTH_TYPE_BASIC, Base64Util.encode(String.format("%s:%s", this.CLIENT_ID, this.CLIENT_SECRET)))); map.put(HttpHeaders.AUTHORIZATION,
String.format("%s %s", AUTH_TYPE_BASIC, Base64Utils.encodeToString(Base64Utils.encode(String.format("%s:%s", this.CLIENT_ID, "this.CLIENT_SECRET").getBytes(StandardCharsets.UTF_8)))));
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, JsonUtils.toJson(reqDTO), TokenResponse.class, map); return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, JsonUtils.toJson(reqDTO), TokenResponse.class, map);
} }
@ -149,6 +172,82 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
// 공개키(Publickey) // 공개키(Publickey)
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
/**
* <pre>
* 0. cache call
* --> 5
* 1. update
* 2. cache && cache call
* @param reqDTO
* @return
* </pre>
*/
@Override
public SymmetrickeyRegResponse requestRegSymmetrickey(SymmetrickeyRegRequest reqDTO) {
validate(reqDTO);
CrtfInfo crtfInfo = getNiceCrtInfo(reqDTO.getDataHeader());
return null;
}
/**
* <pre>
* 0. cache call
* --> 5
* 1. update
* 2. cache && cache call
* @param reqHeader RequestDataHeader
* @return
* </pre>
*/
private CrtfInfo getNiceCrtInfo(RequestDataHeader reqHeader) {
CrtfInfo crtfInfo = cacheService.getNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
cacheService.logCache();
if(crtfInfo.getRemainingDays() > 5) return crtfInfo;
//FIXME::공개키 발급요청 call
PublickeyRequest pubReqDTO = PublickeyRequest.builder()
.dataHeader(reqHeader)
.dataBody(PublickeyReqDataBody.builder()
.reqDtim(DateUtils.getTodayAndNowTime("yyyyMMddHHmmss"))
.build())
.build();
PublickeyResponse pubResDTO = requestPublickey(pubReqDTO);
//FIXME::공개키 정보 갱신
PublickeyResDataBody dataBody = pubResDTO.getDataBody();
if(pubResDTO.getDataHeader().getGwRsltCd().equals("1200")
&& dataBody.getRspCd().equals("P000")
&& dataBody.getResultCd().equals("0000")){
crtfInfo.setSiteCode(dataBody.getSiteCode());
crtfInfo.setKeyVersion(dataBody.getKeyVersion());
crtfInfo.setPublicKey(dataBody.getPublicKey());
crtfInfo.setValidDtim(dataBody.getValidDtim());
cmmEnsMapper.updateNiceCrtfPublickey(crtfInfo);
}else{
//FIXME::예외처리
}
cacheService.removeNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
return cacheService.getNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
}
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
private Map<String,String> getHeaderMap(final String contentType, final String type){ private Map<String,String> getHeaderMap(final String contentType, final String type){
Map<String,String> map = new HashMap<>(); Map<String,String> map = new HashMap<>();
@ -157,11 +256,12 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
HttpHeaders.AUTHORIZATION, HttpHeaders.AUTHORIZATION,
String.format("%s %s", String.format("%s %s",
type, type,
Base64Util.encode( Base64Utils.encodeToString(
String.format("%s:%s:%s", Base64Utils.encode(
"accessToken", String.format("%s:%s:%s",
(new Date().getTime() / 1000), "accessToken",
this.CLIENT_ID) (new Date().getTime() / 1000),
this.CLIENT_ID).getBytes(StandardCharsets.UTF_8))
) )
) )
); );
@ -182,4 +282,47 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
.collect(Collectors.toList()).toString()); .collect(Collectors.toList()).toString());
} }
} }
/**
* :
*
* @param strPublicKey
* @param planText
* @return
*/
protected final String encodeString(final String strPublicKey, final String planText) { //throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] cipherEnc = Base64.getDecoder().decode(strPublicKey);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(cipherEnc);
java.security.PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytePlain = cipher.doFinal(planText.getBytes());
return Base64Utils.encodeToString(bytePlain);
} catch (NoSuchAlgorithmException|InvalidKeySpecException|NoSuchPaddingException|InvalidKeyException e){
throw BizRuntimeException.create(e.getMessage());
} catch (IllegalBlockSizeException e) {
throw BizRuntimeException.create(e.getMessage());
} catch (BadPaddingException e) {
throw BizRuntimeException.create(e.getMessage());
}
}
protected final String randomAlphaWord(int wordLength) {
Random r = new Random();
StringBuilder sb = new StringBuilder(wordLength);
for (int i = 0; i < wordLength; i++) {
char tmp = (char) ('a' + r.nextInt('z' - 'a'));
sb.append(tmp);
}
return sb.toString();
}
} }

@ -1,11 +1,9 @@
package kr.xit.ens.support.nice.web; package kr.xit.ens.support.nice.web;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.tags.Tag; 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.PublickeyRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegRequest;
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest; import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
import kr.xit.core.model.ApiResponseDTO; import kr.xit.core.model.ApiResponseDTO;
import kr.xit.ens.support.nice.service.INiceCiService; import kr.xit.ens.support.nice.service.INiceCiService;
@ -14,7 +12,6 @@ import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**
@ -90,8 +87,22 @@ public class NiceCiController {
) { ) {
return ApiResponseDTO.success(service.requestPublickey(reqDTO)); return ApiResponseDTO.success(service.requestPublickey(reqDTO));
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// 공개키(Publickey) // 공개키(Publickey)
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
@Operation(summary = "대칭키(symmetrickey) 등록 요청", description = "대칭키(symmetrickey) 등록 요청")
@PostMapping(value = "/requestRegSymmetrickey", produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResponseDTO<?> requestRegSymmetrickey(
@RequestBody final SymmetrickeyRegRequest reqDTO
) {
return ApiResponseDTO.success(service.requestRegSymmetrickey(reqDTO));
}
//--------------------------------------------------------------------------------
// 대칭키 : symmetrickey
//--------------------------------------------------------------------------------
} }

@ -25,6 +25,7 @@ import kr.xit.ens.support.nice.service.NiceCiService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -59,9 +60,9 @@ public class NiceCiDummyTestController {
// 기관용 Token // 기관용 Token
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@Operation(summary = "기관용 토큰 발급 요청", description = "기관용 토큰 발급 요청") @Operation(summary = "기관용 토큰 발급 요청", description = "기관용 토큰 발급 요청")
@PostMapping(value = "/generateToken", produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/generateToken", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResponseDTO<?> generateToken( public ApiResponseDTO<?> generateToken(
@RequestBody final TokenRequest reqDTO @ModelAttribute final TokenRequest reqDTO
) { ) {
return ApiResponseDTO.success(service.generateToken(reqDTO)); return ApiResponseDTO.success(service.generateToken(reqDTO));
} }

@ -27,8 +27,9 @@ contract:
nice: nice:
#host: http://parking.cheonan.go.kr #host: http://parking.cheonan.go.kr
host: https://svc.niceapi.co.kr:22001 host: https://svc.niceapi.co.kr:22001
client-id: "6c3eb1ff-530d-458a-9a6e-e02e3346f679" signgu-code: 11000
client-secret: "960f204ec45bb312b7ad2d6b54b984d9c353b8" ffnlg-code: 11
client-id: 6c3eb1ff-530d-458a-9a6e-e02e3346f679
api: api:
generate-token: /digital/niceid/oauth/oauth/token generate-token: /digital/niceid/oauth/oauth/token
revoke-token: /digital/niceid/oauth/oauth/token/revokeById revoke-token: /digital/niceid/oauth/oauth/token/revokeById

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.xit.biz.ens.mapper.IKkoMyDocMapper">
<select id="selectMobilePage" resultType="kr.xit.biz.ens.model.KkoMyDocDTO$MobilePageManage">
/** ens-mysql-mapper|selectMobilePage-모바일페이지콘텐트조회|julim */
SELECT tempm.sndng_detail_id
, tempm.sndng_se_code
, tempm.mobile_page_cn
FROM tb_ens_kakao_my_doc tekmd
JOIN tb_ens_mobile_page_manage tempm
ON tekmd.sndng_detail_id = tempm.sndng_detail_id
WHERE tekmd.unity_sndng_detail_id = #{external_document_uuid}
AND tekmd.document_binder_uuid = #{document_binder_uuid}
</select>
</mapper>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.xit.biz.ens.mapper.IKkoMyDocMapper">
<select id="selectMobilePage" resultType="kr.xit.biz.ens.model.KkoMyDocDTO$MobilePageManage">
/** ens-mysql-mapper|selectMobilePage-모바일페이지콘텐트조회|julim */
SELECT tempm.sndng_detail_id
, tempm.sndng_se_code
, tempm.mobile_page_cn
FROM tb_ens_kakao_my_doc tekmd
JOIN tb_ens_mobile_page_manage tempm
ON tekmd.sndng_detail_id = tempm.sndng_detail_id
WHERE tekmd.unity_sndng_detail_id = #{external_document_uuid}
AND tekmd.document_binder_uuid = #{document_binder_uuid}
</select>
</mapper>

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.xit.core.biz.batch.mapper.IBatchCmmMapper">
<select id="selectBatchLockByInstanceId" resultType="kr.xit.core.biz.batch.model.BatchCmmDTO">
/** cmm-batch-mapper|findById-배치실행상태조회|julim */
SELECT instance_id
, use_yn
FROM tb_cmm_batch_lock
WHERE instance_id = #{instanceId}
-- FOR UPDATE
</select>
<insert id="insertBatchLock">
/** cmm-batch-mapper|insertBatchLock-배치락 데이타 생성|julim */
INSERT INTO tb_cmm_batch_lock (
instance_id,
regist_dt,
use_yn
) VALUES (
#{instanceId},
NOW(3),
#{useYn}
)
</insert>
<insert id="updateBatchLock">
/** cmm-batch-mapper|updateBatchLock-배치 실행 상태 및 결과 반영|julim */
UPDATE tb_cmm_batch_lock
SET result = #{result}
, use_yn = #{useYn}
, updt_dt = NOW(3)
WHERE instance_id = #{instanceId}
</insert>
<insert id="insertBatchLog">
/** cmm-batch-mapper|insertBatchLog-배치 로그 데이타 생성|julim */
<selectKey keyProperty="batchLogId" resultType="string" order="BEFORE">
SELECT LPAD(NEXTVAL(tb_cmm_batch_log_seq), 20, '0')
</selectKey>
INSERT INTO tb_cmm_batch_log (
batch_log_id,
instance_id,
trace_id,
result,
message,
regist_dt
) VALUES (
#{batchLogId},
#{instanceId},
#{traceId},
#{result},
#{message},
NOW(3)
)
</insert>
<insert id="updateBatchLog">
/** cmm-batch-mapper|updateBatchLog-배치 결과 반영|julim */
UPDATE tb_cmm_batch_log
SET trace_id = IFNULL(#{traceId}, trace_id)
, result = IFNULL(#{result}, result)
, message = IFNULL(SUBSTRING(#{message}, 1, 100), message)
, updt_dt = NOW(3)
WHERE batch_log_id = #{batchLogId}
</insert>
</mapper>

@ -38,10 +38,8 @@ import javax.sql.DataSource;
@Configuration @Configuration
@MapperScan( @MapperScan(
basePackages = { basePackages = {
"kr.xit.core.biz.mapper", "kr.xit.core.**.mapper",
"kr.xit.core.biz.batch.mapper", "kr.xit.biz.**.mapper",
"kr.xit.biz.ens.mapper",
"kr.xit.biz.pni.mapper"
}, },
sqlSessionFactoryRef = Constants.PRIMARY_SQL_SESSION sqlSessionFactoryRef = Constants.PRIMARY_SQL_SESSION
) )

@ -1,17 +1,12 @@
package kr.xit.core.biz.model; package kr.xit.biz.common;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
/** /**

@ -8,12 +8,17 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import kr.xit.biz.common.AuditFields;
import kr.xit.core.model.IApiResponse; import kr.xit.core.model.IApiResponse;
import kr.xit.core.support.utils.JsonUtils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Builder.Default; import lombok.Builder.Default;
@ -197,10 +202,10 @@ public class NiceCiDTO {
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
/** /**
* <pre> * <pre>
* * (publickey)
* </pre> * </pre>
*/ */
@Schema(name = "PublickeyRequest", description = "공개키 요청 파라메터 DTO") @Schema(name = "PublickeyRequest", description = "공개키(publickey) 요청 파라메터 DTO")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -218,10 +223,10 @@ public class NiceCiDTO {
/** /**
* <pre> * <pre>
* * (publickey)
* </pre> * </pre>
*/ */
@Schema(name = "PublickeyResponse", description = "공개키 발급 요청 결과 DTO") @Schema(name = "PublickeyResponse", description = "공개키(publickey) 발급 요청 결과 DTO")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -239,11 +244,11 @@ public class NiceCiDTO {
/** /**
* <pre> * <pre>
* dataBody DTO * (publickey) dataBody DTO
* Json data : SNAKE_CASE (req_dtim <-> reqDtim) * Json data : SNAKE_CASE (req_dtim <-> reqDtim)
* </pre> * </pre>
*/ */
@Schema(name = "PublickeyReqDataBody", description = "공개키 요청 dataBody DTO") @Schema(name = "PublickeyReqDataBody", description = "공개키(publickey) 요청 dataBody DTO")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -255,17 +260,17 @@ public class NiceCiDTO {
* (YYYYMMDDHH24MISS) * (YYYYMMDDHH24MISS)
*/ */
@Schema(requiredMode = RequiredMode.REQUIRED, title = "공개키 요청일시", example = "2023090612122259") @Schema(requiredMode = RequiredMode.REQUIRED, title = "공개키 요청일시", example = "2023090612122259")
@Size(min = 16, max = 16, message = "요청일시(req_dtim)는 필수 입니다(16자리)") @Size(min = 14, max = 14, message = "요청일시(req_dtim)는 필수 입니다(14자리)")
private String reqDtim; private String reqDtim;
} }
/** /**
* <pre> * <pre>
* dataBody DTO * (publickey) dataBody DTO
* Json data : SNAKE_CASE (rsp_cd <-> rspCd) * Json data : SNAKE_CASE (rsp_cd <-> rspCd)
* </pre> * </pre>
*/ */
@Schema(name = "PublickeyResDataBody", description = "공개키 요청 응답 dataBody DTO") @Schema(name = "PublickeyResDataBody", description = "공개키(publickey) 요청 응답 dataBody DTO")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -337,11 +342,154 @@ public class NiceCiDTO {
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// 대칭키 : publickey // 대칭키 : symmetrickey
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
/**
* <pre>
* (symmetrickey)
* </pre>
*/
@Schema(name = "SymmetrickeyRegRequest", description = "대칭키(symmetrickey) 등록 요청 파라메터 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public static class SymmetrickeyRegRequest {
@Schema(requiredMode = RequiredMode.REQUIRED)
@Valid
private RequestDataHeader dataHeader;
@Schema(requiredMode = RequiredMode.REQUIRED)
@Valid
private SymmetrickeyRegReqDataBody dataBody;
}
/**
* <pre>
* (symmetrickey)
* </pre>
*/
@Schema(name = "SymmetrickeyRegResponse", description = "대칭키(symmetrickey) 등록 요청 결과 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public static class SymmetrickeyRegResponse implements IApiResponse {
@Schema(requiredMode = RequiredMode.REQUIRED)
@Valid
private ResponseDataHeader dataHeader;
@Schema(requiredMode = RequiredMode.REQUIRED)
@Valid
private SymmetrickeyRegResDataBody dataBody;
}
/**
* <pre>
* (symmetrickey) dataBody DTO
* Json data : SNAKE_CASE (req_dtim <-> reqDtim)
* </pre>
*/
@Schema(name = "SymmetrickeyRegReqDataBody", description = "대칭키(symmetrickey) 등록 요청 dataBody DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class SymmetrickeyRegReqDataBody {
/**
* </pre>
*
* </pre>
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "공개키버전", example = "20210121ca8c1612-2c2d-IPaa-aad1-xxxxxxxxxxxx")
@Size(min = 1, max = 50, message = "공개키버전은 필수 입니다")
private String pubkeyVersion;
/**
* <pre>
* json( )
* : RSA/ECB/PKCS1Padding, X509EncodedKeySpec , Base64 Encoding
* site_code - 16 :
* request_no - 30 :
* key - 32 : KEY
* 32byte AES256 bits, 16byte AES128 bits
* NICE KEY 6
* iv - 16 : Inital Vector
* hmac_key - 32 : HMAC KEY
* </pre>
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "json암호화값(회원사에서 생성한 대칭키를 공개키로 암호화한 값)", example = "SDFWASDFASDFSDFASDFASDFASD=")
@Size(min = 1, max = 512, message = "대칭키(암호화)는 필수 입니다")
private String symkeyRegInfo;
}
/**
* <pre>
* (symmetrickey) dataBody DTO
* Json data : SNAKE_CASE (rsp_cd <-> rspCd)
* </pre>
*/
@Schema(name = "SymmetrickeyRegResDataBody", description = "대칭키(symmetrickey) 등록 요청 응답 dataBody DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(Include.NON_EMPTY)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class SymmetrickeyRegResDataBody {
/**
* dataBody (P000 , ) : 8
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "정상처리 여부", example = "P000")
private String rspCd;
/**
* <pre>
* rsp_cd "EAPI"
* 200
* </pre>
*/
@Schema(requiredMode = RequiredMode.REQUIRED, title = "상세 메세지", example = " ")
private String rspMsg;
/**
* <pre>
* rsp_cd P000 : 4
* - 0000:
* - 0001:
* - 0002:
* - 0003:
* - 0004:
* - 0005: (key_version, key_info )
* - 0006:
* - 0007: key ( Key )
* - 0008:
* - 0099:
* </pre>
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "상세 결과코드", example = "0000")
private String resultCd;
/**
* <pre>
* JSON
* -
* - result_cd 0000, 0007
* cur_symkey_version - 50 :
* cur_valid_dtim - 14 : (YYYYMMDDHH24MISS)
* bef_symkey_version - 50 :
* bef_valid_dtim - 14 : (YYYYMMDDHH24MISS)
* </pre>
*/
@Schema(requiredMode = RequiredMode.AUTO, title = "사이트 코드", example = " ")
private String symkeyStatInfo;
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// 공개키 : publickey // 대칭키 : symmetrickey
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -433,4 +581,93 @@ public class NiceCiDTO {
public String genSymkeyRegInfo() {
/*
final String requestNo = createRequestNo();
final String key = this.createKey();
final String iv = this.createIv();
final String hmacKey = this.createHmacKey();
*/
Map<String, String> m = new HashMap<>();
/*m.put("site_code", siteCode);
m.put("request_no", requestNo);
m.put("key", key);
m.put("iv", iv);
m.put("hmac_key", hmacKey);*/
final String jsonStr = JsonUtils.toJson(m);
//final String jsonStr = this.createMessage(pubkeyVersion, encSymkeyRegInfo(jsonStr, publicKey));
return JsonUtils.toJson(m);
}
/**
* Nice DTO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public static class CrtfInfo extends AuditFields implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private String signguCode;
/**
*
*/
private String ffnlgCode;
/**
*
*/
private String clientId;
/**
* App Security code
*/
private String clientSecret;
/**
*
*/
private String productId;
/**
* access token
*/
private String accessToken;
/**
* access token ()
*/
private long expiresIn;
/**
* token type-bearer
*/
private String tokenType;
/**
* token scope-default
*/
private String scope;
/**
* site code
*/
private String siteCode;
/**
*
*/
private String keyVersion;
/**
*
*/
private String publicKey;
/**
*
*/
private String validDtim;
/**
*
*/
private int remainingDays;
}
} }

@ -1,9 +1,20 @@
package kr.xit.core.support.utils; package kr.xit.core.support.utils;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.exception.BizRuntimeException;
import org.springframework.util.Base64Utils;
/** /**
* <pre> * <pre>
@ -49,4 +60,5 @@ public class SecureUtils {
} }
return sbuf.toString(); return sbuf.toString();
} }
} }

Loading…
Cancel
Save