Compare commits

...

1 Commits

Author SHA1 Message Date
minkyu1128 b636bd7ae6 feat: 네이버페이 간편결제 서비스 구축
+ 결제 process 변경
+ 미사용 클래스 삭제
+ 클래스 패키지경로 편집
2 years ago

@ -49,6 +49,7 @@
${package.include.base}
WEB-INF/classes/**/ens/batch/**,
WEB-INF/classes/**/ens/modules/**,
<!-- WEB-INF/classes/**/ens/biz/iup/**,-->
WEB-INF/classes/application-local*.yml,
</packageIncludesByProfile>
<packageExcludesByProfile>
@ -157,10 +158,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.springframework.boot</groupId> -->
<!-- <artifactId>spring-boot-starter-security</artifactId> -->
<!-- </dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>

@ -1,12 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
@Getter
@Schema(name = "IupAlimtalkReqVO")
public class IupAlimtalkReqVO {
@Schema(required = true, title = "연계입수 아이디", example = " ")
private Long lnkInputId;
}

@ -1,38 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.mq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.kafka.annotation.KafkaListener;
import javax.annotation.Resource;
import java.io.IOException;
@Slf4j
//@Component
@Profile("prod-iup")
public class IupAlimtalkConsumer {
@Resource(name = "iupAlimtalkMakerLegacy")
// @Autowired
// private IupAlimtalkMakerLegacy iupAlimtalkMaker;
/**
*
* @param message
* @throws IOException
*/
@SuppressWarnings("unchecked")
@KafkaListener(topics = "iup-kkoalimtalk-makereq", groupId = "group-id-ens")
public void subMakeReq(String message) throws IOException {
log.info("[iup-kkoalimtalk-makereq] sub message : " + message);
try {
Long sendMastId = Long.parseLong(message);
// iupAlimtalkMaker.make(sendMastId);
} catch (Exception e) {
e.printStackTrace();
}
}
}

@ -1,28 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.mq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class IupAlimtalkProducer {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
/**
*
* @param message
*/
public void pubMakeReq(String message) {
final String topicName = "iup-kkoalimtalk-makereq";
log.info(String.format("[%s] pub message : %s", topicName, message));
this.kafkaTemplate.send(topicName, message);
}
}

@ -1,54 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.presentation;
import cokr.xit.ens.biz.iup.alimtalk.model.IupAlimtalkReqVO;
import cokr.xit.ens.biz.iup.alimtalk.service.IupAlimtalkService;
import cokr.xit.ens.core.aop.EnsResponseVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "IupAlimtalkController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class IupAlimtalkController {
private final IupAlimtalkService iupAlimtalkService;
@Operation(summary = "접수")
@PostMapping(value = "/iup/alimtalk/accept", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> accept(@RequestBody IupAlimtalkReqVO reqDTO){
EnsResponseVO responseVO = iupAlimtalkService.accept(reqDTO.getLnkInputId());
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@Operation(summary = "제작")
// @PutMapping(value = "/iup/alimtalk/re/make", produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = "/iup/alimtalk/re/make", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> reMake(@RequestBody IupAlimtalkReqVO reqDTO){
EnsResponseVO responseVO = iupAlimtalkService.reMake(reqDTO.getLnkInputId());
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@Operation(summary = "전송")
// @PutMapping(value = "/iup/alimtalk/re/send", produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = "/iup/alimtalk/re/send", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> reSend(@RequestBody IupAlimtalkReqVO reqDTO){
EnsResponseVO responseVO = iupAlimtalkService.reSend(reqDTO.getLnkInputId());
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@Operation(summary = "전송결과가져오기")
@PostMapping(value = "/iup/alimtalk/fetch", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> fetch(@RequestBody IupAlimtalkReqVO reqDTO){
EnsResponseVO responseVO = iupAlimtalkService.fetch(reqDTO.getLnkInputId());
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
}

@ -1,45 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.sched;
import cokr.xit.ens.biz.iup.alimtalk.service.IupAlimtalkService;
import cokr.xit.ens.core.aop.EnsResponseVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
@Slf4j
//@Component
//@Profile("prod-iup")
@RequiredArgsConstructor
public class IupAlimtalkScheduler {
private final IupAlimtalkService iupAlimtalkService;
/**
*
* -. IUP ENS .
*/
@Scheduled(cron = "0 */5 7-22 * * *")
public void accepted() {
EnsResponseVO responseVO = iupAlimtalkService.acceptAll();
log.info("=======================================================");
log.info("[IUP] 알림톡 접수처리 결과");
log.info(responseVO.toString());
log.info("=======================================================");
}
/**
*
* -. (/) ENS -> IUP .
*/
@Scheduled(cron = "0 */15 7-22 * * *")
public void fetched() {
EnsResponseVO responseVO = iupAlimtalkService.fetchAll();
log.info("=======================================================");
log.info("[IUP] 알림톡 전송결과 Fetch");
log.info(responseVO.toString());
log.info("=======================================================");
}
}

@ -1,164 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service;
import cokr.xit.ens.biz.iup.alimtalk.service.support.IupAlimtalkAcceptor;
import cokr.xit.ens.biz.iup.alimtalk.service.support.IupAlimtalkFetcher;
import cokr.xit.ens.biz.iup.alimtalk.service.support.IupAlimtalkMaker;
import cokr.xit.ens.biz.iup.alimtalk.service.support.IupAlimtalkSender;
import cokr.xit.ens.biz.iup.code.IupPrcsCd;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.TbInputXit;
import cokr.xit.ens.biz.iup.domain.repository.TbInputXitRepository;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.kkoalimtalk.service.event.KkoAlimtalkSendReserveEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class IupAlimtalkService {
private final TbInputXitRepository tbInputXitRepository;
private final IupAlimtalkAcceptor iupAlimtalkAcceptor;
private final IupAlimtalkMaker iupAlimtalkMaker;
private final IupAlimtalkSender iupAlimtalkSender;
private final IupAlimtalkFetcher iupAlimtalkFetcher;
private final ApplicationEventPublisher applicationEventPublisher;
/**
* (IUP -> ENS)
*/
public EnsResponseVO accept(Long lnkInputId){
try {
TbInputXit tbInputXit = tbInputXitRepository.findByPrcsCdAndSendTypeAndId(IupPrcsCd.TGRG, IupSendTypeCd.NI, lnkInputId)
.orElseThrow(()->new EnsException(EnsErrCd.ACPT404, "일치하는 자료가 없거나 \"등록(TGRG)\" 상태가 아닙니다."));
return this.accept(Arrays.asList(tbInputXit)).getResultInfo().get(0);
} catch (EnsException e){
return EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
}
}
/**
* (IUP -> ENS)
*/
public EnsResponseVO<List<EnsResponseVO>> acceptAll(){
try {
List<TbInputXit> tbInputXits = tbInputXitRepository.findAllByPrcsCdInAndSendType(Arrays.asList(IupPrcsCd.TGRG), IupSendTypeCd.NI);
if(CmmnUtil.isEmpty(tbInputXits))
throw new EnsException(EnsErrCd.ACPT404, "\"등록(TGRG)\" 상태의 자료가 없습니다.");
return this.accept(tbInputXits);
} catch (EnsException e){
return EnsResponseVO.<List<EnsResponseVO>>errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
}
}
private EnsResponseVO<List<EnsResponseVO>> accept(List<TbInputXit> tbInputXits){
iupAlimtalkAcceptor.statReady(tbInputXits.stream().map(row -> row.getLnkInputId()).collect(Collectors.toList()));
List<EnsResponseVO> resultInfo = tbInputXits.stream()
.map(row -> iupAlimtalkAcceptor.execute(row.getLnkInputId()))
.collect(Collectors.toList());
List<Long> sendMastIds = resultInfo.stream()
.filter(ensResponseVO -> EnsErrCd.OK.equals(ensResponseVO.getErrCode()))
.map(ensResponseVO -> (Long)((Map<String, Object>)ensResponseVO.getResultInfo()).get("sendMastId"))
.collect(Collectors.toList());
KkoAlimtalkSendReserveEvent event = KkoAlimtalkSendReserveEvent.builder()
.sendMastIds(sendMastIds)
.callback(() -> this.fetch(tbInputXits))
.build();
applicationEventPublisher.publishEvent(event);
return EnsResponseVO.<List<EnsResponseVO>>okBuilder().resultInfo(resultInfo).build();
}
/**
*
* @param lnkInputId
* @return
*/
public EnsResponseVO reMake(Long lnkInputId){
return iupAlimtalkMaker.execute(lnkInputId);
}
/**
*
* @param lnkInputId
* @return
*/
public EnsResponseVO reSend(Long lnkInputId){
return iupAlimtalkSender.execute(lnkInputId);
}
/**
* (/)
*/
public EnsResponseVO fetch(Long lnkInputId){
TbInputXit tbInputXit = null;
try {
tbInputXit = tbInputXitRepository.findById(lnkInputId)
.orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("[ lnkInputId %s ]와 일치하는 자료가 없습니다.", lnkInputId)));
if(!IupSendTypeCd.NI.equals(tbInputXit.getSendType()))
new EnsException(EnsErrCd.ERR404, String.format("[ lnkInputId %s ]는 인증톡 자료가 아닙니다.", lnkInputId));
} catch (EnsException e) {
return EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
}
return this.fetch(Arrays.asList(tbInputXit));
}
/**
* (/)
*/
public EnsResponseVO fetchAll(){
List<TbInputXit> tbInputXits = tbInputXitRepository.findAllByPrcsCdInAndSendType(Arrays.asList(IupPrcsCd.TGRC), IupSendTypeCd.NI);
return this.fetch(tbInputXits);
}
private EnsResponseVO fetch(List<TbInputXit> tbInputXits){
iupAlimtalkFetcher.statReady(tbInputXits.stream().map(row -> row.getLnkInputId()).collect(Collectors.toList()));
return EnsResponseVO.okBuilder()
.resultInfo(
tbInputXits.stream()
.map(row -> iupAlimtalkFetcher.execute(row.getLnkInputId()))
.collect(Collectors.toList()
)
)
.build();
}
}

@ -1,430 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service;
import cokr.xit.ens.biz.iup.billpay.service.IupBillPayApiServiceSupport;
import cokr.xit.ens.biz.iup.domain.TbEnfrcLevRciv;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfo;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfoSn;
import cokr.xit.ens.biz.iup.domain.repository.TbEnfrcLevRcivRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoSnRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.BillHist;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api.BillKkoClientApiSpec;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.code.BillKkoErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.TmpltMng;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.OrgMngRepository;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.TmpltMngRepository;
import cokr.xit.ens.modules.kkoalimtalk.domain.SendDetailKkoAlimtalk;
import cokr.xit.ens.modules.kkoalimtalk.domain.repository.SendDetailKkoAlimtalkRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@Service("iupBillPayApiService_NI")
@RequiredArgsConstructor
public class IupBillPayApiAlimtalkService extends IupBillPayApiServiceSupport {
private final SendDetailKkoAlimtalkRepository sendDetailKkoAlimtalkRepository;
private final TmpltMngRepository sendTmpltMngRepository;
private final OrgMngRepository orgMngRepository;
private final TbInputDataXitRepository tbInputDataXitRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
private final TbEnfrcLevRcivRepository tbEnfrcLevRcivRepository;
private final BillKkoClientApiSpec billKkoClientApi;
/**
*
*
* @param mParam
* @return
*/
@Transactional
public BillKkoApiRespDTO findNoticeInfo(Map<String, Object> mParam) {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
// data.get("biller_user_key");
// data.get("billed_year_month");
// data.get("ordinal");
// data.get("biller_notice_key");
Map<String, Object> parameters = (Map<String, Object>) data.get("parameters");
// data.get("user_birth");
Map<String, Object> respData = null;
BillKkoApiRespDTO respVO = null;
BillKkoErrCd kkoBillErrCd = BillKkoErrCd.OK;
final String billerUserKey = Optional.ofNullable(data.get("biller_user_key")).isPresent() ?
String.valueOf(data.get("biller_user_key")) : null;
final String userBirth = Optional.ofNullable(data.get("user_birth")).isPresent() ?
String.valueOf(data.get("user_birth")) : null;
final String orgCd = Optional.ofNullable(parameters.get("orgCd")).isPresent() ?
String.valueOf(parameters.get("orgCd")) : null;
final String billUid = Optional.ofNullable(parameters.get("billUid")).isPresent() ?
String.valueOf(parameters.get("billUid")) : null;
BillHist billHist = null;
try {
billHist = this.addBillHistByReqInfo(BillReqSeCd.NOTICE, billerUserKey, orgCd, billUid, mParam);
if (CmmnUtil.isEmpty(billerUserKey)) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR401, "사용자식별키가 없습니다.");
}
if (CmmnUtil.isEmpty(orgCd)) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR401, "기관코드가 없습니다.");
}
if (CmmnUtil.isEmpty(userBirth)) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR401, "생년월일이 없습니다.");
}
Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
if (!orgMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
}
Optional<SendDetailKkoAlimtalk> sendDetailKkoAlimtalk = sendDetailKkoAlimtalkRepository.findByMsgIdx(billerUserKey);
if (!sendDetailKkoAlimtalk.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 발송상세 자료가 없습니다.");
}
Optional<TmpltMng> sendTmpltMng = sendTmpltMngRepository.findFetchByOrgCdAndTmpltCdAndUseYn(orgCd, sendDetailKkoAlimtalk.get().getSendMast().getTmpltCd(), "Y");
if (!sendTmpltMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 템플릿정보가 없습니다.");
}
Optional<TbInputDataXit> tbInputDataXit = tbInputDataXitRepository.findByLinkedUuid(billerUserKey);
if (!tbInputDataXit.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 발송상세정보가 없습니다.");
}
final String dataId = tbInputDataXit.get().getDataId();
if ("Y".equals(orgMng.get().getKkoBpCsignYn())) {
Optional<VKakaoNoticeInfoSn> vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId);
if (!vKakaoNoticeInfoSn.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 단순미납부과 자료가 없습니다.");
}
if (!userBirth.equals(vKakaoNoticeInfoSn.get().getUserBirth())) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR402, "생년월일이 일치하지 않습니다.");
}
respData = this.respNoticeSnData(sendTmpltMng.get().getTitle(), orgMng.get(), vKakaoNoticeInfoSn.get());
} else if ("N".equals(orgMng.get().getKkoBpCsignYn())) {
if (dataId.length() < 20) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR403, "빌러코드가 20자리 미만 입니다.");
}
Optional<VKakaoNoticeInfo> vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20));
if (!vKakaoNoticeInfo.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 강제징수부과 자료가 없습니다.");
}
if (!userBirth.equals(vKakaoNoticeInfo.get().getUserBirth())) {
kkoBillErrCd = BillKkoErrCd.E404;
throw new EnsException(EnsErrCd.ERR402, "생년월일이 일치하지 않습니다.");
}
respData = this.respNoticeData(sendTmpltMng.get().getTitle(), orgMng.get(), vKakaoNoticeInfo.get());
} else {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR999, "위탁업체여부 구분값이 등록되지 않았습니다.");
}
respVO = BillKkoApiRespDTO.okBuilder()
.data(respData)
.build();
this.modifyBillHistByRespInfo(billHist, respVO, null, null);
} catch (EnsException e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(kkoBillErrCd.getCode())
.message(kkoBillErrCd.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, e.getErrCd(), e.getMessage());
} catch (Exception e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(BillKkoErrCd.E801.getCode())
.message(BillKkoErrCd.E801.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, EnsErrCd.ERR999, e.getMessage());
}
return respVO;
}
/**
*
*
* @param mParam
* @return
*/
@Transactional
public BillKkoApiRespDTO findPrepayInfo(Map<String, Object> mParam) {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
// data.get("biller_user_key");
// data.get("billed_year_month");
// data.get("ordinal");
// data.get("biller_notice_key");
Map<String, Object> parameters = (Map<String, Object>) data.get("parameters");
// data.get("amount");
BillKkoApiRespDTO respVO = null;
BillKkoErrCd kkoBillErrCd = BillKkoErrCd.OK;
final String billerUserKey = Optional.ofNullable(data.get("biller_user_key")).isPresent() ?
String.valueOf(data.get("biller_user_key")) : null;
final int amount = Optional.ofNullable(data.get("amount")).isPresent() ?
(int) data.get("amount") : 0;
final String orgCd = Optional.ofNullable(parameters.get("orgCd")).isPresent() ?
String.valueOf(parameters.get("orgCd")) : null;
final String billUid = Optional.ofNullable(parameters.get("billUid")).isPresent() ?
String.valueOf(parameters.get("billUid")) : null;
BillHist billHist = null;
try {
billHist = this.addBillHistByReqInfo(BillReqSeCd.PREPAY, billerUserKey, orgCd, billUid, mParam);
if (CmmnUtil.isEmpty(billerUserKey)) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR401, "사용자식별키가 없습니다.");
}
if (CmmnUtil.isEmpty(orgCd)) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR401, "기관코드가 없습니다.");
}
Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
if (!orgMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
}
Optional<TbInputDataXit> tbInputDataXit = tbInputDataXitRepository.findByLinkedUuid(billerUserKey);
if (!tbInputDataXit.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 발송상세정보가 없습니다.");
}
final String dataId = tbInputDataXit.get().getDataId();
Optional<VKakaoNoticeInfo> vKakaoNoticeInfo = Optional.ofNullable(null);
List<TbEnfrcLevRciv> tbEnfrcLevRcivs = new ArrayList<>();
if ("Y".equals(orgMng.get().getKkoBpCsignYn())) {
if (dataId.length() < 20) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR403, "빌러코드가 20자리 미만 입니다.");
}
Optional<VKakaoNoticeInfoSn> vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId);
if (!vKakaoNoticeInfoSn.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E502;
throw new EnsException(EnsErrCd.ERR404, "일치하는 단순미납 자료가 없습니다.");
}
respVO = billKkoClientApi.callApiByOrg(orgMng.get().getKkoBpCsignPrepayApi(), mParam);
if ("OK".equals(respVO.getRes_code()))
this.modifyBillHistByRespInfo(billHist, respVO, null, null);
else
this.modifyBillHistByRespInfo(billHist, respVO, EnsErrCd.ERR999, String.format("[%s] %s", respVO.getRes_code(), respVO.getMessage()));
return respVO;
} else if ("N".equals(orgMng.get().getKkoBpCsignYn())) {
vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20));
if (!vKakaoNoticeInfo.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E502;
throw new EnsException(EnsErrCd.ERR404, "일치하는 강제징구 자료가 없습니다.");
}
tbEnfrcLevRcivs = tbEnfrcLevRcivRepository.findAllByEnfrcLevMastrIdAndDeleteAt(dataId.substring(0, 20), "N");
} else {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR999, "위탁업체여부 구분값이 등록되지 않았습니다.");
}
if (CmmnUtil.isEmpty(vKakaoNoticeInfo.get().getAmount())
|| amount != Integer.parseInt(vKakaoNoticeInfo.get().getAmount())) {
kkoBillErrCd = BillKkoErrCd.E403;
throw new EnsException(EnsErrCd.ERR902
, String.format("납부 가능 금액이 없거나 일치하지 않습니다. (요청금액:%s, 실제금액:%s)"
, amount
, vKakaoNoticeInfo.get().getAmount()));
}
if (amount > Integer.parseInt(vKakaoNoticeInfo.get().getAmount())) {
kkoBillErrCd = BillKkoErrCd.E501;
throw new EnsException(EnsErrCd.ERR902
, String.format("납부 가능 금액을 초과했습니다. (요청금액:%s, 실제금액:%s)"
, amount
, vKakaoNoticeInfo.get().getAmount()));
}
if (!vKakaoNoticeInfo.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E502;
throw new EnsException(EnsErrCd.ERR404, "일치하는 청구서자료가 없습니다.");
}
if (CmmnUtil.isEmpty(vKakaoNoticeInfo.get().getPayExpireDate())) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR401, "납부기한이 값이 없습니다.");
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
if (Integer.parseInt(vKakaoNoticeInfo.get().getPayExpireDate()) < Integer.parseInt(simpleDateFormat.format(new Date()))) {
kkoBillErrCd = BillKkoErrCd.E506;
throw new EnsException(EnsErrCd.ERR902, "납부기한이 경과한 자료 입니다.");
}
if (tbEnfrcLevRcivs.size() > 0) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR903, "납부가 완료된 자료 입니다.");
}
respVO = BillKkoApiRespDTO.okBuilder()
.data(null)
.build();
this.modifyBillHistByRespInfo(billHist, respVO, null, null);
} catch (EnsException e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(kkoBillErrCd.getCode())
.message(kkoBillErrCd.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, e.getErrCd(), e.getMessage());
} catch (Exception e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(BillKkoErrCd.E601.getCode())
.message(BillKkoErrCd.E601.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, EnsErrCd.ERR999, e.getMessage());
}
return respVO;
}
/**
*
*
* @param mParam
* @return
*/
@Transactional
public BillKkoApiRespDTO addPayReultIfno(Map<String, Object> mParam) {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
// data.get("biller_user_key");
// data.get("billed_year_month");
// data.get("ordinal");
// data.get("biller_notice_key");
Map<String, Object> parameters = (Map<String, Object>) data.get("parameters");
// data.get("pay_by");
// data.get("pay_type");
// data.get("pay_detail1");
// data.get("pay_detail2");
// data.get("pay_detail3");
// data.get("amount");
// data.get("pay_amount");
// data.get("pay_fee_type");
// data.get("pay_fee");
// data.get("pay_fee_tax");
// data.get("adjust_date");
// data.get("paid_at");
// data.get("pay_id");
BillKkoApiRespDTO respVO = null;
BillKkoErrCd kkoBillErrCd = BillKkoErrCd.OK;
final String billerUserKey = Optional.ofNullable(data.get("biller_user_key")).isPresent() ?
String.valueOf(data.get("biller_user_key")) : null;
final String orgCd = Optional.ofNullable(parameters.get("orgCd")).isPresent() ?
String.valueOf(parameters.get("orgCd")) : null;
final String billUid = Optional.ofNullable(parameters.get("billUid")).isPresent() ?
String.valueOf(parameters.get("billUid")) : null;
BillHist billHist = null;
try {
billHist = this.addBillHistByReqInfo(BillReqSeCd.PAYRSLT, billerUserKey, orgCd, billUid, mParam);
if (CmmnUtil.isEmpty(billerUserKey)) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR401, "사용자식별키가 없습니다.");
}
if (CmmnUtil.isEmpty(orgCd)) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR401, "기관코드가 없습니다.");
}
Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
if (!orgMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
}
if ("Y".equals(orgMng.get().getKkoBpCsignYn())) {
return billKkoClientApi.callApiByOrg(orgMng.get().getKkoBpCsignPayresultApi(), mParam);
} else if ("N".equals(orgMng.get().getKkoBpCsignYn())) {
} else {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR999, "위탁업체여부 구분값이 등록되지 않았습니다.");
}
respVO = BillKkoApiRespDTO.okBuilder()
.data(null)
.build();
this.modifyBillHistByRespInfo(billHist, respVO, null, null);
} catch (EnsException e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(kkoBillErrCd.getCode())
.message(kkoBillErrCd.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, e.getErrCd(), e.getMessage());
} catch (Exception e) {
respVO = BillKkoApiRespDTO.errBuilder()
.resCode(BillKkoErrCd.E601.getCode())
.message(BillKkoErrCd.E601.getCodeNm())
.build();
this.modifyBillHistByRespInfo(billHist, respVO, EnsErrCd.ERR999, e.getMessage());
}
return respVO;
}
}

@ -1,294 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service.support;
import cokr.xit.ens.biz.iup.code.IupPrcsCd;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.biz.iup.domain.TbInputXit;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbInputXitRepository;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.core.utils.MapDeserailizer;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.common.code.VenderCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillAcptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoAcptReqVO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.config.CustomUrl;
import cokr.xit.ens.modules.kkoalimtalk.model.KkoAlimtalkAcceptReqDTO;
import cokr.xit.ens.modules.kkoalimtalk.model.config.*;
import cokr.xit.ens.modules.kkoalimtalk.service.KkoAlimtalkService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.utility.RandomString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class IupAlimtalkAcceptor implements EnsPhaseProcSupport<EnsResponseVO, Long> {
private final TbInputXitRepository tbInputXitRepository;
private final TbInputDataXitRepository tbInputDataXitRepository;
private final KkoAlimtalkService kkoAlimtalkService;
Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).disableHtmlEscaping().create();
@Value("${contract.kakao.pay.bill.dozn.api.validate.host}")
private String BILL_HOST;
@Value("${contract.kakao.pay.bill.dozn.api.validate.notice}")
private String BILL_NOTICE_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.prepay}")
private String BILL_PREPAY_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.payresult}")
private String BILL_PAYREUSLT_URL;
/**
* Accept
*
* @param lnkInputIds
* @return
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statReady(List<Long> lnkInputIds) {
try {
AtomicInteger index = new AtomicInteger();
String prefixLinkedUuid = String.format("B-KKOAT-%s%s", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")), RandomString.make(5));
lnkInputIds.stream()
.map(lnkInputId -> tbInputXitRepository.findById(lnkInputId).get())
.map(tbinput -> tbInputDataXitRepository.findAllByTbInputXit(tbinput))
.forEach(list -> {
list.stream()
.forEach(row -> {
log.info(row.toString());
// row.setLinkedUuid(String.format("%s%05d", prefixLinkedUuid, index.getAndIncrement() + 1));
row.setLinkedUuid(row.getDataId());
});
tbInputDataXitRepository.saveAll(list);
}
);
} catch (Exception e) {
return EnsResponseVO.errBuilder()
.errCode(EnsErrCd.ACPT500)
.errMsg(String.format("연계식별UUID 생성에 실패 했습니다. %s", e.getMessage()))
.build();
}
EnsResponseVO respVO = null;
try {
/**
*
*/
if (CmmnUtil.isEmpty(lnkInputIds))
throw new EnsException(EnsErrCd.ACPT410, "연계입수아이디(은)는 필수조건 입니다.");
/**
*
* -. "대상이관등록(TGRI)" .
*/
List<Long> resultInfo = tbInputXitRepository.findAllByLnkInputIdIn(lnkInputIds).stream()
.map(row -> {
row.setUpdId("ENS_SYS");
row.setPrcsCd(IupPrcsCd.TGRI);
return row.getLnkInputId();
})
.collect(Collectors.toList());
respVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
} catch (EnsException e) {
respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
} catch (Exception e) {
respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.ACPT999).errMsg(e.getMessage()).build();
}
return respVO;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statBegin(Long arg) {
log.info("no process");
return null;
}
/**
*
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO execute(Long lnkInputId) {
Map<String, Long> resultInfo = new HashMap<>();
resultInfo.put("lnkInputId", lnkInputId);
EnsResponseVO responseVO = null;
TbInputXit tbInputXit = null;
try {
tbInputXit = tbInputXitRepository.findById(lnkInputId)
.orElseThrow(() -> new EnsException(EnsErrCd.ACPT404, String.format("일치하는 TB_INPUT_XIT 데이터가 없습니다. [ lnkInputId %s ]", lnkInputId)));
KkoAlimtalkAcceptReqDTO reqDTO = this.convertTbInputDataToAcceptReqDTO(tbInputDataXitRepository.findAllFetchByLnkInputId(tbInputXit.getLnkInputId()));
EnsResponseVO reqResp = kkoAlimtalkService.accept(reqDTO);
if (EnsErrCd.OK.equals(reqResp.getErrCode())) {
resultInfo.put("sendMastId", (Long) ((Map<String, Object>) reqResp.getResultInfo()).get("sendMastId"));
responseVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
} else {
responseVO = EnsResponseVO.errRsltBuilder()
.errCode(reqResp.getErrCode())
.errMsg(reqResp.getErrMsg())
.resultInfo(reqResp.getResultInfo())
.build();
}
} catch (EnsException e) {
responseVO = EnsResponseVO.errRsltBuilder()
.errCode(e.getErrCd())
.errMsg(String.format("알림톡 \"접수\" 처리 실패. [%s] %s", e.getErrCd().getCode(), e.getMessage()))
.resultInfo(resultInfo)
.build();
} catch (Exception e) {
responseVO = EnsResponseVO.errRsltBuilder()
.errCode(EnsErrCd.ACPT500)
.errMsg(String.format("알림톡 \"접수\" 처리 실패. %s", e.getMessage()))
.resultInfo(resultInfo)
.build();
} finally {
if (EnsErrCd.OK.equals(responseVO.getErrCode())) {
tbInputXit.setUpdId("ENS_SYS");
tbInputXit.setPrcsCd(IupPrcsCd.TGRC);
tbInputXit.setErrMsg(null);
} else {
tbInputXit.setUpdId("ENS_SYS");
tbInputXit.setPrcsCd(IupPrcsCd.TGRF);
tbInputXit.setErrMsg(responseVO.getErrMsg());
}
}
return responseVO;
}
private KkoAlimtalkAcceptReqDTO convertTbInputDataToAcceptReqDTO(List<TbInputDataXit> list) {
return KkoAlimtalkAcceptReqDTO.builder()
.vender(VenderCd.biztalk.getCode())
.org_cd(list.get(0).getTbInputXit().getOrgCd())
// .tmplt_cd(list.get(0).getTbInputXit().getFsJob().getTemplateCd())
.tmplt_cd(list.get(0).getTbInputXit().getFsJob().getJobCd())
.post_bundle_title(
String.format("%s(%s건)-%s"
, IupSendTypeCd.NI.getCodeNm()
, list.get(0).getTbInputXit().getTotCnt()
, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
)
)
.send_dt(list.get(0).getTbInputXit().getRunDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
.close_dt(list.get(0).getTbInputXit().getExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
.documents(
list.stream()
.map(row -> createDocument(row))
.collect(Collectors.toList())
)
.build();
}
private Document createDocument(TbInputDataXit data) throws EnsException {
return Document.builder()
// .msg_idx(data.getDataId())
.msg_idx(data.getLinkedUuid())
.country_code("82")
.recipient(data.getMoblphonNo())
.app_user_id(null)
.title(null)
.res_method("PUSH")
.attach(this.createAttach(data))
.supplement(this.createSupplement(data))
.message_type("AT")
.use_failback(null)
.mms_attach(this.createMmsAttach(data))
.xit_property(this.createXitProperty(data))
.build();
}
private Attachment createAttach(TbInputDataXit data) {
return null;
}
private Supplement createSupplement(TbInputDataXit data) {
return null;
}
private MmsAttach createMmsAttach(TbInputDataXit data) {
return null;
}
private XitProperty createXitProperty(TbInputDataXit data) {
return XitProperty.builder()
// .bill_link_info(this.createBillLinkInfo(data))
.bill_acpt_data(this.createBillAcptData(data))
.tmplt_msg_data(CmmnUtil.isEmpty(data.getMsgData()) ? null : gson.fromJson(data.getMsgData().replace("~~@@!!", "#{").replace("!!@@~~", "}"), Map.class))
.build();
}
// return BillLinkInfo.builder()
// .button_name("납부하기")
// .button_type("WL")
// .expire_at(data.getTbInputXit().getPayExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
// .notice_url(this.BILL_HOST + this.BILL_NOTICE_URL)
// .prepay_url(this.BILL_HOST + this.BILL_PREPAY_URL)
// .pay_result_url(this.BILL_HOST + this.BILL_PAYREUSLT_URL)
// .build();
// }
protected BillAcptReqDTO createBillAcptData(TbInputDataXit data) {
return BillAcptReqDTO.builder()
.use_bill_uid(false)
.bill_uid(null)
.bill_se(BillSeCd.bpKko)
.bill_kko(BillKkoAcptReqVO.builder()
.billUid(null)
.billerUserKey(data.getLinkedUuid())
.billedYearMonth(null)
.ordinal(null)
.billerNoticeKey(null)
.expireAt(data.getTbInputXit().getPayExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
.parameters(null)
.customUrl(CustomUrl.builder()
.noticeUrl(this.BILL_HOST + this.BILL_NOTICE_URL)
.prepayUrl(this.BILL_HOST + this.BILL_PREPAY_URL)
.payResultUrl(this.BILL_HOST + this.BILL_PAYREUSLT_URL)
.build())
.build())
.build();
}
}

@ -1,192 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service.support;
import cokr.xit.ens.biz.iup.code.IupPrcsCd;
import cokr.xit.ens.biz.iup.code.IupSendSttusCd;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.biz.iup.domain.TbInputXit;
import cokr.xit.ens.biz.iup.domain.TbSendResult;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbInputXitRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbSendResultRepository;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.core.utils.DateUtil;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.common.code.StatCd;
import cokr.xit.ens.modules.kkoalimtalk.model.KkoAlimtalkRsltRespDTO;
import cokr.xit.ens.modules.kkoalimtalk.service.KkoAlimtalkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class IupAlimtalkFetcher implements EnsPhaseProcSupport<EnsResponseVO, Long> {
private final TbInputXitRepository tbInputXitRepository;
private final TbInputDataXitRepository tbInputDataXitRepository;
private final TbSendResultRepository tbSendResultRepository;
private final KkoAlimtalkService kkoAlimtalkService;
/**
* Fetch
* @param lnkInputIds
* @return
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statReady(List<Long> lnkInputIds) {
EnsResponseVO respVO = null;
try {
if (CmmnUtil.isEmpty(lnkInputIds))
throw new EnsException(EnsErrCd.RSLT410, "연계입수아이디(은)는 필수조건 입니다.");
List<Long> resultInfo = tbInputXitRepository.findAllByLnkInputIdIn(lnkInputIds).stream()
.map(row -> {
row.setUpdId("ENS_SYS");
row.setPrcsCd(IupPrcsCd.INCM);
return row.getLnkInputId();
})
.collect(Collectors.toList());
;
respVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
} catch (EnsException e) {
respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
} catch (Exception e) {
respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.RSLT999).errMsg(e.getMessage()).build();
}
return respVO;
}
@Override
public EnsResponseVO statBegin(Long arg) {
log.info("no process");
return null;
}
/**
* (/)
* @param lnkInputId
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO execute(Long lnkInputId){
EnsResponseVO responseVO = null;
Map<String, Object> resultInfo = new HashMap<>();
resultInfo.put("lnkInputId", lnkInputId);
try {
Long sendMastId = tbInputDataXitRepository.findLastSendMastIdByLnkInputIdAndSendType(lnkInputId, IupSendTypeCd.NI)
.orElseThrow(() -> new EnsException(EnsErrCd.RSLT404, "일치하는 ENS 접수자료가 없습니다."));
resultInfo.put("sendMastId", sendMastId);
EnsResponseVO apiRespVO = kkoAlimtalkService.sendResultProvide(sendMastId);
KkoAlimtalkRsltRespDTO respDTO = (KkoAlimtalkRsltRespDTO) apiRespVO.getResultInfo();
tbSendResultRepository.saveAll(respDTO.getDocuments().stream()
.map(row -> {
IupSendSttusCd iupSendSttusCd = null;
try {
switch (row.getKkoResultCd()){
case RS_1000:
iupSendSttusCd = IupSendSttusCd.RECV;
break;
case RS_1014:
case RS_1015:
case RS_3018:
iupSendSttusCd = IupSendSttusCd.NOMB;
break;
case RQ_B400:
case RQ_B401:
case RQ_B402:
case RQ_B403:
case RS_1021:
case RS_1025:
iupSendSttusCd = IupSendSttusCd.DENY;
break;
default:
iupSendSttusCd = IupSendSttusCd.FAIL;
break;
// iupSendSttusCd = IupSendSttusCd.SEND;
// iupSendSttusCd = IupSendSttusCd.RECV;
}
} catch (Exception e){
log.info("IupSendSttusCd와 일치하는 값 없음. [ dataId {} kkoResultCd {} ]", row.getMsgIdx(), row.getKkoResultCd());
}
return TbSendResult.builder()
.lnkInputId(lnkInputId)
// .dataId(row.getMsgIdx())
.dataId(tbInputDataXitRepository.findByLinkedUuid(row.getMsgIdx())
.orElse(new TbInputDataXit())
.getDataId())
.prcsOdr(StatCd.close.equals(respDTO.getStatCd())?"2":"1")
.sendSttusCd(iupSendSttusCd)
.sendType(IupSendTypeCd.NI)
.runDt(DateUtil.toLocalDateTime(respDTO.getSendDt()))
.bizSendDt(null)
.bizRecvDt(null)
.bizReadDt(null)
.bizErrMsg(CmmnUtil.isEmpty(row.getErrorMessage()) ? null : row.getErrorMessage())
.regId("ENS_SYS")
.regDt(LocalDateTime.now())
.expiresDt(DateUtil.toLocalDateTime(respDTO.getCloseDt()))
.prcsYn("N")
.build();
})
.collect(Collectors.toList())
);
responseVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
} catch (EnsException e){
responseVO = EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
} catch (Exception e){
responseVO = EnsResponseVO.errBuilder()
.errCode(EnsErrCd.RSLT999)
.errMsg(String.format("[lnkInputId %s]에 대한 전송결과 FETCH 처리 실패. %s", lnkInputId, e.getMessage()))
.build();
} finally {
TbInputXit tbInputXit = tbInputXitRepository.findById(lnkInputId).orElseThrow(()->new EnsException(EnsErrCd.RSLT404, "일치하는 tbInputXit 자료가 없습니다."));
if(EnsErrCd.OK.equals(responseVO.getErrCode())){
tbInputXit.setUpdId("ENS_SYS");
tbInputXit.setPrcsCd(IupPrcsCd.IPCP);
tbInputXit.setErrMsg(null);
}else{
tbInputXit.setUpdId("ENS_SYS");
tbInputXit.setPrcsCd(IupPrcsCd.FAIL);
tbInputXit.setErrMsg(responseVO.getErrMsg());
}
}
return responseVO;
}
}

@ -1,66 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service.support;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.kkoalimtalk.service.KkoAlimtalkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class IupAlimtalkMaker implements EnsPhaseProcSupport<EnsResponseVO, Long> {
private final TbInputDataXitRepository tbInputDataXitRepository;
private final KkoAlimtalkService kkoAlimtalkService;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statReady(List<Long> lnkInputIds) {
log.info("no process");
return null;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statBegin(Long arg) {
log.info("no process");
return null;
}
/**
*
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO execute(Long lnkInputId){
EnsResponseVO responseVO = null;
try {
Long sendMastId = tbInputDataXitRepository.findLastSendMastIdByLnkInputIdAndSendType(lnkInputId, IupSendTypeCd.NI)
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE404, "일치하는 ENS 접수자료가 없습니다."));
responseVO = kkoAlimtalkService.make(sendMastId);
} catch (EnsException e){
responseVO = EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
}
return responseVO;
}
}

@ -1,66 +0,0 @@
package cokr.xit.ens.biz.iup.alimtalk.service.support;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.kkoalimtalk.service.KkoAlimtalkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class IupAlimtalkSender implements EnsPhaseProcSupport<EnsResponseVO, Long> {
private final TbInputDataXitRepository tbInputDataXitRepository;
private final KkoAlimtalkService kkoAlimtalkService;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statReady(List<Long> lnkInputIds) {
log.info("no process");
return null;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO statBegin(Long arg) {
log.info("no process");
return null;
}
/**
*
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EnsResponseVO execute(Long lnkInputId){
EnsResponseVO responseVO = null;
try {
Long sendMastId = tbInputDataXitRepository.findLastSendMastIdByLnkInputIdAndSendType(lnkInputId, IupSendTypeCd.NI)
.orElseThrow(() -> new EnsException(EnsErrCd.SEND404, "일치하는 ENS 접수자료가 없습니다."));
responseVO = kkoAlimtalkService.sendBulk(sendMastId);
} catch (EnsException e){
responseVO = EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
}
return responseVO;
}
}

@ -1,4 +1,4 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api;
package cokr.xit.ens.biz.iup.billpay.api;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.code.BillKkoErrCd;
@ -25,7 +25,7 @@ import java.util.Map;
@Slf4j
@Component
@Profile({"!local-test"})
public class BillKkoClientApi implements BillKkoClientApiSpec {
public class IupKkoPayUseSysApi implements IupKkoPayUseSysApiSpec {
/**
* API

@ -1,10 +1,10 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api;
package cokr.xit.ens.biz.iup.billpay.api;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import java.util.Map;
public interface BillKkoClientApiSpec {
public interface IupKkoPayUseSysApiSpec {
/**
* API

@ -1,4 +1,4 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api;
package cokr.xit.ens.biz.iup.billpay.api;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
@ -16,7 +16,7 @@ import java.util.Map;
@Slf4j
@Component
@Profile({"local-test"})
public class BillKkoClientApiTest implements BillKkoClientApiSpec {
public class IupKkoPayUseSysApiTest implements IupKkoPayUseSysApiSpec {
/**
* API

@ -1,6 +1,6 @@
package cokr.xit.ens.biz.iup.billpay.presentation;
import cokr.xit.ens.biz.iup.billpay.service.IupBillPayApiServiceSupport;
import cokr.xit.ens.biz.iup.billpay.service.IupBillKkoPayUseSysService;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.core.utils.CmmnUtil;
@ -22,15 +22,15 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@Tag(name = "IupBillPayApiController")
@Tag(name = "IupBillKkoPayUseSysController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class IupBillPayApiController {
public class IupBillKkoPayUseSysController {
private final TbInputDataXitRepository tbInputDataXitRepository;
private final Map<String, IupBillPayApiServiceSupport> mIupBillPayApiService;
private final Map<String, IupBillKkoPayUseSysService> iupBillKkoPayUseSysServiceMap;
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@ -121,9 +121,9 @@ public class IupBillPayApiController {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
String billerUserKey = (String) data.get("biller_user_key");
TbInputDataXit tbInputDataXit = tbInputDataXitRepository.findById(billerUserKey).orElseThrow(() -> new RuntimeException("biller_user_key와 일치하는 데이터를 찾을 수 없습니다."));
IupBillPayApiServiceSupport iupBillPayService = mIupBillPayApiService.get("iupBillPayApiService_" + tbInputDataXit.getTbInputXit().getSendType());
IupBillKkoPayUseSysService iupPayProcessService = iupBillKkoPayUseSysServiceMap.get("iupBillKkoPayUseSysService_" + tbInputDataXit.getTbInputXit().getSendType());
return new ResponseEntity<BillKkoApiRespDTO>(iupBillPayService.findNoticeInfo(mParam), HttpStatus.OK);
return new ResponseEntity<BillKkoApiRespDTO>(iupPayProcessService.findNoticeInfo(mParam), HttpStatus.OK);
} finally {
@ -186,7 +186,7 @@ public class IupBillPayApiController {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
String billerUserKey = (String) data.get("biller_user_key");
TbInputDataXit tbInputDataXit = tbInputDataXitRepository.findById(billerUserKey).orElseThrow(() -> new RuntimeException("biller_user_key와 일치하는 데이터를 찾을 수 없습니다."));
IupBillPayApiServiceSupport iupBillPayService = mIupBillPayApiService.get("iupBillPayApiService_" + tbInputDataXit.getTbInputXit().getSendType());
IupBillKkoPayUseSysService iupBillPayService = iupBillKkoPayUseSysServiceMap.get("iupBillKkoPayUseSysService_" + tbInputDataXit.getTbInputXit().getSendType());
return new ResponseEntity<BillKkoApiRespDTO>(iupBillPayService.findPrepayInfo(mParam), HttpStatus.OK);
@ -253,7 +253,7 @@ public class IupBillPayApiController {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
String billerUserKey = (String) data.get("biller_user_key");
TbInputDataXit tbInputDataXit = tbInputDataXitRepository.findById(billerUserKey).orElseThrow(() -> new RuntimeException("biller_user_key와 일치하는 데이터를 찾을 수 없습니다."));
IupBillPayApiServiceSupport iupBillPayService = mIupBillPayApiService.get("iupBillPayApiService_" + tbInputDataXit.getTbInputXit().getSendType());
IupBillKkoPayUseSysService iupBillPayService = iupBillKkoPayUseSysServiceMap.get("iupBillKkoPayUseSysService_" + tbInputDataXit.getTbInputXit().getSendType());
return new ResponseEntity<BillKkoApiRespDTO>(iupBillPayService.addPayReultIfno(mParam), HttpStatus.OK);

@ -1,109 +0,0 @@
package cokr.xit.ens.biz.iup.billpay.presentation;
import cokr.xit.ens.biz.iup.domain.TbInputXit;
import cokr.xit.ens.biz.iup.domain.repository.TbInputDataXitRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbInputXitRepository;
import cokr.xit.ens.biz.iup.signtalk.model.IupSigntalkReqVO;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.MapDeserailizer;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.impl.BillKkoClientServiceImpl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Tag(name = "IupBillPayRsltFwdController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class IupBillPayRsltFwdController {
private final TbInputXitRepository tbInputXitRepository;
private final TbInputDataXitRepository tbInputDataXitRepository;
private final BillKkoClientServiceImpl billKkoClientServiceImpl;
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).disableHtmlEscaping().create();
@Operation(summary = "납부결과 전달(연계 입수 아이디)")
@PostMapping(value = "/iup/bill/payrslt/fwd/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> payrsltFwdBulk(@RequestBody IupSigntalkReqVO reqDTO) {
TbInputXit tbInputXit = tbInputXitRepository.findById(reqDTO.getLnkInputId())
.orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("연계입수아이디(%s)와 일치하는 자료가 없습니다.", reqDTO.getLnkInputId())));
List<String> billerUserKeys = tbInputDataXitRepository.findAllByTbInputXit(tbInputXit).stream()
.map(tbInputDataXit -> tbInputDataXit.getLinkedUuid())
.collect(Collectors.toList());
BillKkoApiRespDTO resultInfo = billKkoClientServiceImpl.fwdPayRslt(tbInputXit.getOrgCd(), billerUserKeys).getResultInfo();
return new ResponseEntity<EnsResponseVO>(EnsResponseVO.okBuilder().resultInfo(resultInfo).build(), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "sample"
, value = "{\"biller_user_key\":[\"abcd11234\",\"dddd1234\"]}")
})
})
@Operation(summary = "납부결과 전달(빌러 유저 키)")
@PostMapping(value = "/iup/bill/payrslt/fwd/ids", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> payrsltFwdIds(@RequestBody Map<String, List<String>> mParam) {
List<Map<String, Object>> data = mParam.get("biller_user_key").stream()
.map(s -> tbInputDataXitRepository.findById(s))
.filter(tbInputDataXit -> tbInputDataXit.isPresent())
.map(tbInputDataXit -> billKkoClientServiceImpl.fwdPayRslt(tbInputDataXit.get().getTbInputXit().getOrgCd(), Collections.singletonList(tbInputDataXit.get().getLinkedUuid())))
.map(ensResponseVO -> ensResponseVO.getResultInfo().getData())
.collect(Collectors.toList());
BillKkoApiRespDTO resultInfo = BillKkoApiRespDTO.okBuilder().data(data).build();
return new ResponseEntity<EnsResponseVO>(EnsResponseVO.okBuilder().resultInfo(resultInfo).build(), HttpStatus.OK);
}
// @Operation(summary = "[미전달분-일회성] - 납부결과 전달(2022.07.04 09:00:00 ~ 2022.07.05 15:00:00 데이터)")
// @PostMapping(value = "/iup/bill/payrslt/fwd/bulk/temp", produces = MediaType.APPLICATION_JSON_VALUE)
// public ResponseEntity<EnsResponseVO> payrsltFwdBulkTemp() {
//
// List<BillKkoApiRespDTO> resultInfo = tbInputDataXitRepository.findAllByNoFwdPayResult().stream()
// .map(tbInputDataXit -> {
// String billerUserKey = tbInputDataXit.getLinkedUuid();
//
// OrgMng orgMng = orgMngRepository.findById(tbInputDataXit.getTbInputXit().getOrgCd()).orElse(null);
// if (orgMng == null)
// return BillKkoApiRespDTO.errBuilder().resCode(EnsErrCd.ERR404.getCode()).message(String.format("기관코드(%s)와 일치하는 자료가 없습니다. [ biller_user_key %s ]", tbInputDataXit.getTbInputXit().getOrgCd(), billerUserKey)).build();
//
// KkoBillHist kkoBillHist = kkoBillHistRepository.findByBillerUserKeyAndReqSeAndLast(billerUserKey, KkoBillReqSeCd.PAYRSLT).orElse(null);
// if (kkoBillHist == null)
// return BillKkoApiRespDTO.errBuilder().resCode(EnsErrCd.ERR404.getCode()).message(String.format(" 일치하는 청구서 납부결과가 없습니다. [ biller_user_key %s ]", billerUserKey)).build();
// else {
// String uri = orgMng.getKkoBpCsignPayresultApi();
// Map<String, Object> param = gson.fromJson(kkoBillHist.getRequestData(), Map.class);
// return kkoBillClientApi.callApiByOrg(uri, param);
// }
// })
// .collect(Collectors.toList());
//
//
// return new ResponseEntity<EnsResponseVO>(EnsResponseVO.okBuilder().resultInfo(resultInfo).build(), HttpStatus.OK);
// }
}

@ -0,0 +1,135 @@
package cokr.xit.ens.biz.iup.billpay.presentation;
import cokr.xit.ens.biz.iup.billpay.service.IupPayUseSysServiceFactory;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.Map;
@Tag(name = "IupPayUseSysController")
@Slf4j
@RequiredArgsConstructor
@RestController
//public class IupPayUseSysController implements PayUseSysController<ResponseEntity, Map<String, Object>> {
public class IupPayUseSysController {
private final IupPayUseSysServiceFactory factory;
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "kkopay(카카오페이)"
, summary = "kkopay(카카오페이)"
, value = "{\"data\":{\"billerUserKey\":\"빌러유저키\"}}")
})
})
@Parameters({
@Parameter(name = "paySe", example = "kkopay", required = true, in = ParameterIn.PATH),
})
@Operation(summary = "청구서링크생성 정보")
@PostMapping(value = "/iup/bill/{paySe}/gnr/url", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity gnrUrl(@PathVariable String paySe, @RequestBody Map<String, Object> param) {
if (Arrays.stream(IupPayUseSysServiceFactory.IupPaySe.values()).noneMatch(iupPaySe -> iupPaySe.name().equals(paySe)))
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
return new ResponseEntity(factory.getService(IupPayUseSysServiceFactory.IupPaySe.valueOf(paySe)).gnrUrl(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "kkopay(카카오페이)"
, summary = "kkopay(카카오페이)"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"user_birth\":\"\",\"parameters\":{\"some_param\":\"\"}}}"),
@ExampleObject(name = "nvpay(네이버페이)"
, summary = "nvpay(네이버페이)"
, value = "{\"data\":{\"billerUserKey\":\"빌러유저키\"}}")
})
})
@Parameters({
@Parameter(name = "paySe", example = "kkopay", required = true, in = ParameterIn.PATH),
})
@Operation(summary = "납부(결제)정보")
@PostMapping(value = "/iup/bill/{paySe}/pay/notice", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity payNotice(@PathVariable String paySe, @RequestBody Map<String, Object> param) {
if (Arrays.stream(IupPayUseSysServiceFactory.IupPaySe.values()).noneMatch(iupPaySe -> iupPaySe.name().equals(paySe)))
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
return new ResponseEntity(factory.getService(IupPayUseSysServiceFactory.IupPaySe.valueOf(paySe)).payNotice(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "kkopay(카카오페이)"
, summary = "kkopay(카카오페이)"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"amount\":29000,\"parameters\":{\"pay_rqt_seq\":\"KT00000001\"}}}"),
@ExampleObject(name = "nvpay(네이버페이)"
, summary = "nvpay(네이버페이)"
, value = "{\"data\":{\"billerUserKey\":\"빌러유저키\",\"productName\":\"\",\"totalPayAmount\":1000,\"taxScopeAmount\":1000,\"taxExScopeAmount\":null}}")
})
})
@Parameters({
@Parameter(name = "paySe", example = "kkopay", required = true, in = ParameterIn.PATH),
})
@Operation(summary = "납부(결제)가능여부")
@PostMapping(value = "/iup/bill/{paySe}/pay/able", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity payAble(@PathVariable String paySe, @RequestBody Map<String, Object> param) {
if (Arrays.stream(IupPayUseSysServiceFactory.IupPaySe.values()).noneMatch(iupPaySe -> iupPaySe.name().equals(paySe)))
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
return new ResponseEntity(factory.getService(IupPayUseSysServiceFactory.IupPaySe.valueOf(paySe)).payAble(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "kkopay(카카오페이)"
, summary = "kkopay(카카오페이)"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"parameters\":{\"pay_rqt_seq\":\"KT00000001\"},\"pay_by\":\"MONEY\",\"pay_type\":\"P\",\"pay_detail1\":\"\",\"pay_detail2\":\"\",\"amount\":20000,\"pay_amount\":20000,\"pay_fee_type\":\"BEFORE\",\"pay_fee\":150,\"pay_fee_tax\":15,\"paid_at\":\"20190220161656\",\"pay_id\":2748877}}"),
@ExampleObject(name = "nvpay(네이버페이)"
, summary = "nvpay(네이버페이)"
, value = "{\"code\":\"Success\",\"message\":\"detail message(optional)\",\"body\":{\"paymentId\":\"네이버페이 결제번호\",\"detail\":{\"productName\":\"샘플상품\",\"merchantId\":\"loginId\",\"merchantName\":\"가맹점명\",\"cardNo\":\"465887**********\",\"admissionYmdt\":\"20170201151722\",\"payHistId\":\"20170201NP1043587781\",\"totalPayAmount\":1000,\"primaryPayAmount\":1000,\"npointPayAmount\":0,\"giftCardAmount\":0,\"taxScopeAmount\":1000,\"taxExScopeAmount\":0,\"environmentDepositAmount\":0,\"primaryPayMeans\":\"CARD\",\"merchantPayKey\":\"청구서UID\",\"merchantUserKey\":\"빌러유저키\",\"cardCorpCode\":\"C0\",\"paymentId\":\"20170201NP1043587746\",\"admissionTypeCode\":\"01\",\"settleExpectAmount\":971,\"payCommissionAmount\":29,\"admissionState\":\"SUCCESS\",\"tradeConfirmYmdt\":\"20170201152510\",\"cardAuthNo\":\"17545616\",\"cardInstCount\":0,\"usedCardPoint\":false,\"bankCorpCode\":\"\",\"bankAccountNo\":\"\",\"settleExpected\":false,\"extraDeduction\":false,\"useCfmYmdt\":\"20180703\"}}}")
})
})
@Parameters({
@Parameter(name = "paySe", example = "kkopay", required = true, in = ParameterIn.PATH),
})
@Operation(summary = "납부(결제)결과")
@PostMapping(value = "/iup/bill/{paySe}/pay/result", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity payResult(@PathVariable String paySe, @RequestBody Map<String, Object> param) {
if (Arrays.stream(IupPayUseSysServiceFactory.IupPaySe.values()).noneMatch(iupPaySe -> iupPaySe.name().equals(paySe)))
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
return new ResponseEntity(factory.getService(IupPayUseSysServiceFactory.IupPaySe.valueOf(paySe)).payResult(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "nvpay(네이버페이)"
, summary = "nvpay(네이버페이)"
, value = "{\"code\":\"Success\",\"message\":\"detail message(optional)\",\"body\":{\"responseCount\":1,\"totalCount\":1,\"totalPageCount\":1,\"currentPageNumber\":1,\"list\":[{\"cardAuthNo\":\"00000000\",\"bankAccountNo\":\"\",\"bankCorpCode\":\"\",\"paymentId\":\"20170000NP1000229665\",\"cardCorpCode\":\"C0\",\"cardInstCount\":0,\"usedCardPoint\":false,\"settleInfo\":{\"primaryCommissionAmount\":30,\"npointCommissionAmount\":20,\"giftCardCommissionAmount\":0,\"primarySettleAmount\":470,\"npointSettleAmount\":480,\"giftCardSettleAmount\":0,\"totalSettleAmount\":850,\"totalCommissionAmount\":50,\"settleCreated\":true},\"merchantName\":\"나의가맹점\",\"productName\":\"나의상품\",\"payHistId\":\"20170000NP1000229668\",\"merchantId\":\"MID12345\",\"admissionYmdt\":\"20170914163930\",\"tradeConfirmYmdt\":\"20170915163956\",\"totalPayAmount\":1000,\"merchantPayKey\":\"orderKey-91516397\",\"merchantUserKey\":\"빌러유저키\",\"admissionTypeCode\":\"01\",\"primaryPayMeans\":\"CARD\",\"admissionState\":\"SUCCESS\",\"primaryPayAmount\":500,\"npointPayAmount\":500,\"giftCardPayAmount\":0,\"taxScopeAmount\":1000,\"taxExScopeAmount\":0,\"environmentDepositAmount\":0,\"cardNo\":\"123456**********\",\"extraDeduction\":false,\"useCfmYmdt\":\"20180703\"}]}}")
})
})
@Parameters({
@Parameter(name = "paySe", example = "kkopay", required = true, in = ParameterIn.PATH),
})
@Operation(summary = "결제취소정보")
@PostMapping(value = "/iup/bill/{paySe}/pay/cancel", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity payCancel(@PathVariable String paySe, @RequestBody Map<String, Object> param) {
if (Arrays.stream(IupPayUseSysServiceFactory.IupPaySe.values()).noneMatch(iupPaySe -> iupPaySe.name().equals(paySe)))
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
return new ResponseEntity(factory.getService(IupPayUseSysServiceFactory.IupPaySe.valueOf(paySe)).payCancel(param), HttpStatus.OK);
}
}

@ -2,9 +2,17 @@ package cokr.xit.ens.biz.iup.billpay.service;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfo;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfoSn;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.BillKkoClientApiSupport;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.BillHist;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.repository.BillHistRepository;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@ -14,7 +22,75 @@ import java.util.Map;
@Slf4j
@Component
public abstract class IupBillPayApiServiceSupport extends BillKkoClientApiSupport {
public abstract class IupBillKkoPayUseSysService {
@Autowired
private BillHistRepository billHistRepository;
/**
* -
*
* @param reqSeCd
* @param billerUserKey
* @param orgCd
* @param mParam
* @return
*/
protected BillHist addBillHistByReqInfo(BillReqSeCd reqSeCd, String billerUserKey, String orgCd, String billUid, Map<String, Object> mParam) {
BillHist billHist = BillHist.builder()
.billSe(BillSeCd.bpKko)
.billUid(billUid)
.reqSe(reqSeCd)
.orgMng(orgCd == null ? null : OrgMng.builder().orgCd(orgCd).build())
.linkedUuid(billerUserKey)
.requestData(CmmnUtil.toJsonString(mParam))
.build();
billHistRepository.save(billHist);
return billHist;
}
/**
* -
*
* @param billHist
* @param respData
* @param errCd
* @param errMsg
*/
protected void modifyBillHistByRespInfo(BillHist billHist, Object respData, EnsErrCd errCd, String errMsg) {
billHist.setResponseData(CmmnUtil.toJsonString(respData));
billHist.setError(FieldError.initBuilder()
.errorCode(CmmnUtil.isEmpty(errCd) ? null : errCd.getCode())
.errorMessage(errMsg)
.build());
billHistRepository.save(billHist);
}
/**
*
*
* @param mParam
* @return
*/
abstract public BillKkoApiRespDTO findNoticeInfo(Map<String, Object> mParam);
/**
*
*
* @param mParam
* @return
*/
abstract public BillKkoApiRespDTO findPrepayInfo(Map<String, Object> mParam);
/**
*
*
* @param mParam
* @return
*/
abstract public BillKkoApiRespDTO addPayReultIfno(Map<String, Object> mParam);
/**
* "강제징수"

@ -0,0 +1,6 @@
package cokr.xit.ens.biz.iup.billpay.service;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.PayProcessService;
public interface IupPayUseSysService<T, P> extends PayProcessService<T, P> {
}

@ -0,0 +1,32 @@
package cokr.xit.ens.biz.iup.billpay.service;
import cokr.xit.ens.biz.iup.billpay.service.impl.IupKkoPayUseSysServiceImpl;
import cokr.xit.ens.biz.iup.billpay.service.impl.IupNvPayUseSysServiceImpl;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class IupPayUseSysServiceFactory {
private final IupKkoPayUseSysServiceImpl iupKkoPayUseSysService;
private final IupNvPayUseSysServiceImpl iupNvPayUseSysService;
public enum IupPaySe {
kkopay,
nvpay
}
public IupPayUseSysService getService(IupPaySe iupPaySe) {
switch (iupPaySe) {
case kkopay:
return iupKkoPayUseSysService;
case nvpay:
return iupNvPayUseSysService;
default:
throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
}
}
}

@ -0,0 +1,86 @@
package cokr.xit.ens.biz.iup.billpay.service.impl;
import cokr.xit.ens.biz.iup.billpay.service.IupPayUseSysService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupKkoPayAbleService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupKkoPayNoticeService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupKkoPayResultService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupKkoPayUrlService;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayUrlRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.Pay;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.template.PayHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class IupKkoPayUseSysServiceImpl implements IupPayUseSysService<PayApiRespDTO, Map<String, Object>> {
private final IupKkoPayUrlService iupKkoPayUrlService;
private final IupKkoPayNoticeService iupKkoPayNoticeService;
private final IupKkoPayAbleService iupKkoPayAbleService;
private final IupKkoPayResultService iupKkoPayResultService;
@Override
public PayApiRespDTO gnrUrl(Map<String, Object> param) {
Pay<PayApiRespDTO<KkoPayUrlRespData>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<KkoPayUrlRespData>>builder()
.param(param)
.payHelperService(iupKkoPayUrlService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payNotice(Map<String, Object> param) {
Pay<PayApiRespDTO<KkoPayNoticeRespData>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<KkoPayNoticeRespData>>builder()
.param(param)
.payHelperService(iupKkoPayNoticeService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payAble(Map<String, Object> param) {
Pay<PayApiRespDTO<Map<String, Object>>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>>builder()
.param(param)
.payHelperService(iupKkoPayAbleService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payResult(Map<String, Object> param) {
Pay<PayApiRespDTO<Map<String, Object>>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>>builder()
.param(param)
.payHelperService(iupKkoPayResultService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payCancel(Map<String, Object> param) {
return PayApiRespDTO.errBuilder()
.resCode(EnsErrCd.SERVICE_NOT_SUPPORTED.getCode())
.message(EnsErrCd.SERVICE_NOT_SUPPORTED.getCodeNm())
.build();
}
}

@ -0,0 +1,81 @@
package cokr.xit.ens.biz.iup.billpay.service.impl;
import cokr.xit.ens.biz.iup.billpay.service.IupPayUseSysService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupNvPayAbleService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupNvPayCancelService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupNvPayNoticeService;
import cokr.xit.ens.biz.iup.billpay.service.process.IupNvPayResultService;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.Pay;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.template.PayHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class IupNvPayUseSysServiceImpl implements IupPayUseSysService<PayApiRespDTO, Map<String, Object>> {
private final IupNvPayNoticeService iupNvPayNoticeService;
private final IupNvPayAbleService iupNvPayAbleService;
private final IupNvPayResultService iupNvPayResultService;
private final IupNvPayCancelService iupNvPayCancelService;
@Override
public PayApiRespDTO gnrUrl(Map<String, Object> param) {
return PayApiRespDTO.errBuilder()
.resCode(EnsErrCd.SERVICE_NOT_SUPPORTED.getCode())
.message(EnsErrCd.SERVICE_NOT_SUPPORTED.getCodeNm())
.build();
}
@Override
public PayApiRespDTO payNotice(Map<String, Object> param) {
Pay<PayApiRespDTO<NvPayNoticeRespData>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<NvPayNoticeRespData>>builder()
.param(param)
.payHelperService(iupNvPayNoticeService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payAble(Map<String, Object> param) {
Pay<PayApiRespDTO<Map<String, Object>>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>>builder()
.param(param)
.payHelperService(iupNvPayAbleService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payResult(Map<String, Object> param) {
Pay<PayApiRespDTO<Map<String, Object>>> pay = PayHelper.<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>>builder()
.param(param)
.payHelperService(iupNvPayResultService)
.build();
pay.exec();
return pay.getResult();
}
@Override
public PayApiRespDTO payCancel(Map<String, Object> param) {
return PayApiRespDTO.errBuilder()
.resCode(EnsErrCd.SERVICE_NOT_SUPPORTED.getCode())
.message(EnsErrCd.SERVICE_NOT_SUPPORTED.getCodeNm())
.build();
}
}

@ -0,0 +1,217 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbEnfrcLevMastrRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoSnRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.api.PayUseSysApi;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayAbleService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupKkoPayAbleService implements PayAbleService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>> {
private final JPAQueryFactory query;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final TbEnfrcLevMastrRepository tbEnfrcLevMastrRepository;
private final PayUseSysApi payUseSysApi;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
private enum DataKeys {
tbInputDataXit,
payApiRespDTO,
responseJsonStr,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
// Integer amount = (Integer) reqData.get("amount");
if (billerUserKey == null) billerUserKey = "";
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String dataId = tbInputDataXit.getDataId();
if ("Y".equals(fsJob.getBpEntrustYn()) || "y".equals(fsJob.getBpEntrustYn())) {
final String url = fsJob.getBpKkoPrepayApi();
VKakaoNoticeInfoSn vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId)
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 단순미납부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfoSn)
.map(entity -> payUseSysApi.payAble(url, reqParam, null))
.map(response -> checkResponse(response))
.map(payApiRespDTO -> loadRespData(data, payApiRespDTO))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "단순미납 응답데이터 수신에 실패했습니다."))
;
} else if ("N".equals(fsJob.getBpEntrustYn()) || "n".equals(fsJob.getBpEntrustYn())) {
if (dataId.length() < 20)
throw new EnsException(EnsErrCd.INVALID_DATA, "데이터ID가 20자리 미만 입니다.");
VKakaoNoticeInfo vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20))
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 강제징수부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfo)
.map(entity -> validateData(reqParam, entity));
TbEnfrcLevMastr tbEnfrcLevMastr = tbEnfrcLevMastrRepository.findByEnfrcLevMastrIdAndEnfrcLevMastrProcessSttusAndDeleteAt(dataId.substring(0, 20), "04", "N")
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "납부가능 상태가 아닙니다.", PayUseSysResCd.NO_TARGET_PAYABLE));
Optional.of(tbEnfrcLevMastr)
.map(entity -> createRespData())
.map(payApiRespDTO -> loadRespData(data, payApiRespDTO))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "강제징수 응답데이터 생성에 실패했습니다."));
} else {
throw new EnsException(EnsErrCd.INVALID_DATA, "위탁여부가 등록되지 않았습니다.");
}
}
private PayApiRespDTO<Map<String, Object>> checkResponse(ResponseEntity<String> response) {
if (!HttpStatus.OK.equals(response.getStatusCode()))
throw new EnsException(EnsErrCd.API_COMM_ERROR, EnsErrCd.API_COMM_ERROR.getCodeNm() + " " + response.getStatusCode().toString(), response.getBody());
PayApiRespDTO<Map<String, Object>> result = null;
try {
result = gson.fromJson(response.getBody(), PayApiRespDTO.class);
} catch (Exception ex) {
throw new EnsException(EnsErrCd.INVALID_RESPONSE, EnsErrCd.INVALID_RESPONSE.getCodeNm(), ex);
}
return result;
}
private PayApiRespDTO loadRespData(Map<String, Object> data, PayApiRespDTO payApiRespDTO) {
if (CmmnUtil.isEmpty(payApiRespDTO))
return null;
data.put(DataKeys.payApiRespDTO.name(), payApiRespDTO);
data.put(DataKeys.responseJsonStr.name(), gson.toJson(payApiRespDTO));
return payApiRespDTO;
}
private VKakaoNoticeInfo validateData(Map<String, Object> reqParam, VKakaoNoticeInfo vKakaoNoticeInfo) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final Integer amount = (Integer) reqData.getOrDefault("amount", 0);
if (amount != Integer.parseInt(vKakaoNoticeInfo.getAmount()))
throw new EnsException(EnsErrCd.INVALID_DATA
, String.format("납부 가능 금액이 없거나 일치하지 않습니다. (요청금액:%s, 실제금액:%s)", amount, vKakaoNoticeInfo.getAmount())
, PayUseSysResCd.NO_AMOUNT_PAYABLE);
if (amount > Integer.parseInt(vKakaoNoticeInfo.getAmount()))
throw new EnsException(EnsErrCd.INVALID_DATA
, String.format("납부 가능 금액을 초과했습니다. (요청금액:%s, 실제금액:%s)", amount, vKakaoNoticeInfo.getAmount())
, PayUseSysResCd.OVERPAYABLE_AMOUNT);
if (CmmnUtil.isEmpty(vKakaoNoticeInfo.getPayExpireDate()))
throw new EnsException(EnsErrCd.INVALID_DATA
, "납부기한의 값이 비어있습니다."
, PayUseSysResCd.EXPIRED_DATE);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
if (Integer.parseInt(vKakaoNoticeInfo.getPayExpireDate()) < Integer.parseInt(simpleDateFormat.format(new Date())))
throw new EnsException(EnsErrCd.INVALID_DATA
, "납부기한이 경과한 자료 입니다."
, PayUseSysResCd.EXPIRED_DATE);
return vKakaoNoticeInfo;
}
private PayApiRespDTO createRespData() {
return PayApiRespDTO.okBuilder().build();
}
@Override
public PayApiRespDTO<Map<String, Object>> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
PayApiRespDTO payApiRespDTO = (PayApiRespDTO) data.get(DataKeys.payApiRespDTO.name());
return gson.fromJson(gson.toJson(payApiRespDTO), PayApiRespDTO.class);
} else {
if (e.getData() != null && e.getData() instanceof PayUseSysResCd) {
PayUseSysResCd resCode = (PayUseSysResCd) e.getData();
return PayApiRespDTO.<Map<String, Object>>errBuilder()
.resCode(resCode.getCode())
.message(resCode.getCodeNm())
.build();
} else {
return PayApiRespDTO.<Map<String, Object>>errBuilder()
.resCode(PayUseSysResCd.FAILED_CHECK_INFO.getCode())
.message(PayUseSysResCd.FAILED_CHECK_INFO.getCodeNm())
.build();
}
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.kakaoPay)
.hisSeCd(PayUseSysHisSeCd.payAble)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,227 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoSnRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayNoticeService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupKkoPayNoticeService implements PayNoticeService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<KkoPayNoticeRespData>> {
private final JPAQueryFactory query;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
private enum DataKeys {
tbInputDataXit,
kkoPayNoticeRespData,
responseJsonStr,
}
private enum PayDataKeys {
billerUserKey,
userBirth,
amount,
payExpireDate,
detailPasngChrgeSm,
detailAdiPasngChrgeSm,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
if (billerUserKey == null) billerUserKey = "";
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String dataId = tbInputDataXit.getDataId();
if ("Y".equals(fsJob.getBpEntrustYn()) || "y".equals(fsJob.getBpEntrustYn())) {
VKakaoNoticeInfoSn vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId)
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 단순미납부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfoSn)
.map(entity -> toDataMap(entity))
.map(payData -> validateData(reqParam, payData))
.map(payData -> createRespData(tbInputDataXit, payData))
.map(kkoPayNoticeRespData -> loadRespData(data, kkoPayNoticeRespData))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "단순미납 응답데이터 생성에 실패했습니다."))
;
} else if ("N".equals(fsJob.getBpEntrustYn()) || "n".equals(fsJob.getBpEntrustYn())) {
if (dataId.length() < 20)
throw new EnsException(EnsErrCd.INVALID_DATA, "데이터ID가 20자리 미만 입니다.");
VKakaoNoticeInfo vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20))
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 강제징수부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfo)
.map(entity -> toDataMap(entity))
.map(map -> validateData(reqParam, map))
.map(map -> createRespData(tbInputDataXit, map))
.map(kkoPayNoticeRespData -> loadRespData(data, kkoPayNoticeRespData))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "강제징수 응답데이터 생성에 실패했습니다."))
;
} else {
throw new EnsException(EnsErrCd.INVALID_DATA, "위탁여부가 등록되지 않았습니다.");
}
}
private Map<PayDataKeys, Object> toDataMap(VKakaoNoticeInfoSn vKakaoNoticeInfoSn) {
Map<PayDataKeys, Object> payData = new HashMap<>();
payData.put(PayDataKeys.billerUserKey, vKakaoNoticeInfoSn.getDataId());
payData.put(PayDataKeys.userBirth, vKakaoNoticeInfoSn.getUserBirth());
payData.put(PayDataKeys.amount, vKakaoNoticeInfoSn.getAmount().intValue());
payData.put(PayDataKeys.payExpireDate, vKakaoNoticeInfoSn.getPayExpireDate());
payData.put(PayDataKeys.detailPasngChrgeSm, vKakaoNoticeInfoSn.getDetailPasngChrgeSm());
payData.put(PayDataKeys.detailAdiPasngChrgeSm, vKakaoNoticeInfoSn.getDetailAdiPasngChrgeSm());
return payData;
}
private Map<PayDataKeys, Object> toDataMap(VKakaoNoticeInfo vKakaoNoticeInfo) {
Map<PayDataKeys, Object> payData = new HashMap<>();
payData.put(PayDataKeys.billerUserKey, vKakaoNoticeInfo.getEnfrcLevMastrId());
payData.put(PayDataKeys.userBirth, vKakaoNoticeInfo.getUserBirth());
payData.put(PayDataKeys.amount, Integer.parseInt(vKakaoNoticeInfo.getAmount()));
payData.put(PayDataKeys.payExpireDate, vKakaoNoticeInfo.getPayExpireDate());
payData.put(PayDataKeys.detailPasngChrgeSm, vKakaoNoticeInfo.getDetailPasngChrgeSm());
payData.put(PayDataKeys.detailAdiPasngChrgeSm, vKakaoNoticeInfo.getDetailAdiPasngChrgeSm());
return payData;
}
private Map<PayDataKeys, Object> validateData(Map<String, Object> reqParam, Map<PayDataKeys, Object> payData) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String userBirth = (String) reqData.getOrDefault("user_birth", "");
if (!userBirth.equals(payData.get(PayDataKeys.userBirth)))
throw new EnsException(EnsErrCd.INVALID_DATA, String.format("요청과 실제 생년월일이 일치하지 않습니다. (요청: %s 실제: %s)", userBirth, payData.get(PayDataKeys.userBirth)));
return payData;
}
private KkoPayNoticeRespData createRespData(TbInputDataXit tbInputDataXit, Map<PayDataKeys, Object> payData) {
Map<String, Object> detail = new HashMap<>();
detail.put("item_type", "TEXT");
detail.put("elements", Arrays.asList(String.format("상세 통행료: %s", payData.get(PayDataKeys.detailPasngChrgeSm))
, String.format("상세 부가통행료: %s", payData.get(PayDataKeys.detailAdiPasngChrgeSm))));
List<Map<String, Object>> details = Arrays.asList(detail);
return KkoPayNoticeRespData.builder()
.title(tbInputDataXit.getTbInputXit().getFsJob().getJobName())
.amount((Integer) payData.get(PayDataKeys.amount))
.expireType("D1")
.payExpireDate((String) payData.get(PayDataKeys.payExpireDate))
.details(details)
.build();
}
private KkoPayNoticeRespData loadRespData(Map<String, Object> data, KkoPayNoticeRespData kkoPayNoticeRespData) {
if (CmmnUtil.isEmpty(kkoPayNoticeRespData))
return null;
data.put(DataKeys.kkoPayNoticeRespData.name(), kkoPayNoticeRespData);
data.put(DataKeys.responseJsonStr.name(), gson.toJson(kkoPayNoticeRespData));
return kkoPayNoticeRespData;
}
@Override
public PayApiRespDTO<KkoPayNoticeRespData> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
KkoPayNoticeRespData kkoPayNoticeRespData = (KkoPayNoticeRespData) data.get(DataKeys.kkoPayNoticeRespData.name());
return PayApiRespDTO.<KkoPayNoticeRespData>okBuilder()
.data(kkoPayNoticeRespData)
.build();
} else {
String resCode = null;
String message = null;
switch (e.getErrCd()) {
case NO_DATA_FOUND:
resCode = PayUseSysResCd.NOT_FOUND_PAYDATA.getCode();
message = PayUseSysResCd.NOT_FOUND_PAYDATA.getCodeNm();
break;
default:
resCode = PayUseSysResCd.PAYDATA_FIND_FAILED.getCode();
message = PayUseSysResCd.PAYDATA_FIND_FAILED.getCodeNm();
break;
}
return PayApiRespDTO.<KkoPayNoticeRespData>errBuilder()
.resCode(resCode)
.message(message)
.build();
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.kakaoPay)
.hisSeCd(PayUseSysHisSeCd.payNotice)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,191 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbKakaoPayResultRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayResultReqData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.api.PayUseSysApi;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayResultService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupKkoPayResultService implements PayResultService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>> {
private final JPAQueryFactory query;
private final PayUseSysApi payUseSysApi;
private final TbKakaoPayResultRepository tbKakaoPayResultRepository;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
private enum DataKeys {
tbInputDataXit,
responseJsonStr,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
if (billerUserKey == null) billerUserKey = "";
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String url = fsJob.getBpKkoPayresultApi();
Optional.ofNullable(gson.fromJson(gson.toJson(reqParam.get("data")), KkoPayResultReqData.class))
.map(kkoPayResultReqData -> toEntity(kkoPayResultReqData))
.map(entity -> savePayResult(entity))
.map(entity -> tbInputDataXit)
.filter(detail -> "Y".equals(detail.getTbInputXit().getFsJob()))
.map(vKakaoNoticeInfoSn -> payUseSysApi.payResult(url, reqParam, null))
.map(response -> loadRespData(data, response))
.map(response -> checkResponse(response))
;
}
private TbKakaoPayResult toEntity(KkoPayResultReqData kkoPayResultReqData) {
final String jobSe = "EL".equals(kkoPayResultReqData.getBillerUserKey().substring(0, 2)) ? "2" : "1";
final String payAmount = CmmnUtil.isEmpty(kkoPayResultReqData.getPayAmount()) ? null : String.valueOf(kkoPayResultReqData.getPayAmount());
final String payFee = CmmnUtil.isEmpty(kkoPayResultReqData.getPayFee()) ? null : String.valueOf(kkoPayResultReqData.getPayFee());
final String payFeeTax = CmmnUtil.isEmpty(kkoPayResultReqData.getPayFeeTax()) ? null : String.valueOf(kkoPayResultReqData.getPayFeeTax());
final String payId = CmmnUtil.isEmpty(kkoPayResultReqData.getPayId()) ? null : String.valueOf(kkoPayResultReqData.getPayId());
return TbKakaoPayResult.builder()
.dataId(kkoPayResultReqData.getBillerUserKey())
.jobSe(jobSe)
.payMn(kkoPayResultReqData.getPayBy())
.payTy(kkoPayResultReqData.getPayType())
.payDetail1(kkoPayResultReqData.getPayDetail1())
.payDetail2(kkoPayResultReqData.getPayDetail2())
.payDetail3(kkoPayResultReqData.getPayDetail3())
.payAmount(payAmount)
.payFeeTy(kkoPayResultReqData.getPayFeeType())
.payFeeAmount(payFee)
.payFeeVat(payFeeTax)
.excclcPrearngeDe(kkoPayResultReqData.getAdjustDate())
.payDt(kkoPayResultReqData.getPaidAt())
.payId(payId)
.payResultProcessSttus("0")
// .creatDt()
.crtr("ENS_SYS")
// .updtDt()
// .updusr()
.build();
}
private TbKakaoPayResult savePayResult(TbKakaoPayResult entity) {
tbKakaoPayResultRepository.save(entity);
return entity;
}
private ResponseEntity<String> loadRespData(Map<String, Object> data, ResponseEntity<String> response) {
data.put(DataKeys.responseJsonStr.name(), response.getBody());
return response;
}
private PayApiRespDTO<Map<String, Object>> checkResponse(ResponseEntity<String> response) {
if (!HttpStatus.OK.equals(response.getStatusCode()))
throw new EnsException(EnsErrCd.API_COMM_ERROR, EnsErrCd.API_COMM_ERROR.getCodeNm() + " " + response.getStatusCode().toString(), response.getBody());
PayApiRespDTO<Map<String, Object>> result = null;
try {
result = gson.fromJson(response.getBody(), PayApiRespDTO.class);
} catch (Exception ex) {
throw new EnsException(EnsErrCd.INVALID_RESPONSE, EnsErrCd.INVALID_RESPONSE.getCodeNm(), ex);
}
return result;
}
@Override
public PayApiRespDTO<Map<String, Object>> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
return PayApiRespDTO.<Map<String, Object>>okBuilder().build();
} else {
return PayApiRespDTO.<Map<String, Object>>errDataBuilder()
.resCode(PayUseSysResCd.FAILED_SAVE_PAYRSLT.getCode())
.message(PayUseSysResCd.FAILED_SAVE_PAYRSLT.getCodeNm())
.data(null)
.build();
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("biller_user_key");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.kakaoPay)
.hisSeCd(PayUseSysHisSeCd.payResult)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,147 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.CustomUrl;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayUrlRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayUrlService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupKkoPayUrlService implements PayUrlService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<KkoPayUrlRespData>> {
private final JPAQueryFactory query;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new GsonBuilder().disableHtmlEscaping().create();
@Value("${contract.kakao.pay.bill.dozn.api.validate.host}")
private String BILL_HOST;
@Value("${contract.kakao.pay.bill.dozn.api.validate.notice}")
private String BILL_NOTICE_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.prepay}")
private String BILL_PREPAY_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.payresult}")
private String BILL_PAYREUSLT_URL;
private enum DataKeys {
tbInputDataXit,
responseJsonStr,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final String billerUserKey = (String) reqData.getOrDefault("billerUserKey", "");
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
Optional.ofNullable(createRespData(data))
.map(kkoPayUrlRespData -> loadRespData(data, kkoPayUrlRespData));
}
private KkoPayUrlRespData createRespData(Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
return KkoPayUrlRespData.builder()
.billedYearMonth(null)
.ordinal(null)
.expireAt(tbInputDataXit.getTbInputXit().getPayExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
.parameters(null)
.customUrl(CustomUrl.builder()
.noticeUrl(this.BILL_HOST + this.BILL_NOTICE_URL)
.prepayUrl(this.BILL_HOST + this.BILL_PREPAY_URL)
.payResultUrl(this.BILL_HOST + this.BILL_PAYREUSLT_URL)
.build())
.build();
}
private Map<String, Object> loadRespData(Map<String, Object> data, KkoPayUrlRespData kkoPayUrlRespData) {
data.put(DataKeys.responseJsonStr.name(), gson.toJson(kkoPayUrlRespData));
return data;
}
@Override
public PayApiRespDTO<KkoPayUrlRespData> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
KkoPayUrlRespData kkoPayUrlRespData = gson.fromJson((String) data.get(DataKeys.responseJsonStr.name()), KkoPayUrlRespData.class);
return PayApiRespDTO.<KkoPayUrlRespData>okBuilder()
.data(kkoPayUrlRespData)
.build();
} else {
return PayApiRespDTO.<KkoPayUrlRespData>errBuilder()
.resCode(PayUseSysResCd.GRNURL_FIND_FAILED.getCode())
.message(PayUseSysResCd.GRNURL_FIND_FAILED.getCodeNm())
.build();
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final String billerUserKey = (String) reqData.getOrDefault("billerUserKey", "");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.kakaoPay)
.hisSeCd(PayUseSysHisSeCd.gnrUrl)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,224 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbEnfrcLevMastrRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoSnRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.api.PayUseSysApi;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayAbleService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupNvPayAbleService implements PayAbleService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>> {
private final JPAQueryFactory query;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final TbEnfrcLevMastrRepository tbEnfrcLevMastrRepository;
private final PayUseSysApi payUseSysApi;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
private enum DataKeys {
tbInputDataXit,
payApiRespDTO,
responseJsonStr,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("billerUserKey");
// String productName = (String) reqData.get("productName");
// Integer totalPayAmount = (Integer) reqData.get("totalPayAmount");
// Integer taxScopeAmount = (Integer) reqData.get("taxScopeAmount");
// Integer taxExScopeAmount = (Integer) reqData.get("taxExScopeAmount");
if (billerUserKey == null) billerUserKey = "";
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String dataId = tbInputDataXit.getDataId();
if ("Y".equals(fsJob.getBpEntrustYn()) || "y".equals(fsJob.getBpEntrustYn())) {
final String url = fsJob.getBpNvPrepayApi();
VKakaoNoticeInfoSn vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId)
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 단순미납부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfoSn)
.map(entity -> payUseSysApi.payAble(url, reqParam, null))
.map(response -> checkResponse(response))
.map(payApiRespDTO -> loadRespData(data, payApiRespDTO))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "단순미납 응답데이터 수신에 실패했습니다."))
;
} else if ("N".equals(fsJob.getBpEntrustYn()) || "n".equals(fsJob.getBpEntrustYn())) {
if (dataId.length() < 20)
throw new EnsException(EnsErrCd.INVALID_DATA, "데이터ID가 20자리 미만 입니다.");
VKakaoNoticeInfo vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20))
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 강제징수부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfo)
.map(entity -> validateData(reqParam, entity));
TbEnfrcLevMastr tbEnfrcLevMastr = tbEnfrcLevMastrRepository.findByEnfrcLevMastrIdAndEnfrcLevMastrProcessSttusAndDeleteAt(dataId.substring(0, 20), "04", "N")
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "납부가능 상태가 아닙니다.", PayUseSysResCd.NO_TARGET_PAYABLE));
Optional.of(tbEnfrcLevMastr)
.map(entity -> createRespData())
.map(payApiRespDTO -> loadRespData(data, payApiRespDTO))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "강제징수 응답데이터 생성에 실패했습니다."));
} else {
throw new EnsException(EnsErrCd.INVALID_DATA, "위탁여부가 등록되지 않았습니다.");
}
}
private PayApiRespDTO<Map<String, Object>> checkResponse(ResponseEntity<String> response) {
if (!HttpStatus.OK.equals(response.getStatusCode()))
throw new EnsException(EnsErrCd.API_COMM_ERROR, EnsErrCd.API_COMM_ERROR.getCodeNm() + " " + response.getStatusCode().toString(), response.getBody());
PayApiRespDTO<Map<String, Object>> result = null;
try {
result = gson.fromJson(response.getBody(), PayApiRespDTO.class);
} catch (Exception ex) {
throw new EnsException(EnsErrCd.INVALID_RESPONSE, EnsErrCd.INVALID_RESPONSE.getCodeNm(), ex);
}
return result;
}
private PayApiRespDTO loadRespData(Map<String, Object> data, PayApiRespDTO payApiRespDTO) {
if (CmmnUtil.isEmpty(payApiRespDTO))
return null;
data.put(DataKeys.payApiRespDTO.name(), payApiRespDTO);
data.put(DataKeys.responseJsonStr.name(), gson.toJson(payApiRespDTO));
return payApiRespDTO;
}
private VKakaoNoticeInfo validateData(Map<String, Object> reqParam, VKakaoNoticeInfo vKakaoNoticeInfo) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final String productName = (String) reqData.get("productName");
final Integer totalPayAmount = (Integer) reqData.getOrDefault("totalPayAmount", 0);
final Integer taxScopeAmount = (Integer) reqData.get("taxScopeAmount");
final Integer taxExScopeAmount = (Integer) reqData.get("taxExScopeAmount");
if (totalPayAmount != Integer.parseInt(vKakaoNoticeInfo.getAmount()))
throw new EnsException(EnsErrCd.INVALID_DATA
, String.format("납부 가능 금액이 없거나 일치하지 않습니다. (요청금액:%s, 실제금액:%s)", totalPayAmount, vKakaoNoticeInfo.getAmount())
, PayUseSysResCd.NO_AMOUNT_PAYABLE);
if (totalPayAmount > Integer.parseInt(vKakaoNoticeInfo.getAmount()))
throw new EnsException(EnsErrCd.INVALID_DATA
, String.format("납부 가능 금액을 초과했습니다. (요청금액:%s, 실제금액:%s)", totalPayAmount, vKakaoNoticeInfo.getAmount())
, PayUseSysResCd.OVERPAYABLE_AMOUNT);
if (CmmnUtil.isEmpty(vKakaoNoticeInfo.getPayExpireDate()))
throw new EnsException(EnsErrCd.INVALID_DATA
, "납부기한의 값이 비어있습니다."
, PayUseSysResCd.EXPIRED_DATE);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
if (Integer.parseInt(vKakaoNoticeInfo.getPayExpireDate()) < Integer.parseInt(simpleDateFormat.format(new Date())))
throw new EnsException(EnsErrCd.INVALID_DATA
, "납부기한이 경과한 자료 입니다."
, PayUseSysResCd.EXPIRED_DATE);
return vKakaoNoticeInfo;
}
private PayApiRespDTO<Map<String, Object>> createRespData() {
return PayApiRespDTO.<Map<String, Object>>okBuilder().build();
}
@Override
public PayApiRespDTO<Map<String, Object>> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
PayApiRespDTO<Map<String, Object>> payApiRespDTO = (PayApiRespDTO<Map<String, Object>>) data.get(DataKeys.payApiRespDTO.name());
return payApiRespDTO;
} else {
if (e.getData() != null && e.getData() instanceof PayUseSysResCd) {
PayUseSysResCd resCode = (PayUseSysResCd) e.getData();
return PayApiRespDTO.<Map<String, Object>>errBuilder()
.resCode(resCode.getCode())
.message(resCode.getCodeNm())
.build();
} else {
return PayApiRespDTO.<Map<String, Object>>errBuilder()
.resCode(PayUseSysResCd.FAILED_CHECK_INFO.getCode())
.message(PayUseSysResCd.FAILED_CHECK_INFO.getCodeNm())
.build();
}
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
String billerUserKey = (String) reqData.get("billerUserKey");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.naverPay)
.hisSeCd(PayUseSysHisSeCd.payAble)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,51 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.utils.MapDeserailizer;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.entity.BillNvEasyPay;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayCancelService;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.model.PayCancelData;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupNvPayCancelService implements PayCancelService<PayCancelData<BillNvEasyPay>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>> {
private final JPAQueryFactory query;
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).create();
@Override
public PayCancelData<BillNvEasyPay> getData(Map<String, Object> reqParam) {
return null;
}
@Override
public void validate(Map<String, Object> reqParam, PayCancelData<BillNvEasyPay> data) {
}
@Override
public void callApi(Map<String, Object> reqParam, PayCancelData<BillNvEasyPay> data) {
}
@Override
public PayApiRespDTO<Map<String, Object>> generateResult(Map<String, Object> reqParam, PayCancelData<BillNvEasyPay> data, EnsException e) {
return null;
}
@Override
public void saveHist(Map<String, Object> reqParam, PayCancelData<BillNvEasyPay> data, EnsException e) {
}
}

@ -0,0 +1,229 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoRepository;
import cokr.xit.ens.biz.iup.domain.repository.VKakaoNoticeInfoSnRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.code.NvEpCtgyIdCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.config.notice.ProductItem;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayNoticeService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupNvPayNoticeService implements PayNoticeService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<NvPayNoticeRespData>> {
private final JPAQueryFactory query;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
@Value("${contract.naver.pay.easy.api.validate.host}")
private String BILL_HOST;
@Value("${contract.naver.pay.easy.api.validate.prepay}")
private String BILL_PAYABLE_URL;
private enum DataKeys {
tbInputDataXit,
nvPayNoticeRespData,
responseJsonStr,
}
private enum PayDataKeys {
billerUserKey,
userBirth,
amount,
payExpireDate,
detailPasngChrgeSm,
detailAdiPasngChrgeSm,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final String billerUserKey = (String) reqData.getOrDefault("billerUserKey", "");
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String dataId = tbInputDataXit.getDataId();
if ("Y".equals(fsJob.getBpEntrustYn()) || "y".equals(fsJob.getBpEntrustYn())) {
VKakaoNoticeInfoSn vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId)
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 단순미납부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfoSn)
.map(entity -> toDataMap(entity))
.map(payData -> validateData(reqParam, payData))
.map(payData -> createRespData(tbInputDataXit, payData))
.map(kkoPayNoticeRespData -> loadRespData(data, kkoPayNoticeRespData))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "단순미납 응답데이터 생성에 실패했습니다."))
;
} else if ("N".equals(fsJob.getBpEntrustYn()) || "n".equals(fsJob.getBpEntrustYn())) {
if (dataId.length() < 20)
throw new EnsException(EnsErrCd.INVALID_DATA, "데이터ID가 20자리 미만 입니다.");
VKakaoNoticeInfo vKakaoNoticeInfo = vKakaoNoticeInfoRepository.findById(dataId.substring(0, 20))
.orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "일치하는 강제징수부과 자료가 없습니다."));
Optional.of(vKakaoNoticeInfo)
.map(entity -> toDataMap(entity))
.map(map -> validateData(reqParam, map))
.map(map -> createRespData(tbInputDataXit, map))
.map(kkoPayNoticeRespData -> loadRespData(data, kkoPayNoticeRespData))
.orElseThrow(() -> new EnsException(EnsErrCd.FAILED_CREATE_RESPONSE_DATA, "강제징수 응답데이터 생성에 실패했습니다."))
;
} else {
throw new EnsException(EnsErrCd.INVALID_DATA, "위탁여부가 등록되지 않았습니다.");
}
}
private Map<PayDataKeys, Object> toDataMap(VKakaoNoticeInfoSn vKakaoNoticeInfoSn) {
Map<PayDataKeys, Object> payData = new HashMap<>();
payData.put(PayDataKeys.billerUserKey, vKakaoNoticeInfoSn.getDataId());
payData.put(PayDataKeys.userBirth, vKakaoNoticeInfoSn.getUserBirth());
payData.put(PayDataKeys.amount, vKakaoNoticeInfoSn.getAmount().intValue());
payData.put(PayDataKeys.payExpireDate, vKakaoNoticeInfoSn.getPayExpireDate());
payData.put(PayDataKeys.detailPasngChrgeSm, vKakaoNoticeInfoSn.getDetailPasngChrgeSm());
payData.put(PayDataKeys.detailAdiPasngChrgeSm, vKakaoNoticeInfoSn.getDetailAdiPasngChrgeSm());
return payData;
}
private Map<PayDataKeys, Object> toDataMap(VKakaoNoticeInfo vKakaoNoticeInfo) {
Map<PayDataKeys, Object> payData = new HashMap<>();
payData.put(PayDataKeys.billerUserKey, vKakaoNoticeInfo.getEnfrcLevMastrId());
payData.put(PayDataKeys.userBirth, vKakaoNoticeInfo.getUserBirth());
payData.put(PayDataKeys.amount, Integer.parseInt(vKakaoNoticeInfo.getAmount()));
payData.put(PayDataKeys.payExpireDate, vKakaoNoticeInfo.getPayExpireDate());
payData.put(PayDataKeys.detailPasngChrgeSm, vKakaoNoticeInfo.getDetailPasngChrgeSm());
payData.put(PayDataKeys.detailAdiPasngChrgeSm, vKakaoNoticeInfo.getDetailAdiPasngChrgeSm());
return payData;
}
private Map<PayDataKeys, Object> validateData(Map<String, Object> reqParam, Map<PayDataKeys, Object> payData) {
return payData;
}
private NvPayNoticeRespData createRespData(TbInputDataXit tbInputDataXit, Map<PayDataKeys, Object> payData) {
NvEpCtgyIdCd productSe = NvEpCtgyIdCd.ETC_ETC;
List<ProductItem> productItems = Arrays.asList(ProductItem.builder()
.categoryType(productSe.getCategoryTypeCd())
.categoryId(productSe.getCode().split("_")[1])
// .uid(tbInputDataXit.getLinkedUuid())
.uid(tbInputDataXit.getTbInputXit().getFsJob().getJobCd()) //2023.03.14 네이버페이 검수 결과 - 상품고유ID로 변경
.name(tbInputDataXit.getTbInputXit().getFsJob().getJobName())
.count(1)
.build());
Integer productCount = productItems.stream().map(productItem -> productItem.getCount()).reduce(Integer::sum).get();
return NvPayNoticeRespData.builder()
.productName(tbInputDataXit.getTbInputXit().getFsJob().getJobName())
.productCount(productCount)
.totalPayAmount((Integer) payData.get(PayDataKeys.amount))
.taxScopeAmount((Integer) payData.get(PayDataKeys.amount))
.taxExScopeAmount(0)
.environmentDepositAmount(0)
.productItems(productItems)
.returnUrl(this.BILL_HOST + this.BILL_PAYABLE_URL)
.build();
}
private NvPayNoticeRespData loadRespData(Map<String, Object> data, NvPayNoticeRespData kkoPayNoticeRespData) {
if (CmmnUtil.isEmpty(kkoPayNoticeRespData))
return null;
data.put(DataKeys.nvPayNoticeRespData.name(), kkoPayNoticeRespData);
data.put(DataKeys.responseJsonStr.name(), gson.toJson(kkoPayNoticeRespData));
return kkoPayNoticeRespData;
}
@Override
public PayApiRespDTO<NvPayNoticeRespData> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
NvPayNoticeRespData nvPayNoticeRespData = (NvPayNoticeRespData) data.get(DataKeys.nvPayNoticeRespData.name());
return PayApiRespDTO.<NvPayNoticeRespData>okBuilder()
.data(nvPayNoticeRespData)
.build();
} else {
String resCode = null;
String message = null;
switch (e.getErrCd()) {
case NO_DATA_FOUND:
resCode = PayUseSysResCd.NOT_FOUND_PAYDATA.getCode();
message = PayUseSysResCd.NOT_FOUND_PAYDATA.getCodeNm();
break;
default:
resCode = PayUseSysResCd.PAYDATA_FIND_FAILED.getCode();
message = PayUseSysResCd.PAYDATA_FIND_FAILED.getCodeNm();
break;
}
return PayApiRespDTO.<NvPayNoticeRespData>errBuilder()
.resCode(resCode)
.message(message)
.build();
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> reqData = (Map<String, Object>) reqParam.getOrDefault("data", new HashMap<>());
final String billerUserKey = (String) reqData.getOrDefault("billerUserKey", "");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.naverPay)
.hisSeCd(PayUseSysHisSeCd.payNotice)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -0,0 +1,212 @@
package cokr.xit.ens.biz.iup.billpay.service.process;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.TbIupBillPayHistRepository;
import cokr.xit.ens.biz.iup.domain.repository.TbNaverPayResultRepository;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayResultDetail;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayResultReqData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.api.PayUseSysApi;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PaidTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysHisSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.process.kit.PayResultService;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class IupNvPayResultService implements PayResultService<Map<String, Object>, Map<String, Object>, PayApiRespDTO<Map<String, Object>>> {
private final JPAQueryFactory query;
private final PayUseSysApi payUseSysApi;
private final TbNaverPayResultRepository tbNaverPayResultRepository;
private final TbIupBillPayHistRepository tbIupBillPayHistRepository;
private Gson gson = new Gson();
private enum DataKeys {
tbInputDataXit,
responseJsonStr,
}
@Override
public Map<String, Object> getData(Map<String, Object> reqParam) {
Map<String, Object> body = (Map<String, Object>) reqParam.getOrDefault("body", new HashMap<>());
Map<String, Object> detail = (Map<String, Object>) body.getOrDefault("detail", new HashMap<>());
String billerUserKey = (String) detail.get("merchantUserKey");
if (billerUserKey == null) billerUserKey = "";
TbInputDataXit tbInputDataXit = query.selectFrom(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(billerUserKey))
.fetchOne();
Map<String, Object> data = new HashMap<>();
data.put(DataKeys.tbInputDataXit.name(), tbInputDataXit);
return data;
}
@Override
public void validate(Map<String, Object> reqParam, Map<String, Object> data) {
if (CmmnUtil.isEmpty(data.get(DataKeys.tbInputDataXit.name())))
throw new EnsException(EnsErrCd.NO_DATA_FOUND, EnsErrCd.NO_DATA_FOUND.getCodeNm());
}
@Override
public void callApi(Map<String, Object> reqParam, Map<String, Object> data) {
TbInputDataXit tbInputDataXit = (TbInputDataXit) data.get(DataKeys.tbInputDataXit.name());
TbInputXit tbInputXit = tbInputDataXit.getTbInputXit();
FsJob fsJob = tbInputXit.getFsJob();
final String url = fsJob.getBpKkoPayresultApi();
Optional.ofNullable(gson.fromJson(gson.toJson(reqParam.get("body")), NvPayResultReqData.class))
.map(nvPayResultReqData -> toEntity(nvPayResultReqData))
.map(entity -> savePayResult(entity))
.map(entity -> tbInputDataXit)
.filter(detail -> "Y".equals(detail.getTbInputXit().getFsJob()))
.map(vKakaoNoticeInfoSn -> payUseSysApi.payResult(url, reqParam, null))
.map(respnose -> loadRespData(data, respnose))
.map(response -> checkResponse(response))
;
}
private TbNaverPayResult toEntity(NvPayResultReqData nvPayResultReqData) {
NvPayResultDetail detail = nvPayResultReqData.getDetail();
final String billerUserKey = detail.getMerchantUserKey();
final String jobSe = "EL".equals(billerUserKey.substring(0, 2)) ? "2" : "1";
return TbNaverPayResult.builder()
.dataId(billerUserKey)
.jobSe(jobSe)
.paymentId(detail.getPaymentId())
.payHistId(detail.getPayHistId())
.merchantId(detail.getMerchantId())
.merchantName(detail.getMerchantName())
.merchantPayKey(detail.getMerchantPayKey())
.merchantUserKey(detail.getMerchantUserKey())
.admissionTypeCode(detail.getAdmissionTypeCode())
.admissionYmdt(detail.getAdmissionYmdt())
.tradeConfirmYmdt(detail.getTradeConfirmYmdt())
.admissionState(detail.getAdmissionState())
.totalPayAmount(detail.getTotalPayAmount())
.primaryPayAmount(detail.getPrimaryPayAmount())
.npointPayAmount(detail.getNpointPayAmount())
.giftCardAmount(detail.getGiftCardAmount())
.taxScopeAmount(detail.getTaxScopeAmount())
.taxExScopeAmount(detail.getTaxExScopeAmount())
.environmentDepositAmount(detail.getEnvironmentDepositAmount())
.primaryPayMeans(detail.getPrimaryPayMeans())
.cardCorpCode(detail.getCardCorpCode())
.cardNo(detail.getCardNo())
.cardAuthNo(detail.getCardAuthNo())
.cardInstCount(detail.getCardInstCount())
.usedCardPoint(detail.getUsedCardPoint())
.bankCorpCode(detail.getBankCorpCode())
.bankAccountNo(detail.getBankAccountNo())
.productName(detail.getProductName())
.settleExpected(detail.getSettleExpected())
.settleExpectAmount(detail.getSettleExpectAmount())
.payCommissionAmount(detail.getPayCommissionAmount())
.extraDeduction(detail.getExtraDeduction())
.useCfmYmdt(detail.getUseCfmYmdt())
.merchantExtraParameter(detail.getMerchantExtraParameter())
.userIdentifier(detail.getUserIdentifier())
.payResultProcessSttus("0")
// .creatDt()
.crtr("ENS_SYS")
// .updtDt()
// .updusr()
.build();
}
private TbNaverPayResult savePayResult(TbNaverPayResult entity) {
tbNaverPayResultRepository.save(entity);
return entity;
}
private ResponseEntity<String> loadRespData(Map<String, Object> data, ResponseEntity<String> response) {
data.put(DataKeys.responseJsonStr.name(), response.getBody());
return response;
}
private PayApiRespDTO<Map<String, Object>> checkResponse(ResponseEntity<String> response) {
if (!HttpStatus.OK.equals(response.getStatusCode()))
throw new EnsException(EnsErrCd.API_COMM_ERROR, EnsErrCd.API_COMM_ERROR.getCodeNm() + " " + response.getStatusCode().toString(), response.getBody());
PayApiRespDTO<Map<String, Object>> result = null;
try {
result = gson.fromJson(response.getBody(), PayApiRespDTO.class);
} catch (Exception ex) {
throw new EnsException(EnsErrCd.INVALID_RESPONSE, EnsErrCd.INVALID_RESPONSE.getCodeNm(), ex);
}
return result;
}
@Override
public PayApiRespDTO<Map<String, Object>> generateResult(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
if (e == null) {
return PayApiRespDTO.<Map<String, Object>>okBuilder().build();
} else {
return PayApiRespDTO.<Map<String, Object>>errDataBuilder()
.resCode(PayUseSysResCd.FAILED_SAVE_PAYRSLT.getCode())
.message(PayUseSysResCd.FAILED_SAVE_PAYRSLT.getCodeNm())
.data(null)
.build();
}
}
@Override
public void saveHist(Map<String, Object> reqParam, Map<String, Object> data, EnsException e) {
Map<String, Object> body = (Map<String, Object>) reqParam.getOrDefault("body", new HashMap<>());
Map<String, Object> detail = (Map<String, Object>) body.getOrDefault("detail", new HashMap<>());
String billerUserKey = (String) detail.get("merchantUserKey");
String errorCode = null;
String errorMessage = null;
if (e != null) {
errorCode = e.getErrCd().getCode();
errorMessage = String.format("%s %s", e.getMessage(), CmmnUtil.printStackTraceToString(e));
}
TbIupBillPayHist tbIupBillPayHist = TbIupBillPayHist.builder()
.dataId(billerUserKey)
.paidType(PaidTypeCd.naverPay)
.hisSeCd(PayUseSysHisSeCd.payResult)
.requestData(gson.toJson(reqParam))
.responseData((String) data.get(DataKeys.responseJsonStr.name()))
.error(FieldError.initBuilder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build())
.build();
tbIupBillPayHistRepository.save(tbIupBillPayHist);
}
}

@ -85,4 +85,29 @@ public class FsJob {
private String templateCd;
/* =================================================
* 2023.02.14.
================================================= */
@Column(name = "bp_entrust_yn", nullable = true, length = 1)
@Setter
private String bpEntrustYn;
@Column(name = "bp_kko_prepay_api", nullable = true)
@Setter
private String bpKkoPrepayApi;
@Column(name = "bp_kko_payresult_api", nullable = true)
@Setter
private String bpKkoPayresultApi;
@Column(name = "bp_nv_prepay_api", nullable = true)
@Setter
private String bpNvPrepayApi;
@Column(name = "bp_nv_payresult_api", nullable = true)
@Setter
private String bpNvPayresultApi;
}

@ -0,0 +1,33 @@
package cokr.xit.ens.biz.iup.domain;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.BillHistPayUseSysBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Entity
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "tb_iup_bill_pay_hist", schema = "", catalog = "", indexes = {
@Index(name = "idx_iup_bp_his_01", columnList = "data_id")
})
public class TbIupBillPayHist extends BillHistPayUseSysBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "data_id", nullable = true)
private String dataId;
}

@ -23,7 +23,6 @@ import java.time.LocalDateTime;
public class TbKakaoPayResult {
@Id
@Column(name = "data_id", length = 30)
private String dataId;

@ -0,0 +1,159 @@
package cokr.xit.ens.biz.iup.domain;
import cokr.xit.ens.core.jpa.support.BooleanToYnConverter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
//@Data
@Getter
@ToString
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "tb_naver_pay_result", schema = "", catalog = "")
public class TbNaverPayResult {
@Id
@Column(name = "data_id", length = 30)
private String dataId;
@Column(name = "job_se", length = 1, nullable = true)
private String jobSe;
@Column(name = "payment_id", length = 50)
private String paymentId;
@Column(name = "pay_hist_id", length = 50)
private String payHistId;
@Column(name = "merchant_id", length = 50)
private String merchantId;
@Column(name = "merchant_name", length = 50)
private String merchantName;
@Column(name = "merchant_pay_key", length = 64)
private String merchantPayKey;
@Column(name = "merchant_user_key", length = 50)
private String merchantUserKey;
@Column(name = "admission_type_code", length = 2)
private String admissionTypeCode;
@Column(name = "admission_ymdt", length = 14)
private String admissionYmdt;
@Column(name = "trade_confirm_ymdt", length = 50)
private String tradeConfirmYmdt;
@Column(name = "admission_state", length = 10)
private String admissionState;
@Column(name = "total_pay_amount")
private Integer totalPayAmount;
@Column(name = "primary_pay_amount")
private Integer primaryPayAmount;
@Column(name = "npoint_pay_amount")
private Integer npointPayAmount;
@Column(name = "gift_card_amount")
private Integer giftCardAmount;
@Column(name = "tax_scope_amount")
private Integer taxScopeAmount;
@Column(name = "tax_ex_scope_amount")
private Integer taxExScopeAmount;
@Column(name = "environment_deposit_amount")
private Integer environmentDepositAmount;
@Column(name = "primary_pay_means", length = 10)
private String primaryPayMeans;
@Column(name = "card_corp_code", length = 10)
private String cardCorpCode;
@Column(name = "card_no", length = 50)
private String cardNo;
@Column(name = "card_auth_no", length = 30)
private String cardAuthNo;
@Column(name = "card_inst_count")
private Integer cardInstCount;
@Column(name = "used_card_point", length = 1)
@Convert(converter = BooleanToYnConverter.class)
private Boolean usedCardPoint;
@Column(name = "bank_corp_code", length = 10)
private String bankCorpCode;
@Column(name = "bank_account_no", length = 50)
private String bankAccountNo;
@Column(name = "product_name", length = 128)
private String productName;
@Column(name = "settle_expected", length = 1)
@Convert(converter = BooleanToYnConverter.class)
private Boolean settleExpected;
@Column(name = "settle_expect_amount")
private Integer settleExpectAmount;
@Column(name = "pay_commission_amount")
private Integer payCommissionAmount;
@Column(name = "extra_deduction", length = 1)
@Convert(converter = BooleanToYnConverter.class)
private Boolean extraDeduction;
@Column(name = "use_cfm_ymdt", length = 8)
private String useCfmYmdt;
@Column(name = "merchant_extra_parameter", length = 400)
private String merchantExtraParameter;
@Column(name = "user_identifier", length = 28)
private String userIdentifier;
@Column(name = "pay_result_process_sttus", length = 1, nullable = true)
private String payResultProcessSttus;
@CreationTimestamp
@Column(name = "creat_dt", nullable = true)
private LocalDateTime creatDt;
@Column(name = "crtr", length = 50, nullable = true)
private String crtr;
@UpdateTimestamp
@Column(name = "updt_dt", nullable = true)
private LocalDateTime updtDt;
@Column(name = "updusr", length = 50, nullable = true)
private String updusr;
}

@ -14,15 +14,15 @@ import java.util.Objects;
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "V_KAKAO_NOTICE_INFO_SN", schema = "", catalog = "")
@Table(name = "v_kakao_notice_info_sn", schema = "", catalog = "")
public class VKakaoNoticeInfoSn {
@Id
@Column(name = "DATA_ID", nullable = true, length = 24)
@Column(name = "data_id", nullable = true, length = 24)
private String dataId;
@Column(name = "USER_BIRTH", nullable = true, length = 4000)
@Column(name = "user_birth", nullable = true, length = 4000)
private String userBirth;
@ -30,14 +30,14 @@ public class VKakaoNoticeInfoSn {
private Long amount;
@Column(name = "PAY_EXPIRE_DATE", nullable = true, length = 8)
@Column(name = "pay_expire_date", nullable = true, length = 8)
private String payExpireDate;
@Column(name = "DETAIL_PASNG_CHRGE_SM", nullable = true, precision = 0)
@Column(name = "detail_pasng_chrge_sm", nullable = true, precision = 0)
private Long detailPasngChrgeSm;
@Column(name = "DETAIL_ADI_PASNG_CHRGE_SM", nullable = true, precision = 0)
@Column(name = "detail_adi_pasng_chrge_sm", nullable = true, precision = 0)
private Long detailAdiPasngChrgeSm;
}

@ -4,10 +4,9 @@ import cokr.xit.ens.biz.iup.domain.TbEnfrcLevRciv;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface TbEnfrcLevRcivRepository extends JpaRepository<TbEnfrcLevRciv, String>, TbEnfrcLevRcivRepositoryCustom {
public interface TbEnfrcLevRcivRepository extends JpaRepository<TbEnfrcLevRciv, String> {
List<TbEnfrcLevRciv> findAllByEnfrcLevMastrIdAndDeleteAt(String enfrcLevMastrId, String deleteAt);
}

@ -1,5 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
public interface TbEnfrcLevRcivRepositoryCustom {
}

@ -1,12 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class TbEnfrcLevRcivRepositoryImpl implements TbEnfrcLevRcivRepositoryCustom {
private final JPAQueryFactory query;
}

@ -2,8 +2,8 @@ package cokr.xit.ens.biz.iup.domain.repository;
import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillSeCd;
import com.querydsl.core.types.dsl.DateTemplate;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
@ -19,7 +19,7 @@ import java.util.Optional;
import static cokr.xit.ens.biz.iup.domain.QFsJob.fsJob;
import static cokr.xit.ens.biz.iup.domain.QTbInputDataXit.tbInputDataXit;
import static cokr.xit.ens.biz.iup.domain.QTbInputXit.tbInputXit;
import static cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.QBillHist.billHist;
import static cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.QBillHist.billHist;
import static cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.QIntgrnSendDetail.intgrnSendDetail;
import static cokr.xit.ens.modules.kkoalimtalk.domain.QSendDetailKkoAlimtalk.sendDetailKkoAlimtalk;
@ -44,10 +44,8 @@ public class TbInputDataXitCustomRepositoryImpl implements TbInputDataXitCustomR
@Override
public List<TbInputDataXit> findAllFetchByLnkInputId(Long lnkInputId) {
return query.selectFrom(tbInputDataXit)
.innerJoin(tbInputDataXit.tbInputXit, tbInputXit)
.fetchJoin()
.innerJoin(tbInputXit.fsJob, fsJob)
.fetchJoin()
.innerJoin(tbInputDataXit.tbInputXit, tbInputXit).fetchJoin()
.innerJoin(tbInputXit.fsJob, fsJob).fetchJoin()
.where(tbInputDataXit.tbInputXit.lnkInputId.eq(lnkInputId))
.fetch();
}
@ -111,7 +109,7 @@ public class TbInputDataXitCustomRepositoryImpl implements TbInputDataXitCustomR
// .innerJoin(kkoBillHist).on(kkoBillHist.billerUserKey.eq(tbInputDataXit.linkedUuid)).fetchJoin()
.innerJoin(billHist).on(billHist.billSe.eq(BillSeCd.bpKko).and(billHist.linkedUuid.eq(tbInputDataXit.linkedUuid))).fetchJoin()
.where(
billHist.reqSe.eq(BillReqSeCd.PAYRSLT)
billHist.reqSe.eq(BillReqSeCd.US_PAYRSLT)
.and(tbInputXit.runDt.between(from, to))
.and(billHist.registDt.between(from, to))
)

@ -0,0 +1,9 @@
package cokr.xit.ens.biz.iup.domain.repository;
import cokr.xit.ens.biz.iup.domain.TbIupBillPayHist;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TbIupBillPayHistRepository extends JpaRepository<TbIupBillPayHist, Long> {
}

@ -0,0 +1,9 @@
package cokr.xit.ens.biz.iup.domain.repository;
import cokr.xit.ens.biz.iup.domain.TbKakaoPayResult;
import cokr.xit.ens.biz.iup.domain.TbNaverPayResult;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TbNaverPayResultRepository extends JpaRepository<TbNaverPayResult, String> {
}

@ -3,7 +3,7 @@ package cokr.xit.ens.biz.iup.domain.repository;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface VKakaoNoticeInfoRepository extends JpaRepository<VKakaoNoticeInfo, String>, VKakaoNoticeInfoRepositoryCustom {
public interface VKakaoNoticeInfoRepository extends JpaRepository<VKakaoNoticeInfo, String> {
}

@ -1,5 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
public interface VKakaoNoticeInfoRepositoryCustom {
}

@ -1,12 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class VKakaoNoticeInfoRepositoryImpl implements VKakaoNoticeInfoRepositoryCustom {
private final JPAQueryFactory query;
}

@ -3,7 +3,7 @@ package cokr.xit.ens.biz.iup.domain.repository;
import cokr.xit.ens.biz.iup.domain.VKakaoNoticeInfoSn;
import org.springframework.data.jpa.repository.JpaRepository;
public interface VKakaoNoticeInfoSnRepository extends JpaRepository<VKakaoNoticeInfoSn, String>, VKakaoNoticeInfoSnRepositoryCustom {
public interface VKakaoNoticeInfoSnRepository extends JpaRepository<VKakaoNoticeInfoSn, String> {
}

@ -1,5 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
public interface VKakaoNoticeInfoSnRepositoryCustom {
}

@ -1,12 +0,0 @@
package cokr.xit.ens.biz.iup.domain.repository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class VKakaoNoticeInfoSnRepositoryImpl implements VKakaoNoticeInfoSnRepositoryCustom {
private final JPAQueryFactory query;
}

@ -1,17 +1,17 @@
package cokr.xit.ens.biz.iup.signtalk.service;
import cokr.xit.ens.biz.iup.billpay.service.IupBillPayApiServiceSupport;
import cokr.xit.ens.biz.iup.billpay.api.IupKkoPayUseSysApiSpec;
import cokr.xit.ens.biz.iup.billpay.service.IupBillKkoPayUseSysService;
import cokr.xit.ens.biz.iup.domain.*;
import cokr.xit.ens.biz.iup.domain.repository.*;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.BillHist;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api.BillKkoClientApiSpec;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.code.BillKkoErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoPayResultDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoPayResultData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.BillHist;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendDetail;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.IntgrnSendDetailRepository;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
@ -19,6 +19,7 @@ import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.TmpltMng;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.OrgMngRepository;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.TmpltMngRepository;
import com.google.gson.Gson;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -31,9 +32,9 @@ import java.util.Map;
import java.util.Optional;
@Slf4j
@Service("iupBillPayApiService_KP")
@Service("iupBillKkoPayUseSysService_KP")
@RequiredArgsConstructor
public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
public class IupBillKkoPaySigntalkService extends IupBillKkoPayUseSysService {
private final IntgrnSendDetailRepository intgrnSendDetailRepository;
@ -42,10 +43,11 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
private final TbInputDataXitRepository tbInputDataXitRepository;
private final VKakaoNoticeInfoRepository vKakaoNoticeInfoRepository;
private final VKakaoNoticeInfoSnRepository vKakaoNoticeInfoSnRepository;
// private final TbEnfrcLevRcivRepository tbEnfrcLevRcivRepository;
private final TbEnfrcLevMastrRepository tbEnfrcLevMastrRepository;
private final TbKakaoPayResultRepository tbKakaoPayResultRepository;
private final BillKkoClientApiSpec billKkoClientApi;
private final IupKkoPayUseSysApiSpec iupKkoPayApi;
private final JPAQueryFactory query;
/**
@ -232,32 +234,32 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
if (!orgMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
}
Optional<TbInputDataXit> tbInputDataXit = tbInputDataXitRepository.findByLinkedUuid(billerUserKey);
// Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
// if (!orgMng.isPresent()) {
// kkoBillErrCd = BillKkoErrCd.E601;
// throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
// }
// Optional<TbInputDataXit> tbInputDataXit = tbInputDataXitRepository.findByLinkedUuid(billerUserKey);
Optional<TbInputDataXit> tbInputDataXit = this.getTbInputDataXitByLinkedUuid(billerUserKey);
if (!tbInputDataXit.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 발송상세정보가 없습니다.");
}
final FsJob fsJob = tbInputDataXit.get().getTbInputXit().getFsJob();
final String dataId = tbInputDataXit.get().getDataId();
Optional<VKakaoNoticeInfo> vKakaoNoticeInfo = Optional.ofNullable(null);
// List<TbEnfrcLevRciv> tbEnfrcLevRcivs = new ArrayList<>();
if ("Y".equals(orgMng.get().getKkoBpCsignYn())) {
if ("Y".equals(fsJob.getBpEntrustYn())) {
Optional<VKakaoNoticeInfoSn> vKakaoNoticeInfoSn = vKakaoNoticeInfoSnRepository.findById(dataId);
if (!vKakaoNoticeInfoSn.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E502;
throw new EnsException(EnsErrCd.ERR404, "일치하는 단순미납 자료가 없습니다.");
}
respVO = billKkoClientApi.callApiByOrg(orgMng.get().getKkoBpCsignPrepayApi(), mParam);
respVO = iupKkoPayApi.callApiByOrg(fsJob.getBpKkoPrepayApi(), mParam);
if ("OK".equals(respVO.getRes_code()))
this.modifyBillHistByRespInfo(billHist, respVO, null, null);
@ -266,7 +268,7 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
return respVO;
} else if ("N".equals(orgMng.get().getKkoBpCsignYn())) {
} else if ("N".equals(fsJob.getBpEntrustYn())) {
if (dataId.length() < 20) {
kkoBillErrCd = BillKkoErrCd.E502;
throw new EnsException(EnsErrCd.ERR403, "빌러코드가 20자리 미만 입니다.");
@ -364,7 +366,7 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
Map<String, Object> data = (Map<String, Object>) mParam.get("data");
Gson gson = new Gson();
BillKkoPayResultDTO kkoBillPayResultVO = gson.fromJson(gson.toJson(data), BillKkoPayResultDTO.class);
BillKkoPayResultData kkoBillPayResultVO = gson.fromJson(gson.toJson(data), BillKkoPayResultData.class);
Map<String, Object> parameters = kkoBillPayResultVO.getParameters();
@ -392,25 +394,31 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
if (!orgMng.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E601;
throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
// Optional<OrgMng> orgMng = orgMngRepository.findById(orgCd);
// if (!orgMng.isPresent()) {
// kkoBillErrCd = BillKkoErrCd.E601;
// throw new EnsException(EnsErrCd.ERR404, "일치하는 기관정보가 없습니다.");
// }
Optional<TbInputDataXit> tbInputDataXit = this.getTbInputDataXitByLinkedUuid(kkoBillPayResultVO.getBiller_user_key());
if (!tbInputDataXit.isPresent()) {
kkoBillErrCd = BillKkoErrCd.E402;
throw new EnsException(EnsErrCd.ERR404, "일치하는 발송상세정보가 없습니다.");
}
final FsJob fsJob = tbInputDataXit.get().getTbInputXit().getFsJob();
if (!tbKakaoPayResultRepository.findById(kkoBillPayResultVO.getBiller_user_key()).isPresent())
tbKakaoPayResultRepository.save(this.createTbKakaoPayResult(kkoBillPayResultVO));
if ("Y".equals(orgMng.get().getKkoBpCsignYn())) {
respVO = billKkoClientApi.callApiByOrg(orgMng.get().getKkoBpCsignPayresultApi(), mParam);
if ("Y".equals(fsJob.getBpEntrustYn())) {
respVO = iupKkoPayApi.callApiByOrg(fsJob.getBpKkoPayresultApi(), mParam);
if (!"OK".equals(respVO.getRes_code()))
this.modifyBillHistByRespInfo(kkoBillHist, respVO, EnsErrCd.ERR600, String.format("[%s] %s", respVO.getRes_code(), respVO.getMessage()));
return respVO;
} else if ("N".equals(orgMng.get().getKkoBpCsignYn())) {
} else if ("N".equals(fsJob.getBpEntrustYn())) {
} else {
kkoBillErrCd = BillKkoErrCd.E601;
@ -444,7 +452,7 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
}
private TbKakaoPayResult createTbKakaoPayResult(BillKkoPayResultDTO kkoBillPayResultVO) {
private TbKakaoPayResult createTbKakaoPayResult(BillKkoPayResultData kkoBillPayResultVO) {
final String jobSe = "EL".equals(kkoBillPayResultVO.getBiller_user_key().substring(0, 2)) ? "2" : "1";
@ -473,4 +481,13 @@ public class IupBillPayApiSigntalkService extends IupBillPayApiServiceSupport {
.build();
}
private Optional<TbInputDataXit> getTbInputDataXitByLinkedUuid(String linkedUuid) {
return Optional.ofNullable(query.select(QTbInputDataXit.tbInputDataXit)
.from(QTbInputDataXit.tbInputDataXit)
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit, QTbInputXit.tbInputXit).fetchJoin()
.innerJoin(QTbInputDataXit.tbInputDataXit.tbInputXit.fsJob, QFsJob.fsJob).fetchJoin()
.where(QTbInputDataXit.tbInputDataXit.linkedUuid.eq(linkedUuid))
.fetchOne());
}
}

@ -14,10 +14,8 @@ import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.common.code.VenderCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillAcptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoAcptReqVO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.config.CustomUrl;
import cokr.xit.ens.core.model.EnsBillAcptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.IntgrnNotiAcceptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.config.AcptData;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.config.Document;
@ -53,18 +51,9 @@ public class IupSigntalkAcceptor implements EnsPhaseProcSupport<EnsResponseVO, L
private final IntgrnNotiService intgrnNotiService;
@Value("${contract.kakao.pay.bill.dozn.api.validate.host}")
private String BILL_HOST;
@Value("${contract.kakao.pay.bill.dozn.api.validate.notice}")
private String BILL_NOTICE_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.prepay}")
private String BILL_PREPAY_URL;
@Value("${contract.kakao.pay.bill.dozn.api.validate.payresult}")
private String BILL_PAYREUSLT_URL;
@Value("${xit.mblpage.intgrn.url}")
@Value("${xit.mblpage.postse.intgrn.url}")
private String MBLPAGE_URL;
@Value("${xit.mblpage.intgrn.path}")
@Value("${xit.mblpage.postse.intgrn.path}")
private String MBLPAGE_PATH;
@ -251,7 +240,6 @@ public class IupSigntalkAcceptor implements EnsPhaseProcSupport<EnsResponseVO, L
.nv_st(new AcptDocNvSt(data, null, MBLPAGE_URL + MBLPAGE_PATH).createDocument())
.build())
.xit_property(XitProperty.builder()
// .bill_link_info(this.createBillLinkInfo(data))
.bill_acpt_data(this.createBillAcptData(data))
.tmplt_msg_data(CmmnUtil.isEmpty(data.getMsgData()) ? null : gson.fromJson(data.getMsgData().replace("~~@@!!", "#{").replace("!!@@~~", "}"), Map.class))
.mbl_page_data(CmmnUtil.isEmpty(data.getMsgDtlData()) ? null : gson.fromJson(data.getMsgDtlData(), Map.class))
@ -260,42 +248,11 @@ public class IupSigntalkAcceptor implements EnsPhaseProcSupport<EnsResponseVO, L
}
// private List<Map<String, Object>> createDetails(TbInputDataXit data) {
// return null;
// }
// private BillLinkInfo createBillLinkInfo(TbInputDataXit data) {
// return BillLinkInfo.builder()
// .use_bill_mast_id(false)
// .bill_mast_id(null)
// .button_name("납부하기")
// .button_type("WL")
// .expire_at(data.getTbInputXit().getPayExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
// .notice_url(this.BILL_HOST + this.BILL_NOTICE_URL)
// .prepay_url(this.BILL_HOST + this.BILL_PREPAY_URL)
// .pay_result_url(this.BILL_HOST + this.BILL_PAYREUSLT_URL)
// .build();
// }
private BillAcptReqDTO createBillAcptData(TbInputDataXit data) {
return BillAcptReqDTO.builder()
.use_bill_uid(false)
.bill_uid(null)
.bill_se(BillSeCd.bpKko)
.bill_kko(BillKkoAcptReqVO.builder()
private EnsBillAcptReqDTO createBillAcptData(TbInputDataXit data) {
return EnsBillAcptReqDTO.builder()
.billUid(null)
.billerUserKey(data.getLinkedUuid())
.billedYearMonth(null)
.ordinal(null)
.billerNoticeKey(null)
.expireAt(data.getTbInputXit().getPayExpiresDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
.parameters(null)
.customUrl(CustomUrl.builder()
.noticeUrl(this.BILL_HOST + this.BILL_NOTICE_URL)
.prepayUrl(this.BILL_HOST + this.BILL_PREPAY_URL)
.payResultUrl(this.BILL_HOST + this.BILL_PAYREUSLT_URL)
.build())
.build())
.billSe(BillSeCd.bpKko)
.build();
}

@ -16,7 +16,7 @@ import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.core.utils.MapDeserailizer;
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
import cokr.xit.ens.modules.common.code.VenderCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillAcptReqDTO;
import cokr.xit.ens.core.model.EnsBillAcptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.IntgrnNotiAcceptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.config.AcptData;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.config.Document;
@ -54,9 +54,9 @@ public class TrafficCaSigntalkAcceptor implements EnsPhaseProcSupport<EnsRespons
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
@Value("${xit.mblpage.intgrn.url}")
@Value("${xit.mblpage.postse.intgrn.url}")
private String MBLPAGE_URL;
@Value("${xit.mblpage.intgrn.path}")
@Value("${xit.mblpage.postse.intgrn.path}")
private String MBLPAGE_PATH;
/**
@ -229,7 +229,7 @@ public class TrafficCaSigntalkAcceptor implements EnsPhaseProcSupport<EnsRespons
.build();
}
private BillAcptReqDTO createBillAcptData(TcaElctrnNticSndngDetail data) {
private EnsBillAcptReqDTO createBillAcptData(TcaElctrnNticSndngDetail data) {
return null;
}

@ -92,8 +92,8 @@ public class TrafficCcJpaRunner implements ApplicationRunner {
.kkoBpBillerCode(KKO_BP_BILLER_CODE)
.kkoBpAuthorization(KKO_BP_AUTHORIZATION)
.kkoBpCsignYn("N")
.kkoBpCsignPrepayApi(null)
.kkoBpCsignPayResultApi(null)
.kkoBpPrepayApi(null)
.kkoBpPayResultApi(null)
.kkoAtBsid(KKO_AT_BSID)
.kkoAtPasswd(KKO_AT_PASSWD)
.kkoAtSenderKey(KKO_AT_SENDER_KEY)

@ -171,7 +171,7 @@
//// NotiDocument notiDocument = (NotiDocument) CmmnUtil.jsonStringtoObj(NotiDocument.class, row.getMobilePageCn());
// ObjectMapper mapper = new ObjectMapper();
// NotiDocument notiDocument = mapper.readValue(row.getMobilePageCn(), NotiDocument.class);
// notiDocument.setPayload(payload);
// notiDocument.setPayload``(payload);
// notidocuments.add(notiDocument);
// } catch (Exception e) {
// // log.error(String.format("고지정보 변환에 실패 했습니다. [%s]", row.getMobilePageCn()), e);

@ -1,6 +1,9 @@
package cokr.xit.ens.core.aop;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
@ -14,12 +17,21 @@ import lombok.ToString;
public class EnsResponseVO<T> {
@Schema(required = true, title = "에러 코드", example = " ")
@JsonProperty("errCode")
@JsonAlias({"err_code"})
@SerializedName(value = "errCode", alternate = {"err_code"})
private EnsErrCd errCode = null;
@Schema(required = true, title = "에러 메시지", example = " ")
@JsonProperty("errMsg")
@JsonAlias({"err_msg"})
@SerializedName(value = "errMsg", alternate = {"err_msg"})
private String errMsg = null;
@Schema(required = false, title = "결과 데이터", example = " ")
@JsonProperty("resultInfo")
@JsonAlias({"result_info"})
@SerializedName(value = "resultInfo", alternate = {"result_info"})
private T resultInfo;
@Builder(builderClassName = "okBuilder" ,builderMethodName = "okBuilder")

@ -0,0 +1,14 @@
package cokr.xit.ens.core.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}

@ -71,18 +71,34 @@ public class SpringDocConfig {
@Profile({"local", "local-test", "local-maria", "local-oracle", "prod-iup"})
@Bean
public GroupedOpenApi cmmnFtBillApiDoc() {
public GroupedOpenApi cmmnFtBillPaysApiDoc() {
return GroupedOpenApi.builder()
.group("CF. 공통기능-청구서(kakaopay)")
.group("CF. 부가기능-청구서 공통 서비스")
.pathsToMatch("/bill/pay/**")
.build();
}
@Profile({"local", "local-test", "local-maria", "local-oracle", "prod-iup"})
@Bean
public GroupedOpenApi cmmnFtBillKkopayApiDoc() {
return GroupedOpenApi.builder()
.group("CF. 부가기능-청구서(kakaopay)")
.pathsToMatch("/bill/kko/**")
.build();
}
@Profile({"local", "local-test", "local-maria", "local-oracle", "prod-iup"})
@Bean
public GroupedOpenApi cmmnFtBillNvpayApiDoc() {
return GroupedOpenApi.builder()
.group("CF. 부가기능-청구서(naver 간편결제)")
.pathsToMatch("/bill/nv/ep/**")
.build();
}
@Profile({"local", "local-test", "local-maria", "local-oracle", "prod-traffic", "prod-traffic-cheonan", "prod-iup"})
@Bean
public GroupedOpenApi cmmnFtNiceCiDiApiDoc() {
return GroupedOpenApi.builder()
.group("CF. 공통기능-CI변환(나이스 CiDi)")
.group("CF. 부가기능-CI변환(나이스 CiDi)")
.pathsToMatch("/cmft/nice/ci/**")
.build();
}
@ -90,7 +106,7 @@ public class SpringDocConfig {
@Bean
public GroupedOpenApi cmmnFtMblPageApiDoc() {
return GroupedOpenApi.builder()
.group("CF. 공통기능-모바일페이지")
.group("CF. 부가기능-모바일페이지")
.pathsToMatch(
"/cmft/mbl/page/**"
)

@ -1,6 +1,5 @@
package cokr.xit.ens.core.config.redis;
import cokr.xit.ens.core.utils.CmmnUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@ -8,127 +8,149 @@ import cokr.xit.ens.core.code.CodeMapperType;
* <li> : </li>
* <li>: 2021. 8. 4. 3:51:43
* </ul>
*
* @author
*/
public enum EnsErrCd implements CodeMapperType {
OK("정상"),
UNKNOWN("알수없음")
, ERR401("필수 파라미터가 없습니다.")
, ERR402("파라미터 유효성 검증 오류")
, ERR403("잘못된 파라미터 입니다.")
, ERR404("일치하는 자료가 없습니다.")
, ERR405("잘못된 요청 값.")
, ERR410("필수값 없음")
, ERR411("잘못된 JSON 포맷 문자열")
, ERR500("서버 오류")
, ERR501("HttpServer 오류")
, ERR502("HttpClient 오류")
, ERR503("RestClient 오류")
, ERR504("요청 데이터 Json 파싱 오류")
, ERR505("응답 데이터 Json 파싱 오류")
, ERR506("Hash 생성 오류")
, ERR507("유효하지 않은 데이터")
, ERR511("JSON 형식으로 변환 실패")
, ERR521("방화벽 설정 오류")
, ERR540("중복된 데이터")
, ERR600("API 오류")
, ERR601("API서버 응답 오류")
, ERR602("API서버 내부 오류")
, ERR603("유효하지 않은 토큰(OTT) 값")
, ERR610("응답 데이터에 필수값이 없음")
, ERR620("API Response Error")
, ERR699("API 기타 오류")
, ERR999("기타 오류")
, ERR901("권한 없음")
, ERR902("유효하지 않은 데이터")
, ERR903("처리 완료된 데이터")
, ERR904("CI 변환 실패")
, BILL401("duplicated \"bill_uid\"")
, BILL402("duplicated \"biller_user_key\"")
, BILL403("validation fail")
, BILL404("not found data")
, BILL405("invalid value")
, BILL501("json convert fail") //json 변환 실패
, BILL511("청구서 URL 생성 병렬처리 중 ERROR")
, BILL512("청구서 URL 생성 실패")
, BILL601("json parsing fail") //json 분석 실패
, BILL602("http status failure response") //http staus 오류
, BILL603("response data is invalid")
, BILL604("client api failure response")
, BILL999("unknown error")
, ACPT402("유효성 검증 실패")
, ACPT404("일치하는 자료가 없습니다.")
, ACPT405("접수 가능한 자료가 아닙니다.")
, ACPT410("필수값 없음")
, ACPT411("잘못된 JSON 포맷 문자열")
, ACPT412("청구서 접수 실패")
, ACPT500("접수 처리 중 오류")
, ACPT511("JSON 형식으로 변환 실패")
, ACPT999("기타 오류")
, MAKE404("일치하는 자료가 없습니다.")
, MAKE410("필수값 없음")
, MAKE411("잘못된 JSON 포맷 문자열")
, MAKE500("제작 처리 중 오류")
, MAKE511("JSON 형식으로 변환 실패")
, MAKE512("청구서 제작 실패")
, MAKE513("CI 제작 실패")
, MAKE521("데이터 생성 실패")
, MAKE610("응답 데이터에 필수값이 없음")
, MAKE620("API Response Error")
, MAKE630("API Request Error")
, SEND404("일치하는 자료가 없습니다.")
, SEND405("잘못된 요청 값.")
, SEND410("필수값 없음")
, SEND411("잘못된 JSON 포맷 문자열")
, SEND500("전송 처리 중 오류")
, SEND502("발송메시지 생성 실패")
, SEND511("JSON 형식으로 변환 실패")
, SEND601("토큰생성 실패")
, SEND620("API Response Error")
, SEND630("API Request Error")
, RSLT404("일치하는 자료가 없습니다.")
, RSLT405("요청건수와 실제 자료의 건수가 상이 합니다.")
, RSLT406("일부 자료가 결과반영에 실패 했습니다.")
, RSLT407("전체 자료가 결과반영에 실패 했습니다.")
, RSLT410("필수값 없음")
, RSLT411("잘못된 JSON 포맷 문자열")
, RSLT500("전송결과 처리 중 오류")
, RSLT502("요청메시지 생성 실패")
, RSLT511("JSON 형식으로 변환 실패")
, RSLT512("제공되지 않는 서비스 입니다.")
, RSLT601("전송결과 조회 실패")
, RSLT620("API Response Error")
, RSLT630("API Request Error")
, RSLT999("기타 오류")
, PRVD404("일치하는 자료가 없습니다.")
, PRVD410("필수값 없음")
, PRVD411("잘못된 JSON 포맷 문자열")
, PRVD500("상태갱신 처리 중 오류")
, PRVD511("JSON 형식으로 변환 실패")
, PRVD502("요청메시지 생성 실패")
, PRVD601("상태 조회 실패")
, PRVD620("API Response Error")
, PRVD630("API Request Error")
UNKNOWN("알수없음"),
NO_REQUIRED_PARAM("필수 파라미터가 없습니다."),
INVALID_REQUEST("유효하지 않은 요청데이터 입니다."),
INVALID_REQUEST_URL("유효하지 않은 요청 URL 입니다."),
NOT_FOUND_BEAN("빈(bean)을 찾을 수 없습니다."),
NO_DATA_FOUND("자료를 찾을 수 없습니다."),
INVALID_DATA("유효하지 않은 데이터 입니다."),
API_COMM_ERROR("API 통신 오류가 발생 했습니다."),
INVALID_RESPONSE("유효하지 않은 응답 입니다."),
INVALID_RES_CODE("유효하지 않은 응답코드 입니다."),
INVALID_RES_DATA("유효하지 않은 응답데이터 입니다."),
RESPONSED_FAILURE_CODE("실패코드가 응답 되었습니다."),
FAILED_CREATE_RESPONSE_DATA("응답데이터 생성 실패"),
URL_ALREADY_CREATED("URL이 이미 생성 되었습니다."),
PAYMENT_ALREADY_CMPLTED("결제가 완료된 자료 입니다."),
SERVICE_NOT_SUPPORTED("지원하지 않는 서비스 입니다."),
ERR401("필수 파라미터가 없습니다."),
ERR402("파라미터 유효성 검증 오류"),
ERR403("잘못된 파라미터 입니다."),
ERR404("일치하는 자료가 없습니다."),
ERR405("잘못된 요청 값."),
ERR410("필수값 없음"),
ERR411("잘못된 JSON 포맷 문자열"),
ERR500("서버 오류"),
ERR501("HttpServer 오류"),
ERR502("HttpClient 오류"),
ERR503("RestClient 오류"),
ERR504("요청 데이터 Json 파싱 오류"),
ERR505("응답 데이터 Json 파싱 오류"),
ERR506("Hash 생성 오류"),
ERR507("유효하지 않은 데이터"),
ERR511("JSON 형식으로 변환 실패"),
ERR512("JSON Parsing Fail"),
ERR513("Services Not Supported"),
ERR521("방화벽 설정 오류"),
ERR540("중복된 데이터"),
ERR600("API 오류"),
ERR601("API서버 응답 오류"),
ERR602("API서버 내부 오류"),
ERR603("유효하지 않은 토큰(OTT) 값"),
ERR604("API 통신 실패"),
ERR610("응답 데이터에 필수값이 없음"),
ERR620("API Response Error"),
ERR699("API 기타 오류"),
ERR999("기타 오류"),
ERR901("권한 없음"),
ERR902("유효하지 않은 데이터"),
ERR903("처리 완료된 데이터"),
ERR904("CI 변환 실패"),
BILL401("duplicated \"bill_uid\""),
BILL402("duplicated \"biller_user_key\""),
BILL403("validation fail"),
BILL404("not found data"),
BILL405("invalid value"),
BILL501("json convert fail"),
BILL511("청구서 URL 생성 병렬처리 중 ERROR"),
BILL512("청구서 URL 생성 실패"),
BILL601("json parsing fail"),
BILL602("http status failure response"),
BILL603("response data is invalid"),
BILL604("client api failure response"),
BILL999("unknown error"),
ACPT402("유효성 검증 실패"),
ACPT404("일치하는 자료가 없습니다."),
ACPT405("접수 가능한 자료가 아닙니다."),
ACPT410("필수값 없음"),
ACPT411("잘못된 JSON 포맷 문자열"),
ACPT412("청구서 접수 실패"),
ACPT500("접수 처리 중 오류"),
ACPT511("JSON 형식으로 변환 실패"),
ACPT999("기타 오류"),
MAKE404("일치하는 자료가 없습니다."),
MAKE410("필수값 없음"),
MAKE411("잘못된 JSON 포맷 문자열"),
MAKE500("제작 처리 중 오류"),
MAKE511("JSON 형식으로 변환 실패"),
MAKE512("청구서 제작 실패"),
MAKE513("CI 제작 실패"),
MAKE521("데이터 생성 실패"),
MAKE610("응답 데이터에 필수값이 없음"),
MAKE620("API Response Error"),
MAKE630("API Request Error"),
SEND404("일치하는 자료가 없습니다."),
SEND405("잘못된 요청 값."),
SEND410("필수값 없음"),
SEND411("잘못된 JSON 포맷 문자열"),
SEND500("전송 처리 중 오류"),
SEND502("발송메시지 생성 실패"),
SEND511("JSON 형식으로 변환 실패"),
SEND601("토큰생성 실패"),
SEND620("API Response Error"),
SEND630("API Request Error"),
RSLT404("일치하는 자료가 없습니다."),
RSLT405("요청건수와 실제 자료의 건수가 상이 합니다."),
RSLT406("일부 자료가 결과반영에 실패 했습니다."),
RSLT407("전체 자료가 결과반영에 실패 했습니다."),
RSLT410("필수값 없음"),
RSLT411("잘못된 JSON 포맷 문자열"),
RSLT500("전송결과 처리 중 오류"),
RSLT502("요청메시지 생성 실패"),
RSLT511("JSON 형식으로 변환 실패"),
RSLT512("제공되지 않는 서비스 입니다."),
RSLT601("전송결과 조회 실패"),
RSLT620("API Response Error"),
RSLT630("API Request Error"),
RSLT999("기타 오류"),
PRVD404("일치하는 자료가 없습니다."),
PRVD410("필수값 없음"),
PRVD411("잘못된 JSON 포맷 문자열"),
PRVD500("상태갱신 처리 중 오류"),
PRVD511("JSON 형식으로 변환 실패"),
PRVD502("요청메시지 생성 실패"),
PRVD601("상태 조회 실패"),
PRVD620("API Response Error"),
PRVD630("API Request Error"),
;
private final String code;
private final String codeNm;
EnsErrCd(String codeNm) {
this.code = this.name();
this.codeNm = codeNm;

@ -92,8 +92,8 @@ public abstract class InitJpaRunner implements ApplicationRunner {
.kkoBpCsignYn(kkoBpCsignYn)
.kkoBpBillerCode(KKO_BP_BILLER_CODE)
.kkoBpAuthorization(KKO_BP_AUTHORIZATION)
.kkoBpCsignPrepayApi(kkoBpPrepayApi)
.kkoBpCsignPayResultApi(kkoBpPayResultApi)
.kkoBpPrepayApi(kkoBpPrepayApi)
.kkoBpPayResultApi(kkoBpPayResultApi)
.kkoAtBsid(KKO_AT_BSID)
.kkoAtPasswd(KKO_AT_PASSWD)

@ -1,4 +1,4 @@
package cokr.xit.ens.core.dialect;
package cokr.xit.ens.core.jpa.dialect;
import org.hibernate.dialect.MariaDB103Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;

@ -1,4 +1,4 @@
package cokr.xit.ens.core.dialect;
package cokr.xit.ens.core.jpa.dialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.StandardSQLFunction;

@ -0,0 +1,18 @@
package cokr.xit.ens.core.jpa.support;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter
public class BooleanToYnConverter implements AttributeConverter<Boolean, String> {
@Override
public String convertToDatabaseColumn(Boolean attribute) {
return (attribute != null && attribute) ? "Y" : "N";
}
@Override
public Boolean convertToEntityAttribute(String yn) {
return "Y".equalsIgnoreCase(yn);
}
}

@ -0,0 +1,48 @@
package cokr.xit.ens.core.model;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillSeCd;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Builder
@Getter
@Setter
@Schema(name = "EnsBillAcptReqDTO")
public class EnsBillAcptReqDTO {
// @NotNull(message = "청구서ID 사용 여부는 필수 입력값 입니다.")
// @Schema(hidden = true, required = true, title = "청구서ID 사용 여부", example = "false")
// private Boolean use_bill_uid;
@Schema(hidden = true, required = false, title = "청구서 유니크ID", example = " ")
@JsonProperty("billUid")
@JsonAlias({"bill_uid"})
@SerializedName(value = "billUid", alternate = {"bill_uid"})
private String billUid;
@NotNull(message = "청구서 타입은 필수 입력값 입니다.")
@Schema(required = true, title = "청구서 타입", example = "all")
@JsonProperty("billSe")
@JsonAlias({"bill_se"})
@SerializedName(value = "billSe", alternate = {"bill_se"})
private BillSeCd billSe;
@NotBlank(message = "빌러유저키는 필수 입력값 입니다.")
@Length(max = 40, message = "빌러유저키의 최대 길이를 초과 했습니다.")
@Schema(required = true, title = "기관에서 관리하는 해당 고객번호 혹은 계약번호", example = " ")
@JsonProperty("billerUserKey")
@JsonAlias({"biller_user_key"})
@SerializedName(value = "billerUserKey", alternate = {"biller_user_key"})
private String billerUserKey;
}

@ -1,6 +1,6 @@
package cokr.xit.ens.core.model.config;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillAcptReqDTO;
import cokr.xit.ens.core.model.EnsBillAcptReqDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -15,14 +15,14 @@ import java.util.Map;
@NoArgsConstructor
@Schema(name = "XitBaseProperty")
public class XitBaseProperty {
@Schema(required = false, title = "모바일페이지 노출 데이터", example = "{\"details\":[{\"title\":\"텍스트 타입\",\"item_type\":\"TEXT\",\"properties\":{\"use_toggle\":false},\"elements\":[\"test\",\"하하하\"]},{\"title\":\"PRE 텍스트 타입\",\"item_type\":\"PRE_TEXT\",\"properties\":{\"use_toggle\":false},\"elements\":\"가나다라마\\r\\nABCDEFGHI\\n1234567890\"},{\"title\":\"키-밸류 타입\",\"item_type\":\"KEY_VALUE\",\"properties\":{\"use_toggle\":false},\"elements\":[{\"key\":\"당월 부과 금액\",\"value\":\"200,203원\",\"level\":1},{\"key\":\"미납액\",\"value\":\"1,200원\",\"level\":1}]},{\"title\":\"테이블 타입\",\"item_type\":\"TABLE\",\"properties\":{\"use_toggle\":false,\"style\":{\"text_align\":[\"center\",\"left\",\"right\"]}},\"elements\":{\"head\":[\"항목\",\"당월금액\",\"전월대비\"],\"rows\":[[\"전기료\",\"1,000,000원\",\"+500,000\"],[\"수도료\",\"300,000원\",\"-100,000\"]]}},{\"title\":\"이미지 타입\",\"item_type\":\"IMAGE\",\"print_type\":\"이미지출력타입(공백: img태그(default), SLIDE: 슬라이드 기능 적용)\",\"properties\":{\"use_toggle\":false},\"elements\":[{\"링크 이미지\":\"http://www.xit.co.kr/....\"},{\"Base64 이미지\":\"data:image/png;base64,iVBORw0KGgoAAAAN....\"}]},{\"title\":\"링크버튼 타입\",\"item_type\":\"BUTTON\",\"link_url\":\"https://www.naver.com\"},{\"title\":\"결제버튼 타입\",\"item_type\":\"PAY_BUTTON\",\"properties\":{\"billSe\":\"bpKko\"}}]}")
@Schema(required = false, title = "모바일페이지 노출 데이터", example = "{\"details\":[{\"title\":\"텍스트 타입\",\"item_type\":\"TEXT\",\"properties\":{\"use_toggle\":false,\"style\":{\"highlight\":{\"하하하\":{\"use-clipboard\":true,\"font-size\":\"large\",\"font-color\":\"red\",\"font-weight\":\"bold\",\"font-style\":\"italic\"}}},\"hyperlink\":[\"http://www.naver.com\",\"http://www.xit.co.kr\"]},\"elements\":[\"test\",\"하하하\"]},{\"title\":\"PRE 텍스트 타입\",\"item_type\":\"PRE_TEXT\",\"properties\":{\"use_toggle\":false,\"style\":{\"highlight\":{\"다라마\":{\"use-clipboard\":true,\"font-size\":\"large\",\"font-color\":\"red\",\"font-weight\":\"bold\",\"font-style\":\"italic\"},\"1111-23123-12313\":{\"use-clipboard\":false,\"font-size\":\"large\",\"font-color\":\"red\",\"font-weight\":\"bold\",\"font-style\":\"italic\"}}},\"hyperlink\":[\"http://www.naver.com\",\"http://www.xit.co.kr\"]},\"elements\":\"가나다라마\\r\\nABCDEFGHI\\n1234567890\\n1111-23123-12313 카카오\\n카카오뱅크\\nhttp://www.naver.com\"},{\"title\":\"키-밸류 타입\",\"item_type\":\"KEY_VALUE\",\"properties\":{\"use_toggle\":false,\"style\":{\"highlight\":{\"액\":{\"font-size\":\"large\",\"font-color\":\"red\",\"font-weight\":\"bold\",\"font-style\":\"italic\"}}},\"hyperlink\":[\"http://www.naver.com\",\"http://www.xit.co.kr\"]},\"elements\":[{\"key\":\"당월 부과 금액\",\"value\":\"200,203원\",\"level\":1},{\"key\":\"미납액\",\"value\":\"1,200원\",\"level\":1}]},{\"title\":\"테이블 타입\",\"item_type\":\"TABLE\",\"properties\":{\"use_toggle\":false,\"style\":{\"text_align\":[\"center\",\"left\",\"right\"],\"highlight\":{\"전기료\":{\"font-size\":\"large\",\"font-color\":\"red\",\"font-weight\":\"bold\",\"font-style\":\"italic\"}}},\"hyperlink\":[\"http://www.naver.com\",\"http://www.xit.co.kr\"]},\"elements\":{\"head\":[\"항목\",\"당월금액\",\"전월대비\"],\"rows\":[[\"전기료\",\"1,000,000원\",\"+500,000\"],[\"수도료\",\"300,000원\",\"-100,000\"]]}},{\"title\":\"이미지 타입\",\"item_type\":\"IMAGE\",\"print_type\":\"이미지출력타입(공백: img태그(default), SLIDE: 슬라이드 기능 적용)\",\"properties\":{\"use_toggle\":false},\"elements\":[{\"key\":\"링크 이미지\",\"value\":\"http://www.xit.co.kr/....\"},{\"key\":\"Base64 이미지\",\"value\":\"data:image/png;base64,iVBORw0KGgoAAAAN....\"}]},{\"title\":\"링크버튼 타입\",\"item_type\":\"BUTTON\",\"link_url\":\"https://www.naver.com\"},{\"title\":\"결제버튼 타입\",\"item_type\":\"PAY_BUTTON\"}]}")
private Map<String, List<Map<String, Object>>> mbl_page_data;
@Schema(required = false, title = "템플릿 메시지 데이터", example = "{\"#{TARGET_NAME}\":\"홍길동\",\"#{CAR_NO}\":\"12더1234\",\"#{HISTORY}\":\"2022-01-01\",\"#{FEE}\":\"1000\",\"#{YYYY}\":\"2022\",\"#{MM}\":\"03\",\"#{DD}\":\"30\",\"#{BANK}\":\"기업\",\"#{ACCOUNT}\":\"311-063233-01-123\",\"#{HOMEPAGE}\":\"http://www.xit.co.kr\",\"#{REP_CALL_NO}\":\"070-4490-7404\"}")
private Map<String, String> tmplt_msg_data;
@Valid
private BillAcptReqDTO bill_acpt_data;
private EnsBillAcptReqDTO bill_acpt_data;
}

@ -40,6 +40,7 @@ public class CmmnUtil {
* :resultMsg =>
* :responseEntity => api
* </pre>
*
* @param method
* @param url
* @param param
@ -47,7 +48,6 @@ public class CmmnUtil {
* @return Map<String, Object>
* @author:
* @date: 2021. 8. 4.
* @apiNote: https://e2e2e2.tistory.com/15
*/
public static Map<String, Object> callApi(HttpMethod method, String url, String param, HttpHeaders headers) {
log.debug("param =======================");
@ -60,6 +60,7 @@ public class CmmnUtil {
String resultMsg = EnsErrCd.OK.getCodeNm();
try {
HttpEntity<?> entity = null;
UriComponents uri = null;
switch (method) {
@ -83,17 +84,23 @@ public class CmmnUtil {
}
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
RestTemplate restTemplate = new RestTemplate(factory);
responseEntity = restTemplate.exchange(uri.toString(), method, entity, String.class);
} catch (HttpServerErrorException e) {
// 코드: responseEntity.getStatusCodeValue()
// 메시지: responseEntity.getStatusCode()
} catch (
HttpServerErrorException e) {
result = EnsErrCd.ERR501.getCode();
resultMsg = String.format("%s [사유: %s]", EnsErrCd.ERR501.getCodeNm(), e.getMessage());
log.error(String.format("call API 서버오류[url =>%s param => %s error => %s]", url, param, e.getMessage()));
} catch (HttpClientErrorException e) {
} catch (
HttpClientErrorException e) {
result = EnsErrCd.ERR502.getCode();
resultMsg = String.format("%s [사유: %s]", EnsErrCd.ERR502.getCodeNm(), e.getMessage());
log.error(String.format("call API 클라이언트오류[url =>%s param => %s error => %s]", url, param, e.getMessage()));
@ -116,9 +123,9 @@ public class CmmnUtil {
}
/**
* <pre> : Json String .</pre>
*
* @param obj
* @return String
* @author:
@ -127,8 +134,10 @@ public class CmmnUtil {
public static String toJsonString(Object obj) {
return toJsonString(obj, JsonInclude.Include.ALWAYS);
}
/**
* <pre> : Json String .</pre>
*
* @param obj
* @param type JsonInclude.Include
* <pre>
@ -157,34 +166,44 @@ public class CmmnUtil {
return result;
}
/**
* <pre> : jsonString Object </pre>
* @param clz
* @param jsonStr
* @return Object
* @author:
* @date: 2021. 12. 23.
*/
public static Object jsonStringtoObj(Class clz, String jsonStr) {
Object result = null;
try {
ObjectMapper mapper = new ObjectMapper();
result = mapper.readValue(jsonStr, clz.getClass());
} catch (JsonProcessingException e) {
throw new RuntimeException(String.format("jsonString -> obj converting fail:: %s", e.getMessage()), e);
}
return result;
}
// /**
// * <pre>메소드 설명: jsonString을 Object로 반환한다</pre>
// * @param clz
// * @param jsonStr
// * @return Object 요청처리 후 응답객체
// * @author: 박민규
// * @date: 2021. 12. 23.
// */
// public static Object jsonStringtoObj(Class clz, String jsonStr) {
// Object result = null;
//
// try {
// ObjectMapper mapper = new ObjectMapper();
// result = mapper.readValue(jsonStr, clz.getClass());
// } catch (JsonProcessingException e) {
// throw new RuntimeException(String.format("jsonString -> obj converting fail:: %s", e.getMessage()), e);
// }
//
// return result;
// }
public static boolean isEmpty(Object obj) {
if (obj == null) return true;
if ((obj instanceof String) && (((String)obj).trim().length() == 0)) { return true; }
if (obj instanceof Map) { return ((Map<?, ?>) obj).isEmpty(); }
if (obj instanceof Map) { return ((Map<?, ?>)obj).isEmpty(); }
if (obj instanceof List) { return ((List<?>)obj).isEmpty(); }
if (obj instanceof Object[]) { return (((Object[])obj).length == 0); }
if ((obj instanceof String) && (((String) obj).trim().length() == 0)) {
return true;
}
if (obj instanceof Map) {
return ((Map<?, ?>) obj).isEmpty();
}
if (obj instanceof Map) {
return ((Map<?, ?>) obj).isEmpty();
}
if (obj instanceof List) {
return ((List<?>) obj).isEmpty();
}
if (obj instanceof Object[]) {
return (((Object[]) obj).length == 0);
}
return false;
}

@ -15,13 +15,9 @@ import java.util.Optional;
public class DateUtil {
/**
* <pre> : (: milliesecond) .</pre>
*
* @param millisec
* @param fmt
* @return String
@ -33,8 +29,10 @@ public class DateUtil {
return null;
return absTimeToDate(millisec, fmt);
}
/**
* <pre> : (: second) .</pre>
*
* @param sec
* @param fmt
* @return String
@ -44,8 +42,10 @@ public class DateUtil {
public static String absTimeSecToDate(int sec, String fmt) {
return absTimeSecToDate(sec * 1L, fmt);
}
/**
* <pre> : (: second) .</pre>
*
* @param sec
* @param fmt
* @return String
@ -57,8 +57,10 @@ public class DateUtil {
return null;
return absTimeToDate(sec * 1000L, fmt);
}
/**
* <pre> : (: ms) .</pre>
*
* @param millionSec
* @param fmt
* @return String
@ -77,6 +79,7 @@ public class DateUtil {
/**
* <pre> : (: sec) .</pre>
*
* @param expireDt (yyyyMMddHHmmss)
* @return Long
* @author:
@ -85,8 +88,10 @@ public class DateUtil {
public static Long dateToAbsTimeSec(String expireDt) {
return dateToAbsTime(expireDt) / 1000;
}
/**
* <pre> : (: sec) .</pre>
*
* @param year
* @param month
* @param day
@ -100,8 +105,10 @@ public class DateUtil {
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:
@ -132,8 +139,10 @@ public class DateUtil {
}
}
/**
* <pre> : (: ms) .</pre>
*
* @param year
* @param month
* @param day
@ -158,10 +167,9 @@ public class DateUtil {
}
/**
* <pre> : (: ms) .</pre>
*
* @param expireDt (yyyyMMddHHmmss)
* @return Long
* @author:
@ -192,8 +200,10 @@ public class DateUtil {
}
}
/**
* <pre> : (: ms) .</pre>
*
* @param year
* @param month
* @param day
@ -215,8 +225,10 @@ public class DateUtil {
return dateToRelTime(LocalDateTime.of(year, month, day, hour, minute, sec));
}
/**
* <pre> : (: ms) .</pre>
*
* @param date
* @return Long
* @author:
@ -232,6 +244,7 @@ public class DateUtil {
/**
* <pre> : (: ms) .</pre>
*
* @param days
* @return Long
* @author:
@ -244,6 +257,7 @@ public class DateUtil {
/**
* <pre> : (yyyyMMddHHmmss) LocalDateTime .</pre>
*
* @param yyyyMMddHHmmss
* @return Long
* @author:
@ -272,6 +286,7 @@ public class DateUtil {
/**
* (date) (day) .
*
* @param fromDate
* @param toDate
* @return
@ -279,8 +294,10 @@ public class DateUtil {
public static int daysByFromBetweenTo(Date fromDate, Date toDate) {
return daysByFromBetweenTo(fromDate.getTime(), toDate.getTime());
}
/**
* (date) (day) .
*
* @param fromDate
* @param toDate
* @return
@ -288,8 +305,10 @@ public class DateUtil {
public static int daysByFromBetweenTo(LocalDateTime fromDate, LocalDateTime toDate) {
return daysByFromBetweenTo(Timestamp.valueOf(fromDate).getTime(), Timestamp.valueOf(toDate).getTime());
}
/**
* (sec) (day) .
*
* @param fromSec
* @param toSec
* @return
@ -297,8 +316,10 @@ public class DateUtil {
public static int daysByFromBetweenTo(int fromSec, int toSec) {
return daysByFromBetweenTo(fromSec * 1000L, toSec * 1000L);
}
/**
* (ms) (day) .
*
* @param fromMs
* @param toMs
* @return
@ -306,8 +327,10 @@ public class DateUtil {
public static int daysByFromBetweenTo(long fromMs, long toMs) {
return (int) ((toMs - fromMs) / (24 * 60 * 60 * 1000));
}
/**
* (ms) (second) .
*
* @param fromDate
* @param toDate
* @toDate
@ -315,8 +338,10 @@ public class DateUtil {
public static int secByFromBetweenTo(LocalDateTime fromDate, LocalDateTime toDate) {
return secByFromBetweenTo(Timestamp.valueOf(fromDate).getTime(), Timestamp.valueOf(toDate).getTime());
}
/**
* (ms) (second) .
*
* @param fromMs
* @param toMs
* @return
@ -328,13 +353,16 @@ public class DateUtil {
/**
* (sec) (day) .
*
* @return
*/
public static int secToDays(int sec) {
return msToDays(sec * 1000L);
}
/**
* (ms) (day) .
*
* @return
*/
public static int msToDays(long ms) {
@ -344,6 +372,7 @@ public class DateUtil {
/**
* (sec) .
*
* @param sec
* @param pattern
* @return
@ -358,8 +387,10 @@ public class DateUtil {
return new SimpleDateFormat(pattern).format(date);
}
/**
* (sec) .
*
* @param sec
* @param pattern
* @return

@ -19,6 +19,7 @@ public class IdGenerator {
} while (!currentTime.compareAndSet(prev, next));
return next;
}
public static Long getCurrentTimeSec() {
return IdGenerator.getCurrentTimeMs() / 1000L;
}

@ -1,19 +1,17 @@
package cokr.xit.ens.core.utils;
import java.util.Base64;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Base64.Decoder;
import org.springframework.util.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import lombok.Builder;
import lombok.Getter;
import org.springframework.util.StringUtils;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
@Getter
public class JwtUtil {
@ -64,10 +62,12 @@ public class JwtUtil {
public JwtUtil(String secretKey, String jwt) {
this.verify(secretKey, jwt, Algorithm.HMAC512(secretKey.getBytes()));
}
@Builder(builderClassName = "verifyBuilderByAlgorithm", builderMethodName = "verifyBuilderByAlgorithm")
public JwtUtil(String secretKey, String token, Algorithm algorithm) {
this.verify(secretKey, token, algorithm);
}
@SuppressWarnings("deprecation")
private void verify(String secretKey, String jwt, Algorithm algorithm) {
if (StringUtils.isEmpty(secretKey))

@ -7,7 +7,8 @@ import java.util.*;
public class MapDeserailizer implements JsonDeserializer<Map<String, Object>> {
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Map<String, Object> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
return (Map<String, Object>) read(json);

@ -1,18 +1,16 @@
package cokr.xit.ens.core.utils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import lombok.Builder;
import lombok.Getter;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.springframework.util.StringUtils;
import lombok.Builder;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@Builder
@Getter
@ -27,6 +25,7 @@ public class RequireValidator {
* <pre> :
* -. message .
* </pre>
*
* @return RequireValidator
* @author:
* @date: 2021. 8. 6.
@ -56,6 +55,7 @@ public class RequireValidator {
* -.message null Exception .
* </pre>
* void
*
* @author:
* @date: 2021. 8. 6.
*/

@ -1,38 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoAcptReqVO;
import com.fasterxml.jackson.annotation.JsonAlias;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@Builder
@Getter
@Setter
@Schema(name = "BillAcptReqDTO")
public class BillAcptReqDTO {
@NotNull(message = "청구서ID 사용 여부는 필수 입력값 입니다.")
@Schema(required = true, title = "청구서ID 사용 여부", example = "false")
private Boolean use_bill_uid;
@Schema(required = false, title = "청구서 유니크ID", example = " ")
private String bill_uid;
@NotNull
@Schema(required = true, title = "청구서 타입", example = "all")
private BillSeCd bill_se;
@Valid
@JsonAlias({"bill_kko"})
private BillKkoAcptReqVO bill_kko;
// @Valid
// @JsonAlias({"bill_nv"})
// private BillNvAcptReqVO bill_nv;
}

@ -1,6 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill;
public interface BillAcptReqData<T> {
T get();
}

@ -1,127 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.monitor.slack.event.MonitorEvent;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.Bill;
import cokr.xit.ens.modules.common.monitor.MessageByBill;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
public abstract class BillMakerSupport implements Consumer<List<Bill>>, Function<List<Bill>, EnsResponseVO> {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Transactional
@Override
public void accept(List<Bill> bills) {
try {
Lists.partition(filter(bills), 500).stream()
.forEach(partBillUids -> {
List<Bill> partBills = findBillsByBillUidsAndNotExists(partBillUids);
acceptProc(partBills);
});
} catch (EnsException e) {
throw e;
} catch (Exception e) {
throw new EnsException(EnsErrCd.BILL999, e.getMessage());
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public EnsResponseVO apply(List<Bill> bills) {
try {
if (CmmnUtil.isEmpty(bills))
return EnsResponseVO.okBuilder().build();
int cntTotFail = Lists.partition(filter(bills), 500).stream()
.map(partBillUids -> {
List<Bill> partBills = findBillsByBillUidsAndUrlIsNull(partBillUids);
if (partBills.size() == 0)
return 0;
return generateUrlProc(partBills);
})
.reduce(Integer::sum)
.get();
if (cntTotFail == 0)
return EnsResponseVO.okBuilder().build();
else
return EnsResponseVO.errBuilder()
.errCode(EnsErrCd.BILL512)
.errMsg(String.format("총 %d건 중 %d건 생성 실패", bills.size(), cntTotFail))
.build();
} catch (EnsException e) {
return EnsResponseVO.errBuilder()
.errCode(e.getErrCd())
.errMsg(e.getMessage())
.build();
} catch (Exception e) {
return EnsResponseVO.errBuilder()
.errCode(EnsErrCd.BILL999)
.errMsg(e.getMessage())
.build();
}
}
abstract protected BillSeCd getBillSeCd();
abstract protected List<String> filter(List<Bill> bills);
/**
*
* @param bills
* @throws EnsException
*/
abstract protected void acceptProc(List<Bill> bills) throws EnsException;
/**
*
* @param billUids
* @return
*/
abstract protected List<Bill> findBillsByBillUidsAndNotExists(List<String> billUids);
/**
* URL
* @param bills
* @return
*/
abstract protected int generateUrlProc(List<Bill> bills);
/**
* URL
* @param billUids
* @return
*/
abstract protected List<Bill> findBillsByBillUidsAndUrlIsNull(List<String> billUids);
protected void errSend(EnsErrCd ensErrCd, String message, Exception e) {
applicationEventPublisher.publishEvent(MonitorEvent.builder()
.message(MessageByBill.builder()
.oClass(getClass().getSimpleName() + "." + new Throwable().getStackTrace()[0].getMethodName())
.billSeCd(getBillSeCd())
.errCd(ensErrCd)
.message(message + "\n" + CmmnUtil.printStackTraceToString(e))
.build())
.build());
}
}

@ -1,8 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill;
public interface BillService<T, ACPTREQ, URLREQ> {
T accept(ACPTREQ acptreq);
T createUrl(URLREQ urlreq);
}

@ -1,6 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill;
public interface BillUrlReqData<T> {
T get();
}

@ -1,41 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.code;
import cokr.xit.ens.core.code.CodeMapperType;
/**
* <ul>
* <li> : API - </li>
* <li> : </li>
* <li>: 2022. 2. 15. 3:51:43
* </ul>
* @author
*/
public enum BillReqSeCd implements CodeMapperType {
ACPT("요청 접수")
,URL("청구서링크생성")
,REURL("청구서링크재생성")
,NOTICE("청구서조회")
,PREPAY("납부가능조회")
,PAYRSLT("납부결과전달")
;
private final String code;
private final String codeNm;
BillReqSeCd(String codeNm) {
this.code = this.name();
this.codeNm = codeNm;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getCodeNm() {
return this.codeNm;
}
}

@ -1,50 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.entity;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillSeCd;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
//@Inheritance(strategy = InheritanceType.JOINED)
//@DiscriminatorColumn(name = "dtype")
//@DiscriminatorValue("master")
@Table(name = "ens_bill", schema = "", catalog = "")
public class Bill extends BillEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "Bill_Generator")
@TableGenerator(table = "ens_seq_generator", name = "Bill_Generator"
, pkColumnName = "seq_name", pkColumnValue = "Bill_id"
, initialValue = 0, allocationSize = 200)
private Long billId;
@Enumerated(EnumType.STRING)
@Column(name = "bill_se_cd")
private BillSeCd billSeCd;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "org_cd")
@Setter
private OrgMng orgMng;
@Column(name = "doc_bill_kko", nullable = true)
@Lob
private String docBillKko;
@Column(name = "doc_bill_nv", nullable = true)
@Lob
private String docBillNv;
}

@ -1,9 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.repository;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.BillHist;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BillHistRepository extends JpaRepository<BillHist, Long> {
}

@ -1,10 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.repository;
public interface BillSeRepository {
String findUrlByBillUid(String billUid);
}

@ -21,7 +21,7 @@ import java.nio.charset.StandardCharsets;
@Slf4j
@Component
@Profile({"!local-test"})
public class BillKkoApi implements BillKkoApiSpec {
public class BillKkoPayApi implements BillKkoPayApiSpec {
@Value("${contract.kakao.pay.bill.dozn.host}")
private String HOST;
@ -30,59 +30,6 @@ public class BillKkoApi implements BillKkoApiSpec {
@Value("${contract.kakao.pay.bill.dozn.api.reurl}")
private String API_RE_URL;
/**
*
*
* @param billerCode
* @param authorization
* @param jsonStr
* @return
*/
@Override
public ResponseEntity<String> url(String billerCode, String authorization, String jsonStr) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
headers.set("X-Xit-BillerCode", billerCode);
StringBuilder url = new StringBuilder();
url.append(this.HOST)
.append(this.API_URL.replace("{billerCode}", billerCode == null ? "" : billerCode));
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
return resp;
}
/**
*
*
* @param billerCode
* @param authorization
* @param jsonStr
* @return
*/
@Override
public ResponseEntity<String> reUrl(String billerCode, String authorization, String jsonStr) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
headers.set("X-Xit-BillerCode", billerCode);
StringBuilder url = new StringBuilder();
url.append(this.HOST)
.append(this.API_RE_URL.replace("{billerCode}", billerCode == null ? "" : billerCode));
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
return resp;
}
/**
* <pre> : API
@ -95,7 +42,6 @@ public class BillKkoApi implements BillKkoApiSpec {
* @return ResponseEntity
* @author:
* @date: 2021. 8. 4.
* @apiNote: https://e2e2e2.tistory.com/15
*/
private ResponseEntity<String> callApi(HttpMethod method, String url, String body, HttpHeaders headers) {
@ -128,9 +74,8 @@ public class BillKkoApi implements BillKkoApiSpec {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(2000);
// factory.setReadTimeout(2000);
factory.setReadTimeout(10000);
factory.setConnectTimeout(5000);
factory.setReadTimeout(60000);
RestTemplate restTemplate = new RestTemplate(factory);
sb.append("\n url => " + uri.toString())
.append("\n method => " + method)
@ -165,4 +110,57 @@ public class BillKkoApi implements BillKkoApiSpec {
}
/**
*
*
* @param billerCode
* @param authorization
* @param jsonStr
* @return
*/
@Override
public ResponseEntity<String> url(String billerCode, String authorization, String jsonStr) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
headers.set("X-Xit-BillerCode", billerCode);
StringBuilder url = new StringBuilder();
url.append(this.HOST)
.append(this.API_URL.replace("{billerCode}", billerCode == null ? "" : billerCode));
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
return resp;
}
/**
*
*
* @param billerCode
* @param authorization
* @param jsonStr
* @return
*/
@Override
public ResponseEntity<String> reUrl(String billerCode, String authorization, String jsonStr) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
headers.set("X-Xit-BillerCode", billerCode);
StringBuilder url = new StringBuilder();
url.append(this.HOST)
.append(this.API_RE_URL.replace("{billerCode}", billerCode == null ? "" : billerCode));
ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);
return resp;
}
}

@ -2,7 +2,7 @@ package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.api;
import org.springframework.http.ResponseEntity;
public interface BillKkoApiSpec {
public interface BillKkoPayApiSpec {
/**
*

@ -16,7 +16,7 @@ import java.nio.charset.StandardCharsets;
@Slf4j
@Component
@Profile({"local-test"})
public class BillKkoApiTest implements BillKkoApiSpec {
public class BillKkoPayApiTest implements BillKkoPayApiSpec {
@Value("${contract.kakao.pay.bill.dozn.host}")
private String HOST;

@ -1,69 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.BillEntity;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Entity
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ens_bill_kko", schema = "", catalog = "")
@Schema(name = "BillKko")
public class BillKko extends BillEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "BillKko_Generator")
@TableGenerator(table = "ens_seq_generator", name = "BillKko_Generator"
, pkColumnName = "seq_name", pkColumnValue = "BillKko_id"
, initialValue = 0, allocationSize = 200)
@Schema(required = true, title = "PK", example = " ")
private Long billId;
@Schema(required = true, title = "기관에서 관리하는 해당 고객번호 혹은 계약번호", example = " ")
@Column(name = "biller_user_key", nullable = false, length = 40)
private String billerUserKey;
@Schema(required = false, title = "청구 연월", example = " ")
@Column(name = "billed_year_month", nullable = true)
private String billedYearMonth;
@Schema(required = false, title = "동일 고객번호 구분 값", example = " ")
@Column(name = "ordinal", nullable = true)
private String ordinal;
@Schema(required = false, title = "개별 청구서를 식별하는 키 값", example = " ")
@Column(name = "biller_notice_key", nullable = true)
private String billerNoticeKey;
@Schema(required = true, title = "URL 만료일", example = "20200130235959")
@Column(name = "expire_at", nullable = false)
private String expireAt;
@Schema(required = false, title = "API 호출 시 함께 전달할 JSON형태의 문자열", example = " ")
@Column(name = "parameters", nullable = true)
@Lob
private String parameters;
@Schema(required = false, title = "청구서조회/납부가능여부/납부결과 API Url정보 JSON형태의 문자열", example = " \"custom_url\": {\n" +
" \"notice_url\" : \" https://test-api.dozn.co.kr/kakao/notice\",\n" +
" \"prepay_url\": \"https://test-api.dozn.co.kr/kakao/prepay\",\n" +
" \"pay_result_url\": \" https://test-api.dozn.co.kr/kakao/pay-result\"\n" +
" }")
@Column(name = "custom_url", nullable = true, length = 500)
private String customUrl;
@Schema(required = false, title = "청구서URL", example = " ")
@Column(name = "url", nullable = true)
@Setter
private String url;
@Embedded
@Setter
private FieldError error;
}

@ -0,0 +1,117 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.BillBaseEntity;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Entity
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ens_bill_kko", schema = "", catalog = "")
@Schema(name = "BillKkoPay")
public class BillKkoPay extends BillBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "BillKko_Generator")
@TableGenerator(table = "ens_seq_generator", name = "BillKko_Generator"
, pkColumnName = "seq_name", pkColumnValue = "BillKko_id"
, initialValue = 0, allocationSize = 200)
@Schema(required = true, title = "PK", example = " ")
private Long billId;
@Schema(required = false, title = "청구 연월", example = " ")
@Column(name = "billed_year_month", nullable = true)
@Setter
private String billedYearMonth;
@Schema(required = false, title = "동일 고객번호 구분 값", example = " ")
@Column(name = "ordinal", nullable = true)
@Setter
private String ordinal;
@Schema(required = false, title = "개별 청구서를 식별하는 키 값", example = " ")
@Column(name = "biller_notice_key", nullable = true)
@Setter
private String billerNoticeKey;
@Schema(required = false, title = "URL 만료일", example = "20200130235959")
@Column(name = "expire_at", nullable = true)
@Setter
private String expireAt;
@Schema(required = false, title = "API 호출 시 함께 전달할 JSON형태의 문자열", example = " ")
@Column(name = "parameters", nullable = true)
@Lob
@Setter
private String parameters;
@Schema(required = false, title = "청구서조회/납부가능여부/납부결과 API Url정보 JSON형태의 문자열", example = " \"custom_url\": {\n" +
" \"notice_url\" : \" https://test-api.dozn.co.kr/kakao/notice\",\n" +
" \"prepay_url\": \"https://test-api.dozn.co.kr/kakao/prepay\",\n" +
" \"pay_result_url\": \" https://test-api.dozn.co.kr/kakao/pay-result\"\n" +
" }")
@Column(name = "custom_url", nullable = true, length = 500)
@Setter
private String customUrl;
@Schema(required = false, title = "청구서URL", example = " ")
@Column(name = "url", nullable = true)
@Setter
private String url;
/* =====================================
* - PayNotice
===================================== */
@Schema(required = false, title = "청구서명", example = "테스트청구서")
@Column(name = "title", nullable = true)
@Setter
private String title;
@Schema(required = false, title = "납부 요청금액", example = "1000")
@Column(name = "amount", nullable = true)
@Setter
private Integer amount;
@Schema(required = false, title = "비과세 금액", example = "0")
@Column(name = "tax_free_amount", nullable = true)
@Setter
private Integer taxFreeAmount;
@Schema(required = false, title = "부가세 금액", example = "0")
@Column(name = "vat_amount", nullable = true)
@Setter
private Integer vatAmount;
@Schema(required = false, title = "납기 안내타입", example = "D1")
@Column(name = "expire_type", nullable = true, length = 10)
@Setter
private String expireType;
@Schema(required = false, title = "첫번째 납기일", example = "20230212")
@Column(name = "pay_expire_date", nullable = true, length = 8)
@Setter
private String payExpireDate;
@Schema(required = false, title = "두번째 납기일", example = "20230212")
@Column(name = "second_pay_expire_date", nullable = true, length = 8)
@Setter
private String secondPayExpireDate;
@Schema(required = false, title = "계좌송금수단 사용 시 계좌정보", example = " ")
@Lob
@Column(name = "bank_accounts", nullable = true)
@Setter
private String bankAccounts;
@Schema(required = false, title = "청구서 상세정보", example = " ")
@Lob
@Column(name = "details", nullable = true)
@Setter
private String details;
@Schema(required = false, title = "결제일시(YYYYMMDDHH24MISS)", example = "20190220161656")
@Column(name = "last_paid_at", nullable = true, length = 14)
@Setter
private String lastPaidAt;
@Schema(required = false, title = "결제번호", example = "2748877")
@Column(name = "last_pay_id", nullable = true)
@Setter
private Integer lastPayId;
@Embedded
@Setter
private FieldError error;
}

@ -1,12 +1,8 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.repository;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.BillKko;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.BillKkoPay;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface BillKkoRepository extends JpaRepository<BillKko, Long>, BillKkoRepositoryCustom {
Optional<BillKko> findByBillUid(String billUid);
public interface BillKkoPayRepository extends JpaRepository<BillKkoPay, Long> {
}

@ -1,11 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.repository;
import java.util.List;
public interface BillKkoRepositoryCustom {
List<String> findBillUidsByBillUidIn(List<String> billUids);
List<String> findBillerUserKeysByBillerUserKeyIn(List<String> billerUserKeys);
}

@ -1,42 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.repository;
import com.google.common.collect.Lists;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import java.util.ArrayList;
import java.util.List;
import static cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.QBillKko.billKko;
@RequiredArgsConstructor
public class BillKkoRepositoryImpl implements BillKkoRepositoryCustom {
private final JPAQueryFactory query;
@Override
public List<String> findBillUidsByBillUidIn(List<String> billUids) {
List<String> result = new ArrayList<>();
Lists.partition(billUids, 1000)
.forEach(ids -> result.addAll(
query.select(billKko.billUid)
.from(billKko)
.where(billKko.billUid.in(ids))
.fetch())
);
return result;
}
@Override
public List<String> findBillerUserKeysByBillerUserKeyIn(List<String> billerUserKeys) {
List<String> result = new ArrayList<>();
Lists.partition(billerUserKeys, 1000)
.forEach(ids -> result.addAll(
query.select(billKko.billerUserKey)
.from(billKko)
.where(billKko.billerUserKey.in(ids))
.fetch())
);
return result;
}
}

@ -1,26 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.repository;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.entity.repository.BillSeRepository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import static cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.QBillKko.billKko;
@Repository(value = "bpKko")
@RequiredArgsConstructor
public class BillSeKkoRepositoryImpl implements BillSeRepository {
private final JPAQueryFactory query;
@Override
public String findUrlByBillUid(String billUid) {
String url = query.select(billKko.url)
.from(billKko)
.where(billKko.billUid.eq(billUid)
.and(billKko.url.isNotNull())
)
.fetchOne();
return url;
}
}

@ -1,32 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import com.fasterxml.jackson.annotation.JsonAlias;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
@Builder
@Getter
@Setter
@Schema(name = "BillKkoAcptReqDTO")
public class BillKkoAcptReqDTO {
@NotBlank(message = "(계약정보)빌러코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)빌러코드", example = "LIF378880088002")
@JsonAlias({"biller_code"})
private String billerCode;
@NotBlank(message = "(계약정보)허가코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)허가코드", example = "LG7upsMTsXbQiMGP4htZi/IXS7LJvEOmAx2HmY6X6Q8jh1dpv6vgNxbA4a4H2n3r")
@JsonAlias({"authorization"})
private String authorization;
@Valid
@JsonAlias({"documents"})
private BillKkoAcptReqVO documents;
}

@ -1,68 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.config.CustomUrl;
import com.fasterxml.jackson.annotation.JsonAlias;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.Map;
@Builder
@Getter
@Schema(name = "BillKkoAcptReqVO")
public class BillKkoAcptReqVO {
@Length(max = 45, message = "청구서 유니크 아이디의 최대 길이를 초과 했습니다.")
@Schema(required = false, title = "청구서 유니크 아이디", example = " ")
@JsonAlias({"bill_uid"})
@Setter
private String billUid;
@NotEmpty(message = "계약번호는 필수 입력값 입니다.")
@Length(max = 50, message = "계약번호의 최대 길이를 초과 했습니다.")
@Schema(required = true, title = "기관에서 관리하는 해당 고객번호 혹은 계약번호", example = " ")
@JsonAlias({"biller_user_key"})
private String billerUserKey;
@Length(max = 6, message = "청구연월의 최대 길이를 초과 했습니다.")
@Schema(required = false, title = "청구 연월", example = "202203")
@JsonAlias({"billed_year_month"})
private String billedYearMonth;
@Length(max = 24, message = "고객번호구분값의 최대 길이를 초과 했습니다.")
@Schema(required = false, title = "동일 고객번호 구분 값", example = " ")
@JsonAlias({"ordinal"})
private String ordinal;
@Length(max = 80, message = "개별청구서식별키의 최대 길이를 초과 했습니다.")
@Schema(required = false, title = "개별 청구서를 식별하는 키 값", example = " ")
@JsonAlias({"biller_notice_key"})
private String billerNoticeKey;
@NotEmpty(message = "URL만료일은 필수 입력값 입니다.")
@Schema(required = true, title = "URL 만료일", example = "20200130235959")
@JsonAlias({"expire_at"})
private String expireAt;
// @Valid
// private Parameters parameters;
@Schema(required = false, title = "API 호출 시 함께 전달할 JSON형태의 문자열", example = "{\"some_param\": \"...\"}")
@JsonAlias({"parameters"})
private Map<String, String> parameters;
// " \"notice_url\" : \" https://test-api.dozn.co.kr/kakao/notice\",\n" +
// " \"prepay_url\": \"https:// test-api.dozn.co.kr/kakao/prepay\",\n" +
// " \"pay_result_url\": \" https:// test-api.dozn.co.kr/kakao/pay-result\"\n" +
// " }")
@Valid
@JsonAlias({"custom_url"})
private CustomUrl customUrl;
}

@ -10,8 +10,8 @@ import java.util.Map;
@Getter
@ToString
@EqualsAndHashCode
@Schema(name = "BillKkoPayResultDTO")
public class BillKkoPayResultDTO {
@Schema(name = "BillKkoPayResultData")
public class BillKkoPayResultData {
@Schema(required = true, title = "사용자 식별키", example = " ")
private String biller_user_key;

@ -1,25 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "BillKkoRsltFwdFailDTO")
public class BillKkoRsltFwdFailDTO {
@Schema(title = "기관코드", example = " ")
private String org_cd;
@Schema(title = "기관코드명", example = " ")
private String org_nm;
@Schema(title = "빌러유저키", example = " ")
private List<String> biller_user_key;
}

@ -1,18 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Builder
@Data
@Schema(name = "BillKkoRsltFwdFailSearchDTO")
public class BillKkoRsltFwdFailSearchDTO {
@Schema(title = "기관코드", example = "[]")
private List<String> schOrgCd;
@Schema(title = "기관코드명", example = "[]")
private List<String> schOrgNm;
}

@ -1,32 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import com.fasterxml.jackson.annotation.JsonAlias;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
@Builder
@Data
@Schema(name = "BillKkoUrlReqDTO")
public class BillKkoUrlReqDTO {
@NotBlank(message = "(계약정보)빌러코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)빌러코드", example = "LIF378880088002")
@JsonAlias({"biller_code"})
private String billerCode;
@NotBlank(message = "(계약정보)허가코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)허가코드", example = "LG7upsMTsXbQiMGP4htZi/IXS7LJvEOmAx2HmY6X6Q8jh1dpv6vgNxbA4a4H2n3r")
@JsonAlias({"authorization"})
private String authorization;
@NotNull(message = "청구서 유니크 아이디는 필수 입력값 입니다.")
@Schema(required = false, title = "청구서 유니크 아이디", example = " ")
@JsonAlias({"bill_uids"})
private List<String> billUids;
}

@ -1,33 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillReqSeCd;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Builder
@Data
@Schema(name = "BillKkoUrlReqVO")
public class BillKkoUrlReqVO {
@NotNull(message = "요청구분은 필수 입력값 입니다.")
@Schema(required = true, title = "요청구분", example = "URL")
private BillReqSeCd reqSe;
@NotBlank(message = "(계약정보)빌러코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)빌러코드", example = " ")
private String billerCode;
@NotBlank(message = "(계약정보)허가코드는 필수 입력값 입니다.")
@Schema(required = true, title = "(계약정보)허가코드", example = " ")
private String authorization;
@Length(max = 45, message = "청구서 유니크 아이디의 최대 길이를 초과 했습니다.")
@Schema(required = false, title = "청구서 유니크 아이디", example = " ")
private String billUid;
}

@ -1,114 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.presentation;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoRsltFwdFailSearchDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.impl.BillKkoClientServiceImpl;
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.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Tag(name = "BillKkoClientController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class BillKkoClientController {
private final BillKkoClientServiceImpl billKkoClientServiceImpl;
@Operation(summary = "납부결과 전달실패 자료 조회")
@GetMapping(value = "/bill/kko/fwd/fail/{orgCd}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> findAllByFwdFail(@PathVariable String orgCd) {
EnsResponseVO responseVO = billKkoClientServiceImpl.findBillerUserKeysByOrgCdAndPayresultFwdFail(orgCd);
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@Operation(summary = "납부결과 전달실패 자료 조회(일괄)")
@PostMapping(value = "/bill/kko/fwd/fail/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> findAllByFwdFailBulk(@RequestBody BillKkoRsltFwdFailSearchDTO searchDTO) {
EnsResponseVO responseVO = billKkoClientServiceImpl.findBillerUserKeysBySearchDTOAndPayresultFwdFail(searchDTO);
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "sample"
, value = "{ \"org_cd\" : \"EX_ORG001\", \"biller_user_key\" : [\"a1b2c3d4e5f6g7h8i9j0\", \"A1B2C3D4E5F6G7H8I9J0\"] }")
})
})
@ApiResponses({
@ApiResponse(responseCode = "200", content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Success Example..."
, summary = "Success"
, value = "{\n" +
"\"res_code\": \"OK\",\n" +
"\"message\": \"성공\",\n" +
"\"data\": null\n" +
"}"
)
})
})
})
@Operation(summary = "납부 결과 재전달")
@PostMapping(value = "/bill/kko/fwd/pay-reuslt", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> fwdPayRslt(@RequestBody Map<String, Object> mParam) {
EnsResponseVO responseVO = billKkoClientServiceImpl.fwdPayRslt((String) mParam.get("org_cd"), (List<String>) mParam.get("biller_user_key"));
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "sample"
, value = "{ \"targets\" : [{\"org_cd\" : \"EX_ORG001\", \"biller_user_key\" : [\"a1b2c3d4e5f6g7h8i9j0\", \"A1B2C3D4E5F6G7H8I9J0\"]}, {\"org_cd\" : \"0001\", \"biller_user_key\" : [\"fffffffffffffffffffff\"]} ] }")
})
})
@ApiResponses({
@ApiResponse(responseCode = "200", content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Success Example..."
, summary = "Success"
, value = "{\n" +
"\"res_code\": \"OK\",\n" +
"\"message\": \"성공\",\n" +
"\"data\": null\n" +
"}"
)
})
})
})
@Operation(summary = "납부 결과 재전달(일괄)")
@PostMapping(value = "/bill/kko/fwd/pay-reuslt/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> fwdPayRsltBulk(@RequestBody Map<String, Object> mParam) {
List<Map<String, Object>> targets = (List<Map<String, Object>>) mParam.get("targets");
EnsResponseVO responseVO = billKkoClientServiceImpl.fwdPayRsltBulk(targets);
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
}

@ -1,118 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.presentation;
import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillAcptReqData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.BillUrlReqData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.entity.BillKko;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoAcptReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoAcptReqVO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoUrlReqDTO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoUrlReqVO;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.BillKkoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "BillKkoController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class BillKkoController {
private final BillKkoService billKkoService;
@Operation(summary = "청구서링크 생성")
@PostMapping(value = "/bill/kko/url/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
@Transactional
public ResponseEntity<EnsResponseVO> url(@RequestBody BillKkoAcptReqDTO reqDTO) {
BillAcptReqData<BillKkoAcptReqVO> acptreq = new BillAcptReqData<BillKkoAcptReqVO>() {
@Override
public BillKkoAcptReqVO get() {
return reqDTO.getDocuments();
}
};
EnsResponseVO responseVO = billKkoService.accept(Arrays.asList(acptreq));
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
List<Map<String, String>> result = (List<Map<String, String>>) responseVO.getResultInfo();
List<Map<String, Object>> resultInfo = result.stream()
.map(m -> {
Set<String> billerUserKeys = m.keySet();
return billerUserKeys.stream()
.map(billerUserKey -> {
Map<String, Object> mOutput = new HashMap<>();
this.callUrlCreate(BillReqSeCd.URL, reqDTO.getBillerCode(), reqDTO.getAuthorization(), m.get(billerUserKey), mOutput);
mOutput.put("biller_user_key", billerUserKey);
mOutput.put("bill_uid", m.get(billerUserKey));
return mOutput;
})
.collect(Collectors.toList());
}).collect(Collectors.toList())
.get(0);
responseVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
@Operation(summary = "청구서링크 재생성")
@PostMapping(value = "/bill/kko/re/url/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EnsResponseVO> reUrl(@RequestBody BillKkoUrlReqDTO reqDTO) {
List<Map<String, Object>> resultInfo = reqDTO.getBillUids().stream()
.map(billUid -> {
Map<String, Object> mOutput = new HashMap<>();
this.callUrlCreate(BillReqSeCd.REURL, reqDTO.getBillerCode(), reqDTO.getAuthorization(), billUid, mOutput);
mOutput.put("bill_uid", billUid);
return mOutput;
})
.collect(Collectors.toList());
EnsResponseVO responseVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
return new ResponseEntity<EnsResponseVO>(responseVO, HttpStatus.OK);
}
private void callUrlCreate(BillReqSeCd billReqSeCd, String billerCode, String authorization, String billUid, Map<String, Object> mOutput) {
BillUrlReqData<BillKkoUrlReqVO> urlreq = new BillUrlReqData<BillKkoUrlReqVO>() {
@Override
public BillKkoUrlReqVO get() {
return BillKkoUrlReqVO.builder()
.reqSe(billReqSeCd)
.billerCode(billerCode)
.authorization(authorization)
.billUid(billUid)
.build();
}
};
try {
EnsResponseVO response = billKkoService.createUrl(urlreq);
mOutput.put("errCode", response.getErrCode().getCode());
mOutput.put("errMsg", response.getErrMsg());
if (EnsErrCd.OK.equals(response.getErrCode()))
mOutput.put("url", ((BillKko) response.getResultInfo()).getUrl());
} catch (Exception e) {
mOutput.put("errCode", EnsErrCd.ERR999);
mOutput.put("errMsg", "청구서링크 생성 실패. " + e.getMessage());
}
}
}

@ -0,0 +1,92 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.presentation;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.KkoPayProcessService;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.PayController;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.model.PayApiRespDTO;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@Tag(name = "KkoPayProcessController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class KkoPayProcessController implements PayController<ResponseEntity<PayApiRespDTO>, Map<String, Object>> {
private final KkoPayProcessService kkoPayProcessService;
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "청구서링크 생성"
, value = "{\"billUid\":\"청구서UID\"}")
})
})
@Operation(summary = "청구서링크 생성")
@PostMapping(value = "/bill/kko/pay/gnrurl", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<PayApiRespDTO> gnrUrl(@RequestBody Map<String, Object> param) {
return new ResponseEntity<PayApiRespDTO>(kkoPayProcessService.gnrUrl(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "결제정보 요청"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"biller_notice_key\":\"청구서UID\",\"user_birth\":\"19861128\",\"parameters\":{\"파라미터1\":\"8자이내값\"}}}")
})
})
@Operation(summary = "납부(결제)정보 요청")
@PostMapping(value = "/bill/kko/pay/notice", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<PayApiRespDTO> payNotice(@RequestBody Map<String, Object> param) {
return new ResponseEntity<PayApiRespDTO>(kkoPayProcessService.payNotice(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "납부(결제)가능여부 확인"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"biller_notice_key\":\"청구서UID\",\"amount\":29000,\"parameters\":{\"파라미터1\":\"8자이내값\"}}}")
})
})
@Operation(summary = "납부(결제)가능여부 확인")
@PostMapping(value = "/bill/kko/pay/able", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<PayApiRespDTO> payAble(@RequestBody Map<String, Object> param) {
return new ResponseEntity<PayApiRespDTO>(kkoPayProcessService.payAble(param), HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "결과전달"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"biller_notice_key\":\"청구서UID\",\"parameters\":{\"파라미터1\":\"8자이내값\"},\"pay_by\":\"MONEY\",\"pay_type\":\"P\",\"pay_detail1\":\"\",\"pay_detail2\":\"\",\"amount\":20000,\"pay_amount\":20000,\"pay_fee_type\":\"BEFORE\",\"pay_fee\":150,\"pay_fee_tax\":15,\"paid_at\":\"20190220161656\",\"pay_id\":2748877}}")
})
})
@Operation(summary = "납부(결제)결과 전달")
@PostMapping(value = "/bill/kko/pay/result", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<PayApiRespDTO> payResult(@RequestBody Map<String, Object> param) {
return new ResponseEntity<PayApiRespDTO>(kkoPayProcessService.payResult(param), HttpStatus.OK);
}
@Operation(summary = "결제취소")
@PostMapping(value = "/bill/kko/pay/cancel", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<PayApiRespDTO> payCancel(Map<String, Object> param) {
return new ResponseEntity<PayApiRespDTO>(kkoPayProcessService.payCancel(param), HttpStatus.OK);
}
}

@ -0,0 +1,195 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.presentation;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.process.model.KkoPayUrlRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.PayUseSysController;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import com.google.gson.Gson;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Tag(name = "KkoPayUseSysSampleController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class KkoPayUseSysSampleController implements PayUseSysController<ResponseEntity, Map<String, Object>> {
private Gson gson = new Gson();
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "청구서링크생성 정보"
, value = "{\"data\":{\"billerUserKey\":\"빌러유저키\"}}")
})
})
@Operation(summary = "청구서링크생성 정보 샘플")
@PostMapping(value = "/bill/kko/sample/gnrUrl", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity gnrUrl(@RequestBody Map<String, Object> param) {
log.info("[Request Data] {}", param.toString());
/* ============================================
* [ ]
* OK
* [ ]
* GRNURL_FIND_FAILED
============================================ */
PayUseSysResCd resCd = PayUseSysResCd.OK;
String expireAt = "20231231235959";
KkoPayUrlRespData data = KkoPayUrlRespData.builder()
.billedYearMonth(null)
.ordinal(null)
.expireAt(expireAt)
.parameters(null)
.build();
Map<String, Object> result = new HashMap<>();
result.put("res_code", resCd.getCode());
result.put("message", resCd.getCodeNm());
result.put("data", data);
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "납부(결제)정보"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"user_birth\":\"\",\"parameters\":{\"some_param\":\"\"}}}"),
})
})
@Operation(summary = "납부(결제)정보 샘플")
@PostMapping(value = "/bill/kko/sample/paynotice", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<Map<String, Object>> payNotice(@RequestBody Map<String, Object> param) {
log.info("[Request Data] {}", param.toString());
/* ============================================
* [ ]
* OK
* [ ]
* NOT_FOUND_PAYDATA
* PAYDATA_FIND_FAILED
============================================ */
PayUseSysResCd resCd = PayUseSysResCd.OK;
String payExpireDate = "20231231";
KkoPayNoticeRespData data = KkoPayNoticeRespData.builder()
.title("테스트 청구서")
.amount(1000)
.taxFreeAmount(null)
.vatAmount(null)
.expireType("D1")
.payExpireDate(payExpireDate)
.secondPayExpireDate(null)
.bankAccounts(null)
.details(null)
.build();
Map<String, Object> result = new HashMap<>();
result.put("res_code", resCd.getCode());
result.put("message", resCd.getCodeNm());
result.put("data", data);
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "납부(결제)가능여부"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"amount\":29000,\"parameters\":{\"pay_rqt_seq\":\"KT00000001\"}}}")
})
})
@Operation(summary = "납부(결제)가능여부 샘플")
@PostMapping(value = "/bill/kko/sample/payable", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<Map<String, Object>> payAble(@RequestBody Map<String, Object> param) {
log.info("[Request Data] {}", param.toString());
/* ============================================
* [ ]
* OK
* [ ]
* NO_AMOUNT_PAYABLE
* OVERPAYABLE_AMOUNT
* NO_TARGET_PAYABLE
* EXPIRED_DATE
* FAILED_CHECK_INFO
============================================ */
PayUseSysResCd resCd = PayUseSysResCd.OK;
Map<String, Object> result = new HashMap<>();
result.put("res_code", resCd.getCode());
result.put("message", resCd.getCodeNm());
result.put("data", null);
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Sample Example..."
, summary = "납부(결제)결과"
, value = "{\"data\":{\"biller_user_key\":\"빌러유저키\",\"parameters\":{\"pay_rqt_seq\":\"KT00000001\"},\"pay_by\":\"MONEY\",\"pay_type\":\"P\",\"pay_detail1\":\"\",\"pay_detail2\":\"\",\"amount\":20000,\"pay_amount\":20000,\"pay_fee_type\":\"BEFORE\",\"pay_fee\":150,\"pay_fee_tax\":15,\"paid_at\":\"20190220161656\",\"pay_id\":2748877}}")
})
})
@Operation(summary = "납부(결제)결과 샘플")
@PostMapping(value = "/bill/kko/sample/payresult", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<Map<String, Object>> payResult(@RequestBody Map<String, Object> param) {
log.info("[Request Data] {}", param.toString());
PayUseSysResCd resCd = PayUseSysResCd.OK;
Map<String, Object> result = new HashMap<>();
result.put("res_code", resCd.getCode());
result.put("message", resCd.getCodeNm());
result.put("data", null);
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
}
// @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
// @Content(mediaType = "application/json", examples = {
// @ExampleObject(name = "Sample Example..."
// , summary = "결제취소정보"
// , value = "{}")
// })
// })
@Operation(summary = "결제취소정보 샘플")
@PostMapping(value = "/bill/kko/sample/cancelresult", produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<Map<String, Object>> payCancel(Map<String, Object> param) {
throw new EnsException(EnsErrCd.SERVICE_NOT_SUPPORTED, EnsErrCd.SERVICE_NOT_SUPPORTED.getCodeNm());
}
}

@ -1,35 +0,0 @@
package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.model.BillKkoApiRespDTO;
import java.util.Map;
public interface BillKkoClientApiSpec {
/**
*
*
* @param mParam
* @return
*/
BillKkoApiRespDTO findNoticeInfo(Map<String, Object> mParam);
/**
*
*
* @param mParam
* @return
*/
BillKkoApiRespDTO findPrepayInfo(Map<String, Object> mParam);
/**
*
*
* @param mParam
* @return
*/
BillKkoApiRespDTO addPayReultIfno(Map<String, Object> mParam);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save