feat: KT-GIBIS 적용

main
Jonguk. Lim 3 months ago
parent 21efd3bed0
commit 657c5dabc0

@ -92,3 +92,7 @@ where teim.ihidnum = 'RUNCNjEwM0JERENGMEMzNjRBOTAyMERERjg5MDFEODc=';
AND IFNULL(tekmd.document_binder_uuid, '') != '' AND IFNULL(tekmd.document_binder_uuid, '') != ''
AND tesm.signgu_code = '51110' AND tesm.signgu_code = '51110'
AND tesm.ffnlg_code = '11'; AND tesm.ffnlg_code = '11';
select * from ens_snd_mast;
select * from ENS_SND_DTL_KT_GBS;

@ -0,0 +1,28 @@
package kr.xit.biz.ktgbs.mapper;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
import kr.xit.biz.ens.model.cmm.CmmEnsRlaybsnmDTO;
import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMsgRsltReqData;
/**
* <pre>
* description :
*
* packageName : kr.xit.biz.ktgbs.mapper
* fileName : IBizKtGbsMapper
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
@Mapper
public interface IBizKtGbsMapper {
int updateRlaybsnmKtInfo(final CmmEnsRlaybsnmDTO dto);
int updateKtBcDtl(final KtMsgRsltReqData dto);
int saveKtCntcSndngResult(final KtMsgRsltReqData dto);
}

@ -0,0 +1,137 @@
package kr.xit.biz.ktgbs.service;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.xit.biz.cmm.service.ICmmEnsCacheService;
import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.kt.KtCommonDTO.ErrorMsg;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import kr.xit.biz.ktgbs.mapper.IBizKtGbsMapper;
import kr.xit.core.service.AbstractService;
import kr.xit.core.spring.annotation.TraceLogging;
import kr.xit.core.support.utils.Checks;
import kr.xit.core.support.utils.DateUtils;
import kr.xit.ens.cmm.CmmEnsUtils;
import kr.xit.ens.kt.web.KtBcInboundController;
import kr.xit.ens.ktgbs.service.IKtGbsService;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* description :
*
* packageName : kr.xit.biz.ktgbs.service
* fileName : BizKtGbsService
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
@RequiredArgsConstructor
@Service
public class BizKtGbsService extends AbstractService implements IBizKtGbsService {
private final IKtGbsService ktGbsService;
private final ICmmEnsCacheService cacheService;
private final IBizKtGbsMapper mapper;
/**
* <pre>
* kt Access token
* 1. kt Access token
* 2. DB
* 3.
* @param paramDTO KtMnsRequest
* @return KtTokenResponse
* </pre>
*/
/*
@Override
public KtTokenResponse requestToken(final KtMnsRequest paramDTO) {
KtTokenResponse resDTO = ktMmsService.requestToken(paramDTO);
if(StringUtils.isEmpty(resDTO.getAccessToken())){
throw BizRuntimeException.create("fail.api.kt.token.request");
}
mapper.updateRlaybsnmKtInfo(
CmmEnsRlaybsnmDTO.builder()
.signguCode(paramDTO.getSignguCode())
.ffnlgCode(paramDTO.getFfnlgCode())
.profile(ApiConstants.PROFILE)
.ktAccessToken(resDTO.getAccessToken())
.ktTokenExpiresIn(resDTO.getExpiresIn())
.ktScope(resDTO.getScope())
.ktTokenJti(resDTO.getJti())
.build()
);
cacheService.removeRlaybsnmInfoCache(
CmmEnsRequestDTO.builder()
.signguCode(paramDTO.getSignguCode())
.ffnlgCode(paramDTO.getFfnlgCode())
.profile(paramDTO.getProfile())
.build()
);
return resDTO;
}
*/
/**
* <pre>
* / /
* - KT
* - http://{각대행사(IP:Port)}/api/ag/message/result
* {@link KtBcInboundController#messageResult messageResult}
*
*
* -> 1 ,
* ->
*
* @param reqDTO KtMsgRsltRequest
* @return KtCommonResponse
* </pre>
*/
@Override
@TraceLogging
@Transactional
public KtCommonDTO.KtCommonResponse messageResult(final KtGbsApiDTO.MsgRsltRequest reqDTO) {
List<ErrorMsg> errors = CmmEnsUtils.getValidateErrors(reqDTO);
if(!errors.isEmpty()) return throwError(errors);
for(KtGbsApiDTO.MsgRsltReqsData dto : reqDTO.getReqs()){
// 결과코드가 '40' 이고 열람타임스탬프가 있는 경우 -> 결과코드 '열람확인:60'으로 reset
if("40".equals(dto.getMmsRsltDvcd()) && Checks.isNotEmpty(dto.getMmsRdgTmst())){
dto.setMmsRsltDvcd("60");
}
dto.setMmsRsltDvcdMsg(messageUtil.getMessage("info.api.kt.msg.rslt."+dto.getMmsRsltDvcd()));
// FIXME: KT GIBIS 적용 안됨
//if(mapper.updateKtBcDtl(dto) != 1) {
// errors.add(new ErrorMsg(
// String.format("존재 하지 않는 발송 대상(src_key[%s], mms_rslt_sqno[%s]) 입니다",
// dto.getSrcKey(), dto.getMmsSndgRsltSqno())));
//}
// FIXME: KT GIBIS 적용 안됨
//mapper.saveKtCntcSndngResult(dto);
}
return KtCommonDTO.KtCommonResponse.builder()
.resultCd("00")
.resultDt(DateUtils.getTodayAndNowTime(ApiConstants.FMT_DT_EMPTY_DLT))
.build();
}
private static KtCommonDTO.KtCommonResponse throwError(List<ErrorMsg> errors) {
return KtCommonDTO.KtCommonResponse.builder()
.resultCd("01")
.resultDt(DateUtils.getTodayAndNowTime(ApiConstants.FMT_DT_EMPTY_DLT))
.errors(errors)
.build();
}
}

@ -0,0 +1,26 @@
package kr.xit.biz.ktgbs.service;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
/**
* <pre>
* description :
*
* packageName : kr.xit.biz.ktgbs.service
* fileName : IBizKtGbsService
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
public interface IBizKtGbsService {
//KtTokenResponse requestToken(final KtMnsRequest paramDTO);
KtCommonDTO.KtCommonResponse messageResult(final KtGbsApiDTO.MsgRsltRequest reqDTO);
}

@ -0,0 +1,31 @@
package kr.xit.ens.ktgbs.service;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
/**
* <pre>
* description :
* packageName : kr.xit.ens.ktgbs.service
* fileName : IKtGbsService
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
public interface IKtGbsService {
// FIXME : KT GIBIS 적용 안됨
//------------------------------------------------------------------------------
// mens 사용 API
//------------------------------------------------------------------------------
// KtTokenDTO.KtTokenResponse requestToken(final KtCommonDTO.KtMnsRequest paramDTO);
KtCommonDTO.KtCommonResponse mainSend(final KtGbsApiDTO.MsgSendRequest reqDTO);
// KtTokenDTO.KtTokenConfirmResponse cfmToken(final KtTokenDTO.KtTokenConfirmRequest reqDTO);
// KtCommonDTO.KtCommonResponse readToken(final KtTokenDTO.KtTokenReadRequest reqDTO);
//------------------------------------------------------------------------------
}

@ -0,0 +1,70 @@
package kr.xit.ens.ktgbs.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.ens.model.cmm.CmmEnsRlaybsnmDTO;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import kr.xit.core.service.AbstractService;
import kr.xit.core.spring.annotation.TraceLogging;
import kr.xit.core.spring.util.ApiWebClientUtil;
import kr.xit.core.support.utils.JsonUtils;
import kr.xit.ens.cmm.CmmEnsUtils;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* description :
* packageName : kr.xit.ens.ktgbs.service
* fileName : KtGbsService
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
@RequiredArgsConstructor
@Service
public class KtGbsService extends AbstractService implements IKtGbsService {
@Value("${app.contract.ktgbs.host}")
private String HOST;
/**
* : BC-AG-SN-002
*/
@Value("${app.contract.ktgbs.api.main-send}")
private String API_MAIN_SEND;
private final ApiWebClientUtil webClient;
// FIXME : KT GIBIS 적용 안됨
@Override
@TraceLogging
public KtCommonDTO.KtCommonResponse mainSend(final KtGbsApiDTO.MsgSendRequest reqDTO) {
final CmmEnsRlaybsnmDTO ktMnsInfo = getRlaybsnmInfo(reqDTO);
reqDTO.setServiceCd(ktMnsInfo.getKtServiceCode());
reqDTO.setServiceCd(ktMnsInfo.getKtSvcCerfKey());
reqDTO.setSignguCode(null);
reqDTO.setFfnlgCode(null);
reqDTO.setProfile(null);
CmmEnsUtils.validate(reqDTO);
return webClient.exchangeKtGbs(
HOST + API_MAIN_SEND,
HttpMethod.POST,
JsonUtils.toJson(reqDTO),
KtCommonDTO.KtCommonResponse.class,
ktMnsInfo
);
}
private CmmEnsRlaybsnmDTO getRlaybsnmInfo(final KtCommonDTO.KtMnsRequest request){
return CmmEnsUtils.getRlaybsnmInfo(request.getSignguCode(), request.getFfnlgCode(), ApiConstants.SndngSeCode.KT_BC);
}
}

@ -0,0 +1,46 @@
package kr.xit.ens.ktgbs.web;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.model.IApiResponse;
import kr.xit.ens.ktgbs.service.IKtGbsService;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* description :
* packageName : kr.xit.ens.ktgbs.web
* fileName : KtGbsController
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
@Tag(name = "KtGbsController", description = "KT GIBIS API controller")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api/ens/ktgbs/v1")
public class KtGbsController {
private final IKtGbsService service;
// FIXME : KT GIBIS 적용 안됨
@Operation(summary = "본문자 수신 등록 요청", description = "본문자 수신 등록 요청")
@PostMapping(value = "/mainSend", produces = MediaType.APPLICATION_JSON_VALUE)
public IApiResponse mainSend(@RequestBody final KtGbsApiDTO.MsgSendRequest reqDTO) {
KtCommonDTO.KtCommonResponse dto = service.mainSend(reqDTO);
return ApiResponseDTO.success(dto);
}
}

@ -0,0 +1,79 @@
package kr.xit.ens.ktgbs.web;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
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 kr.xit.biz.ens.model.kt.KtCommonDTO;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* description : KT GBIS API
* packageName : kr.xit.ens.ktgbs.web
* fileName : KtGbsMmsInboundController
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
@Tag(name = "KtGbsInboundController", description = "KT GIBIS Inbound API")
@RequiredArgsConstructor
@RestController
public class KtGbsInboundController {
/**
* <pre>
* / -> KT GIBIS
* - KT GBIS
* - url : http://{각대행사(IP:Port)}/api/msg/result
* @param reqDTO KtMsgRsltRequest
* @return KtCommonResponse
* </pre>
*/
// FIXME : KT GIBIS 적용 안됨
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(
mediaType = "application/json",
examples = {
@ExampleObject(
value = """
{
"service_cd" : "CD001",
"reqs" : [
{
"src_key" : "OvSsuljd1K-67c1fc38-1a59-4fbe-930e-802db6609140",
"mms_sndg_rslt_sqno" : 2,
"prcs_dt" : "20240819",
"mms_bsns_dvcd" : "01001",
"mbl_bzowr_dvcd" : "02",
"rl_mms_sndg_telno" : "4230",
"mms_rslt_dvcd" : "40",
"mms_sndg_tmst" : "20240819090237",
"mms_rcv_tmst" : "20240819090239",
"mms_rdg_tmst" : "20240819114405",
"prev_approve_yn" : "Y",
"msg_type" : "2"
}
]
}
"""
),
})
})
@Operation(summary = "메세지 발송/수신 결과 전송 -> KT GIBIS에서 호출", description = "메세지 발송/수신 결과 전송 -> KT GIBIS에서 호출")
//@PostMapping(value = "/goji/kt/gibis/stat/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = "/api/msg/result", produces = MediaType.APPLICATION_JSON_VALUE)
public KtCommonDTO.KtCommonResponse messageResult(@RequestBody final KtGbsApiDTO.MsgRsltRequest reqDTO) {
return null; //bizService.messageResult(reqDTO);
}
}

@ -82,3 +82,10 @@ app:
info-acmd: /api/acmdinfo info-acmd: /api/acmdinfo
# 전자문서유통정보수치확인서 발급처리 : BC-AG-HS-002 # 전자문서유통정보수치확인서 발급처리 : BC-AG-HS-002
cfm-acmd: /api/acmdinfocfm cfm-acmd: /api/acmdinfocfm
ktgbs:
host: http://172.16.0.13:10210/ONLWeb
api:
# 본문자수신등록 : BC-AG-SN-002
main-send: /api/msg/send
# 사전/본 문자 발송/수신 결과 전송 : BC-AG-SN-010
result-message: /api/msg/result

@ -8,6 +8,7 @@ import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
import kr.xit.biz.ens.model.EnsDTO; import kr.xit.biz.ens.model.EnsDTO;
import kr.xit.biz.ens.model.EnsKtBcDTO; import kr.xit.biz.ens.model.EnsKtBcDTO;
import kr.xit.biz.ens.model.EnsKtGbsDTO;
import kr.xit.biz.ens.model.cmm.SndngMssageParam; import kr.xit.biz.ens.model.cmm.SndngMssageParam;
import kr.xit.biz.ens.model.cmm.TmplatManage; import kr.xit.biz.ens.model.cmm.TmplatManage;
import kr.xit.biz.ens.model.cntc.CntcDTO; import kr.xit.biz.ens.model.cntc.CntcDTO;
@ -15,6 +16,7 @@ import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO;
import kr.xit.biz.ens.model.kakao.v1.KkopayDocDTO; import kr.xit.biz.ens.model.kakao.v1.KkopayDocDTO;
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO; import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData; import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
/** /**
* <pre> * <pre>
@ -182,6 +184,7 @@ public interface IEnsBatchMapper {
/** /**
* <pre> * <pre>
* Kt * Kt
* KT GIBIS skip
* - tb_ens_kt_bc * - tb_ens_kt_bc
* @param t T * @param t T
* @return int * @return int
@ -199,6 +202,16 @@ public interface IEnsBatchMapper {
*/ */
<T> int insertKtBcDetail(final T t); <T> int insertKtBcDetail(final T t);
/**
* <pre>
* Kt Gibis
* - ens_snd_dtl_kt_gbs
* @param t T
* @return int
* </pre>
*/
<T> int insertKtGbsDetail(final T t);
/** /**
* <pre> * <pre>
* *
@ -316,6 +329,10 @@ public interface IEnsBatchMapper {
Optional<EnsKtBcDTO> selectKtBcMstTgtInfo(final SndngMssageParam dto); Optional<EnsKtBcDTO> selectKtBcMstTgtInfo(final SndngMssageParam dto);
List<KtMainSendReqData> selectKtBcSendTgts(final SndngMssageParam dto); List<KtMainSendReqData> selectKtBcSendTgts(final SndngMssageParam dto);
int updateKtBcMst(final SndngMssageParam dto); int updateKtBcMst(final SndngMssageParam dto);
Optional<EnsKtGbsDTO> selectKtGbsMstTgtInfo(final SndngMssageParam dto);
List<KtGbsApiDTO.MsgSendReqsData> selectKtGbsSendTgts(final SndngMssageParam dto);
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// send // send
//---------------------------------------------------------------------- //----------------------------------------------------------------------

@ -0,0 +1,64 @@
package kr.xit.biz.ens.model;
import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* <pre>
* description : tb_ens_ Entity DTO
*
* packageName : kr.xit.biz.ens.model
* fileName : EnsKtGbsDTO
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-29 limju
*
* </pre>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
public class EnsKtGbsDTO extends KtGbsApiDTO.MsgSendRequest {
@Builder.Default
private String sndngTyCode = "ENS";
/**
* 릿 ID
*/
private String tmplatId;
/**
*
*/
private String tgtYn;
/**
* ID
*/
private String unitySndngMastrId;
/**
* ID
*/
private String unitySndngDetailId;
/**
* ID
*/
private String sndngMastrId;
/**
*
*/
@Builder.Default
private String sndngProcessSttus = ApiConstants.SndngProcessStatus.ACCEPT.getCode();
}

@ -271,7 +271,7 @@ public class EnsBatchAcceptService extends AbstractService implements IEnsBatchA
} }
//FIXME : KT 데이타 적합성 체크 //FIXME : KT 데이타 적합성 체크
case KT_BC -> { case KT_BC, KT_GIBIS -> {
isCiCreate = true; isCiCreate = true;
} }

@ -23,6 +23,7 @@ import kr.xit.biz.ens.model.cntc.CntcDTO;
import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO; import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO;
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO; import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData; import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.service.AbstractService; import kr.xit.core.service.AbstractService;
import kr.xit.core.support.utils.Checks; import kr.xit.core.support.utils.Checks;
@ -150,6 +151,16 @@ public class EnsBatchExtractService extends AbstractService implements
mapper.updateKtBcMst(dto); mapper.updateKtBcMst(dto);
} }
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveKtGbsResult(final SndngMssageParam dto, final List<KtGbsApiDTO.MsgSendReqsData> sendReqs) {
// 성공처리
// mobile page create
// FIXME : KT GIBIS 적용 안됨
if(Checks.isNotEmpty(sendReqs)) sendReqs.forEach(d -> mapper.insertKtMobilePageManage(d.getSrcKey()));
mapper.updateKtBcMst(dto);
}
/** /**
* <pre> * <pre>
* fail * fail

@ -218,6 +218,22 @@ public class EnsBatchMakeService extends AbstractService implements IEnsBatchMak
mapper.insertKtBcMastr(dto); mapper.insertKtBcMastr(dto);
yield mapper.insertKtBcDetail(dto); yield mapper.insertKtBcDetail(dto);
} }
// FIXME : KT GIBIS 적용 안됨
case KT_GIBIS -> {
// FIXME: KT callback url 확인 적용
// ENS_SND_DTL_KT_GBS
if(SignguCode.CHUNCHEON.getCode().equals(dto.getSignguCode())){
dto.setUrl(CHUNCHEON_CALLBACK_URL);
}
// FIXME: KT callback url 확인 적용
if(SignguCode.FUNERAL.getCode().equals(dto.getSignguCode())){
dto.setUrl(ME_CALLBACK_URL);
}
//mapper.insertKtBcMastr(dto);
//tb_ens_sndng_mastr
//ENS_SND_DTL_KT_GBS
yield mapper.insertKtGbsDetail(dto);
}
//default -> throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode())); //default -> throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode()));
}; };
} }

@ -32,6 +32,7 @@ import kr.xit.biz.ens.mapper.IEnsBatchMapper;
import kr.xit.biz.ens.model.EnsDTO; import kr.xit.biz.ens.model.EnsDTO;
import kr.xit.biz.ens.model.EnsDTO.SendKakaoTgt; import kr.xit.biz.ens.model.EnsDTO.SendKakaoTgt;
import kr.xit.biz.ens.model.EnsKtBcDTO; import kr.xit.biz.ens.model.EnsKtBcDTO;
import kr.xit.biz.ens.model.EnsKtGbsDTO;
import kr.xit.biz.ens.model.cmm.SndngMssageParam; import kr.xit.biz.ens.model.cmm.SndngMssageParam;
import kr.xit.biz.ens.model.kakao.v1.KkopayDocAttrDTO; import kr.xit.biz.ens.model.kakao.v1.KkopayDocAttrDTO;
import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO; import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO;
@ -40,6 +41,7 @@ import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
import kr.xit.biz.ens.model.kt.KtCommonDTO.ErrorMsg; import kr.xit.biz.ens.model.kt.KtCommonDTO.ErrorMsg;
import kr.xit.biz.ens.model.kt.KtCommonDTO.KtCommonResponse; import kr.xit.biz.ens.model.kt.KtCommonDTO.KtCommonResponse;
import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData; import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.model.ApiResponseDTO; import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.service.AbstractService; import kr.xit.core.service.AbstractService;
@ -78,9 +80,12 @@ public class EnsBatchSendService extends AbstractService implements IEnsBatchSen
@Value("${app.contract.kakao.api.talk.bulksend}") @Value("${app.contract.kakao.api.talk.bulksend}")
private String apiKkotalkBulkSend; private String apiKkotalkBulkSend;
@Value("${app.contract.kt.api.bulksend}") @Value("${app.contract.kt.bc.api.bulksend}")
private String apiKtBcBulkSend; private String apiKtBcBulkSend;
@Value("${app.contract.kt.gibis.api.bulksend}")
private String apiKtGbsBulkSend;
@Value("${app.contract.kakao.bulk-max-cnt}") @Value("${app.contract.kakao.bulk-max-cnt}")
private int bulkKkoMaxCnt; private int bulkKkoMaxCnt;
@ -153,6 +158,7 @@ public class EnsBatchSendService extends AbstractService implements IEnsBatchSen
case KAKAO -> sendBulkKakaopay(dto); case KAKAO -> sendBulkKakaopay(dto);
case KAKAO_NEW -> sendBulkKakaotalk(dto); case KAKAO_NEW -> sendBulkKakaotalk(dto);
case KT_BC -> sendBulkKtBc(dto); case KT_BC -> sendBulkKtBc(dto);
case KT_GIBIS -> sendBulkKtGibis(dto);
default -> throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode())); default -> throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode()));
} }
} }
@ -593,6 +599,93 @@ public class EnsBatchSendService extends AbstractService implements IEnsBatchSen
extractService.updateSendSndngMstStatus(mstId, unitySndMstId, SndngSeCode.KT_BC, "KT-BC 실패(발송마스터 데이타 오류)"); extractService.updateSendSndngMstStatus(mstId, unitySndMstId, SndngSeCode.KT_BC, "KT-BC 실패(발송마스터 데이타 오류)");
} }
/**
* <pre>
* KT BC send
* @param dto SndngMssageParam
* </pre>
*/
// FIXME : KT GIBIS 적용 안됨
private void sendBulkKtGibis(final SndngMssageParam dto) {
final String url = apiHost + apiKtGbsBulkSend;
EnsKtGbsDTO mstDTO = mapper.selectKtGbsMstTgtInfo(dto)
.orElseThrow(() -> BizRuntimeException.create("KT GBIS 본문자 수신 등록 대상이 존재 하지 않습니다 "));
final String mstId = dto.getSndngMastrId();
final String unitySndMstId = dto.getUnitySndngMastrId();
final List<KtGbsApiDTO.MsgSendReqsData> sendReqs = mapper.selectKtGbsSendTgts(dto);
// validation check
try {
validatedKtGbsSendBulks(sendReqs);
} catch (Exception e) {
extractService.updateSndngMstFailStatus(mstId, SndngSeCode.KT_GIBIS, "", e.getMessage(), "[send]KT-GIBIS 발송(bulks)요청 실패(파라메터 오류)");
throw e;
}
final List<List<KtGbsApiDTO.MsgSendReqsData>> partitions = ListUtils.partition(sendReqs, bulkKtMaxCnt);
@SuppressWarnings("rawtypes")
List<ApiResponseDTO> apiResults = partitions.stream()
.map(bulkSendList -> {
mstDTO.setReqs(bulkSendList);
return apiWebClient.exchange(
url,
HttpMethod.POST,
mstDTO,
ApiResponseDTO.class,
CmmEnsBizUtils.getHeadeMap());
}
)
.toList();
boolean isSuccess = false;
List<ErrorMsg> errList = new ArrayList<>();
//noinspection rawtypes
for(ApiResponseDTO apiResult : apiResults) {
// KT-BC API 정상 호출
if(ObjectUtils.isNotEmpty(apiResult.getData())) {
KtCommonResponse resDTO = toObjByObj(apiResult.getData(), KtCommonResponse.class);
assert resDTO != null;
dto.setResultDt(resDTO.getResultDt());
if(ObjectUtils.isNotEmpty(resDTO) && "00".equals(resDTO.getResultCd())){
isSuccess = true;
dto.setErrorMssage("정상");
}else{
//TODO:: 모바일 콘텐츠 삭제??
errList.addAll(resDTO.getErrors());
}
}else{
// KT-BC API 호출전 에러 발생
if(ObjectUtils.isEmpty(dto.getResultDt())) {
dto.setResultDt(DateUtils.getTodayAndNowTime(ApiConstants.FMT_DT_EMPTY_DLT));
}
dto.setErrorMssage(apiResult.getMessage());
errList.add(new ErrorMsg(apiResult.getMessage()));
}
}
// 모두 실패한 경우
if(!isSuccess) {
dto.setResultCd("01");
dto.setErrorMssage(
errList.stream()
.map(ErrorMsg::getErrorMsg)
.collect(Collectors.joining(","))
);
extractService.saveKtBcResult(dto, null);
extractService.updateSndngMstFailStatus(mstId, SndngSeCode.KT_BC, dto.getErrorCode(), dto.getErrorMssage(), "[send] KT-BC 발송(bulks)요청 실패");
return;
}
// 성공 건수 존재시 성공 처리
dto.setResultCd("00");
dto.setErrorMssage("정상");
extractService.saveKtGbsResult(dto, sendReqs);
extractService.updateSendSndngMstStatus(mstId, unitySndMstId, SndngSeCode.KT_BC, "KT-BC 실패(발송마스터 데이타 오류)");
}
private void validatedKtBcSendBulks(List<KtMainSendReqData> sendReqs) { private void validatedKtBcSendBulks(List<KtMainSendReqData> sendReqs) {
List<String> errors = new ArrayList<>(); List<String> errors = new ArrayList<>();
int idx = 0; int idx = 0;
@ -615,5 +708,28 @@ public class EnsBatchSendService extends AbstractService implements IEnsBatchSen
throw BizRuntimeException.create(errors.toString()); throw BizRuntimeException.create(errors.toString());
} }
} }
private void validatedKtGbsSendBulks(List<KtGbsApiDTO.MsgSendReqsData> sendReqs) {
List<String> errors = new ArrayList<>();
int idx = 0;
for (KtGbsApiDTO.MsgSendReqsData dto : sendReqs) {
Set<ConstraintViolation<KtGbsApiDTO.MsgSendReqsData>> errList = validator.validate(dto);
if (!errList.isEmpty()) {
int finalIdx = idx;
errors.addAll(errList.stream()
.map(row -> String.format("%s[%d]=%s", row.getPropertyPath(), finalIdx + 1,
row.getMessageTemplate()))
.toList()
);
}
idx++;
}
if (!errors.isEmpty()) {
throw BizRuntimeException.create(errors.toString());
}
}
//----------------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------------
} }

@ -107,7 +107,7 @@ public class EnsBatchStatusService extends AbstractService implements IEnsBatchS
case KAKAO_NEW case KAKAO_NEW
-> statusKakaotalk(dto); -> statusKakaotalk(dto);
//break; //break;
case KT_BC -> {} case KT_BC, KT_GIBIS -> {}
default -> default ->
throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode())); throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode()));

@ -7,6 +7,7 @@ import kr.xit.biz.ens.model.cmm.SndngMssageParam;
import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO; import kr.xit.biz.ens.model.kakao.v1.KkopayDocBulkDTO;
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO; import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData; import kr.xit.biz.ens.model.kt.KtMmsSendDTO.KtMainSendReqData;
import kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO;
/** /**
* <pre> * <pre>
@ -34,6 +35,7 @@ public interface IEnsBatchExtractService {
void saveKkotalkSendResult(final String mstId, String unitySndMstId, final List<KkotalkDTO.BulkSendResponse> resList); void saveKkotalkSendResult(final String mstId, String unitySndMstId, final List<KkotalkDTO.BulkSendResponse> resList);
void saveKtBcResult(final SndngMssageParam dto, final List<KtMainSendReqData> sendReqs); void saveKtBcResult(final SndngMssageParam dto, final List<KtMainSendReqData> sendReqs);
void saveKtGbsResult(final SndngMssageParam dto, final List<KtGbsApiDTO.MsgSendReqsData> sendReqs);
void updateSndngMstFailStatus(final String mstId, final SndngSeCode seCode, final String errCode, final String errMsg, final String stsErrMsg); void updateSndngMstFailStatus(final String mstId, final SndngSeCode seCode, final String errCode, final String errMsg, final String stsErrMsg);

@ -32,12 +32,14 @@ app:
bulkstatus: /api/ens/kakao/v2/envelopes/bulk/status bulkstatus: /api/ens/kakao/v2/envelopes/bulk/status
kt: kt:
bulk-max-cnt: 10 bulk-max-cnt: 10
api: bc:
bulksend: /api/ens/kt/v1/mainSend api:
bulkstatus: /api/ens/kt/v1/messageResult bulksend: /api/ens/kt/v1/mainSend
other: bulkstatus: /api/ens/kt/v1/messageResult
api: gibis:
merge: /api/other/v1/merge api:
bulksend: /api/ens/ktgbs/v1/mainSend
bulkstatus: /api/ens/ktgbs/v1/messageResult
# 배치 설정 # 배치 설정
batch: batch:

@ -310,9 +310,9 @@
, now() , now()
, 'batch' , 'batch'
FROM tb_ens_unity_sndng_mastr teusm FROM tb_ens_unity_sndng_mastr teusm
LEFT JOIN tb_ens_tmplat_manage tetm JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id ON teusm.tmplat_id = tetm.tmplat_id
LEFT JOIN tb_ens_unity_sndng_detail teusd JOIN tb_ens_unity_sndng_detail teusd
ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id
WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId} WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId}
AND teusm.sndng_process_sttus = #{sndngProcessSttus} AND teusm.sndng_process_sttus = #{sndngProcessSttus}
@ -361,9 +361,9 @@
, now() , now()
, 'batch' , 'batch'
FROM tb_ens_unity_sndng_mastr teusm FROM tb_ens_unity_sndng_mastr teusm
LEFT JOIN tb_ens_tmplat_manage tetm JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id ON teusm.tmplat_id = tetm.tmplat_id
LEFT JOIN tb_ens_unity_sndng_detail teusd JOIN tb_ens_unity_sndng_detail teusd
ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id
WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId} WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId}
AND teusm.sndng_process_sttus = #{sndngProcessSttus} AND teusm.sndng_process_sttus = #{sndngProcessSttus}
@ -417,9 +417,9 @@
, now() , now()
, 'batch' , 'batch'
FROM tb_ens_unity_sndng_mastr teusm FROM tb_ens_unity_sndng_mastr teusm
LEFT JOIN tb_ens_tmplat_manage tetm JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id ON teusm.tmplat_id = tetm.tmplat_id
LEFT JOIN tb_ens_rlaybsnm_manage term JOIN tb_ens_rlaybsnm_manage term
ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code
WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId} WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId}
AND teusm.sndng_process_sttus = #{sndngProcessSttus} AND teusm.sndng_process_sttus = #{sndngProcessSttus}
@ -466,11 +466,11 @@
, now() , now()
, 'batch' , 'batch'
FROM tb_ens_unity_sndng_mastr teusm FROM tb_ens_unity_sndng_mastr teusm
LEFT JOIN tb_ens_tmplat_manage tetm JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id ON teusm.tmplat_id = tetm.tmplat_id
LEFT JOIN tb_ens_unity_sndng_detail teusd JOIN tb_ens_unity_sndng_detail teusd
ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id
LEFT JOIN tb_ens_rlaybsnm_manage term JOIN tb_ens_rlaybsnm_manage term
ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code
LEFT JOIN tb_ens_ci tec LEFT JOIN tb_ens_ci tec
ON teusd.unity_sndng_detail_id = tec.unity_sndng_detail_id ON teusd.unity_sndng_detail_id = tec.unity_sndng_detail_id

@ -436,8 +436,7 @@
<insert id="insertKtBcDetail"> <insert id="insertKtBcDetail">
/** ens-oracle-mapper|insertKtBcDetail 공인 알림문자 디테일 데이터 생성|julim */ /** ens-oracle-mapper|insertKtBcDetail 공인 알림문자 디테일 데이터 생성|julim */
INSERT INSERT INTO tb_ens_kt_bc_detail (
INTO tb_ens_kt_bc_detail (
sndng_mastr_id, /* 발송 마스터 id */ sndng_mastr_id, /* 발송 마스터 id */
sndng_detail_id, /* 발송 상세 id */ sndng_detail_id, /* 발송 상세 id */
unity_sndng_detail_id, /* 통합 발송 상세 id */ unity_sndng_detail_id, /* 통합 발송 상세 id */
@ -474,16 +473,63 @@
, sysdate , sysdate
, 'batch' , 'batch'
FROM tb_ens_unity_sndng_mastr teusm FROM tb_ens_unity_sndng_mastr teusm
LEFT JOIN tb_ens_tmplat_manage tetm JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id ON teusm.tmplat_id = tetm.tmplat_id
LEFT JOIN tb_ens_unity_sndng_detail teusd JOIN tb_ens_unity_sndng_detail teusd
ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id
LEFT JOIN tb_ens_rlaybsnm_manage term JOIN tb_ens_rlaybsnm_manage term
ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code
LEFT JOIN tb_ens_ci tec LEFT JOIN tb_ens_ci tec
ON teusd.unity_sndng_detail_id = tec.unity_sndng_detail_id ON teusd.unity_sndng_detail_id = tec.unity_sndng_detail_id
WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId} WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId}
AND teusm.sndng_process_sttus = #{sndngProcessSttus} AND teusm.sndng_process_sttus = #{sndngProcessSttus}
</insert>
<insert id="insertKtGbsDetail">
/** ens-oracle-mapper|insertKtGbsDetail KT GIBIS 디테일 데이터 생성|julim */
INSERT INTO ens_snd_dtl_kt_gbs (
send_mast_id, /* 발송 마스터 id */
send_detail_id, /* 발송 상세 id */
-- unity_sndng_detail_id, /* 통합 발송 상세 id */
src_key, /* 관리키 */
src_seq, /* 리스트 순번 */
ci, /* ci */
mms_dtl_cnts, /* MMS 상세 내용 */
mms_title, /* MMS 제목 */
rcs_dtl_cnts, /* RCS 메시지 생세내용 */
url, /* 연결 URL */
hash, /* 문서 해시 */
mdn, /* 개인 휴대 전화 번호 */
mk_tmplt_msg_json_data,
doc_stat
)
SELECT #{sndngMastrId}
, LPAD(sndng_detail_id_seq.nextval, 20, '0')
-- , teusd.unity_sndng_detail_id
, teusd.unity_sndng_detail_id
, row_number() over (order by teusd.unity_sndng_detail_id)
, tec.ci
, tetm.tmplat_cn || CHR(13) || CHR(10) || '- 열람기간 : ' || substr(teusm.clos_dt, 1, 4) || '년 ' || substr(teusm.clos_dt, 5, 2) || '월 ' || substr(teusm.clos_dt, 7, 2) || '일까지'|| CHR(13) || CHR(10) || '- 문의처 : ' || tetm.cstmr_cnter_tlphon_no || CHR(13) || CHR(10) || CHR(13) || CHR(10) ||'{#INFO_CFRM_STR}'|| CHR(13) || CHR(10) ||'{#RCVE_RF_STR}'
, tetm.tmplat_sj
, tetm.tmplat_cn || CHR(13) || CHR(10) || '- 열람기간 : ' || substr(teusm.clos_dt, 1, 4) || '년 ' || substr(teusm.clos_dt, 5, 2) || '월 ' || substr(teusm.clos_dt, 7, 2) || '일까지'|| CHR(13) || CHR(10) || '- 문의처 : ' || tetm.cstmr_cnter_tlphon_no || CHR(13) || CHR(10)
, #{url}
, sha256.encrypt(teusd.unity_sndng_detail_id)
, ''
, tensd.tmplt_msg_data
, ''
FROM tb_ens_unity_sndng_mastr teusm
JOIN tb_ens_tmplat_manage tetm
ON teusm.tmplat_id = tetm.tmplat_id
JOIN tb_ens_unity_sndng_detail teusd
ON teusm.unity_sndng_mastr_id = teusd.unity_sndng_mastr_id
JOIN tb_ens_rlaybsnm_manage term
ON teusm.signgu_code = term.signgu_code AND teusm.ffnlg_code = term.ffnlg_code
JOIN tb_elctrn_ntic_sndng_detail tensd
ON teusd.unity_sndng_detail_id = tensd.elctrn_ntic_sndng_detail_id
LEFT JOIN tb_ens_ci tec
ON teusd.unity_sndng_detail_id = tec.unity_sndng_detail_id
WHERE teusm.unity_sndng_mastr_id = #{unitySndngMastrId}
AND teusm.sndng_process_sttus = #{sndngProcessSttus}
</insert> </insert>
<update id="updateProcessSttusUnitySndngMst"> <update id="updateProcessSttusUnitySndngMst">
@ -653,9 +699,9 @@
, tekbm.test_sndn_yn , tekbm.test_sndn_yn
, tekbm.rcv_rfrl_yn , tekbm.rcv_rfrl_yn
, tekbm.reopen_day /* ci */ , tekbm.reopen_day /* ci */
FROM tb_ens_sndng_mastr tesm FROM tb_ens_sndng_mastr tesm
JOIN tb_ens_kt_bc_mastr tekbm JOIN tb_ens_kt_bc_mastr tekbm
ON tesm.sndng_mastr_id = tekbm.sndng_mastr_id ON tesm.sndng_mastr_id = tekbm.sndng_mastr_id
WHERE tesm.sndng_mastr_id = #{sndngMastrId} WHERE tesm.sndng_mastr_id = #{sndngMastrId}
AND tesm.signgu_code = #{signguCode} AND tesm.signgu_code = #{signguCode}
AND tesm.ffnlg_code = #{ffnlgCode} AND tesm.ffnlg_code = #{ffnlgCode}
@ -700,6 +746,79 @@
ORDER BY tekbd.sndng_detail_id ORDER BY tekbd.sndng_detail_id
</select> </select>
<select id="selectKtGbsMstTgtInfo" resultType="kr.xit.biz.ens.model.EnsKtGbsDTO">
/** ens-oracle-mapper|selectKtGbsMstTgtInfo-Kt GIBIS 본문자 수신 대상 정보 조회|julim */
SELECT tesm.sndng_mastr_id /* 발송마스터 ID */
, tesm.unity_sndng_mastr_id /* 통합발송마스터 ID */
, tesm.signgu_code /* 시군구 코드 */
, tesm.ffnlg_code /* 과태료 코드 */
, tesm.tmplat_id /* 템플릿 Id */
, tesm.sndng_ty_code /* 발송유형 코드 */
, tesm.sndng_co /* 발송건수 */
, FN_GET_DATETOUNIXTIME(tesm.clos_dt) AS closDt /* 마감일시 */
/*
, tekbm.sndng_mastr_id
, tekbm.service_cd
, tekbm.service_key
, tekbm.agency_id
, tekbm.dept_cd
, tekbm.msg_cd
, tekbm.msg_type
, tekbm.make_dt
, tekbm.sndn_ex_time
, tekbm.ex_time
, tekbm.snd_tel_no
, tekbm.m_type
, tekbm.brand_id
, tekbm.opt_type
, tekbm.tkn_rpmt_yn
, tekbm.rdng_rpmt_yn
, base64encode(tekbm.mms_binary) AS mmsBinary
, tekbm.file_fmat
, tekbm.sndn_tot_cnt
, tekbm.mktn_rcve_csyn
, tekbm.snd_plfm_id
, tekbm.snd_npost
, tekbm.snd_date
, tekbm.multi_mbl_prc_type
, tekbm.test_sndn_yn
, tekbm.rcv_rfrl_yn
, tekbm.reopen_day
*/
FROM tb_ens_sndng_mastr tesm
-- JOIN tb_ens_kt_bc_mastr tekbm
-- ON tesm.sndng_mastr_id = tekbm.sndng_mastr_id
WHERE tesm.sndng_mastr_id = #{sndngMastrId}
AND tesm.signgu_code = #{signguCode}
AND tesm.ffnlg_code = #{ffnlgCode}
ORDER BY tesm.unity_sndng_mastr_id
</select>
<select id="selectKtGbsSendTgts" resultType="kr.xit.biz.ens.model.ktgbs.KtGbsApiDTO$MsgSendReqsData">
/** ens-oracle-mapper|selectKtGbsSendTgts-Kt GIBIS 수신 대상 목록 조회|julim */
SELECT tekbm.sndng_mastr_id /* 발송마스터 ID */
, tekbm.signgu_code /* 시군구 코드 */
, tekbm.ffnlg_code /* 과태료 코드 */
, esdkg.src_key
, esdkg.src_seq
, esdkg.ci
, esdkg.mms_dtl_cnts
, esdkg.mms_title
, esdkg.rcs_dtl_cnts
, esdkg.url
, esdkg.hash AS docHash
, esdkg.mdn
, esdkg.mk_tmplt_msg_json_data
, esdkg.doc_stat
FROM tb_ens_kt_bc_mastr tekbm
JOIN ens_snd_dtl_kt_gbs esdkg
ON tekbm.sndng_mastr_id = esdkg.SEND_MAST_ID
WHERE tekbm.sndng_mastr_id = #{sndngMastrId}
AND tekbm.signgu_code = #{signguCode}
AND tekbm.ffnlg_code = #{ffnlgCode}
ORDER BY esdkg.send_detail_id
</select>
<select id="selectSndProcessStatus" resultType="kr.xit.biz.ens.model.cmm.SndngMssageParam"> <select id="selectSndProcessStatus" resultType="kr.xit.biz.ens.model.cmm.SndngMssageParam">
/** ens-oracle-mapper|selectSndProcessStatus-발송상태정보조회|julim */ /** ens-oracle-mapper|selectSndProcessStatus-발송상태정보조회|julim */
SELECT tesm.sndng_mastr_id SELECT tesm.sndng_mastr_id

@ -187,6 +187,7 @@ public class ApiConstants {
KAKAO("KKO-MY-DOC", "카카오"), KAKAO("KKO-MY-DOC", "카카오"),
KAKAO_NEW("KKO-NEW", "카카오NEW"), KAKAO_NEW("KKO-NEW", "카카오NEW"),
KT_BC("KT-BC", "공공알림문자"), KT_BC("KT-BC", "공공알림문자"),
KT_GIBIS("KT-GIBIS", "GIBIS알림문자"),
; ;
private final String code; private final String code;

@ -0,0 +1,426 @@
package kr.xit.biz.ens.model.ktgbs;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.Digits;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
import kr.xit.biz.ens.model.kt.KtCommonDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* <pre>
* description :
* packageName : kr.xit.biz.ens.model.ktgbs
* fileName : KtGbsApiDTO
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
public class KtGbsApiDTO {
//-------------------------------------------------------------------
// 메세지 발송
//-------------------------------------------------------------------
@Schema(name = "MsgSendRequest DTO", description = "메세지 발송 요청 request DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = false)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class MsgSendRequest extends KtCommonDTO.KtMnsRequest {
/**
* - (5)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "기관코드", example = "51110")
@Size(min = 5, max = 5, message = "기관코드는 필수 입니다(5자리)")
private String serviceCd;
/**
* - (5)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서코드", example = "DP112")
@Size(min = 5, max = 5, message = "기관코드는 필수 입니다(5자리)")
private String msgCd;
/**
* - (14) : yyyymmddHHmiss
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "생성일시", example = "20240819123456")
@Size(min = 5, max = 5, message = "생성일시는 필수 입니다(14자리)")
private String makeDt;
/**
* - (max:8)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "회차전체데이터건수", example = " ")
@Digits(integer = 8, fraction = 0, message = "회차전체데이터건수(max:8자리)")
private Integer dataCnt;
/**
* - (yyyyMMddHHmiss : 14)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송마감시간(yyyyMMddHHmiss)", example = " ")
@Size(min = 14, max = 14, message = "발송마감시간(yyyyMMddHHmiss)")
private String sendExTime;
/**
* - (yyyyMMddHHmiss : 14)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "열람마감시간(yyyyMMddHHmiss)", example = " ")
@Size(min = 14, max = 14, message = "열람마감시간(yyyyMMddHHmiss)")
private String exTime;
/**
* - (3 : sms|lms|mms)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서종류(sms|lms|mms)", example = " ", allowableValues = {
"sms", "lms", "mms"})
@Size(min = 3, max = 3, message = "문서종류(sms|lms|mms)")
@JsonAlias("m_type")
//@JsonProperty("m_type")
private String mType;
/**
* - (1 : 1-RCS, 2-xMS)
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송메세지타입(1-RCS, 2-xMS)", example = " ", allowableValues = {
"1", "2"})
@Size(min = 1, max = 1, message = "발송메세지타입(1-RCS, 2-xMS)")
private String msgType;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
private List<MsgSendReqsData> reqs;
/**
* ()
*/
@Schema(title = "발신번호", example = " ")
@Size(max = 20, message = "발신번호(max:20)")
private String sndTelNo;
/**
*
*/
@Schema(title = "메세지발송구분", example = " ")
@Digits(integer = 8, fraction = 0, message = "메세지발송구분(max:1자리)")
private Integer optType;
}
@Schema(name = "MsgSendReqsData", description = "메세지 발송 요청 reqs DTO")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class MsgSendReqsData {
//-------------------------------------------------------------------
// 필수
//-------------------------------------------------------------------
/**
* : Unique key
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "관리키", example = "S20211229102000011")
@NotEmpty(message = "관리키는 필수 입니다(max:50)")
@Size(max = 50)
private String srcKey;
/**
* : max 8
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "리스트순번", example = "1")
@NotEmpty(message = "리스트 순번은 필수 입니다(max:8)")
@Size(max = 8)
private String srcSeq;
/**
* : 128
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "개인식별코드", example = "vMtqVxJX56lBgbf9heK3QTc+jVndTfK77i/UJKAzPmBG4n9CazCdd/8YytlFZnN4qofIqgxHpSoiG0yYzgEpJg==")
@Size(min = 128, max = 128, message = "개인식별코드는 필수 입니다(128자리)")
private String sci;
/**
* <pre>
* MMS : max 4000
* URL
* {#INFO_CFRM_STR}, {#RCVE_RF_STR} .
* , 'Y' {#RCVE_RF_STR} .
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "MMS 상세내용", example = "{#INFO_CFRM_STR}, {#RCVE_RF_STR}")
@Size(min = 1, max = 4000, message = "MMS 상세내용 필수입니다(max:4000)")
private String mmsDtlCnts;
/**
* <pre>
* MMS : max 40
* utf-8 20
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "MMS 제목(max:40)", example = "공유재산사용료 정기분")
@Size(min = 1, max = 40, message = "MMS 제목은 필수 입니다(max:40)")
private String mmsTitle;
//-------------------------------------------------------------------
/**
* <pre>
* RCS : max 4000 - RCS|Binary
* RCS fallback mms_dtl_cnts
* RCS title mms_title .
* </pre>
*/
@Schema(title = "RCS 메세지 상세내용(max:4000)", example = " ")
@Size(max = 4000, message = "RCS 메세지 상세내용은 4000자를 넘을 수 없습니다.")
private String rcsDtlCnts;
/**
* <pre>
* URL
* </pre>
*/
@Schema(title = "연결 URL", example = "http://localhost:8081/api/biz/kt/v1/cfmToken")
private String url;
/**
* : max 64
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서해시(max:64)", example = "gdlIa53FZGQz5aKa3wLk33nW57N3mDpcwHytWlWMhzxHKulk7EZs143442394326642342364238648423864237")
@Size(max = 64, message = "문서해시 64자를 넘을 수 없습니다.")
private String docHash;
/**
* <pre>
* : 11
* MDN
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.AUTO, title = "개인휴대전화번호(max:11)", example = "01093414345")
@Size(max = 11, message = "개인 휴대 전화번호는 11자리 입니다")
private String mdn;
}
//-------------------------------------------------------------------
// 메세지 발송
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// 메세지 발송 및 수신결과 전송
//-------------------------------------------------------------------
@Schema(name = "MsgRsltRequest", description = "메세지 발송 및 수신결과 전송 요청 DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
@EqualsAndHashCode(callSuper = false)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class MsgRsltRequest {
/**
* <pre>
* : - 5
* BizCenter
* </pre>>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "서비스코드", example = " ")
@Size(min = 5, max = 5, message = "서비스코드는 필수 입니다(5자리)")
private String serviceCd;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
private List<MsgRsltReqsData> reqs;
}
@Schema(name = "MsgRsltReqsData", description = "메세지 발송 및 수신결과 전송 reqs DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonInclude(JsonInclude.Include.NON_NULL)
@EqualsAndHashCode(callSuper = false)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class MsgRsltReqsData extends CmmEnsRequestDTO {
//-------------------------------------------------------------------
// 필수
//-------------------------------------------------------------------
/**
* : Unique key
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "관리키", example = "S20211229102000001")
@Size(min = 1, max = 50, message = "관리키는 필수 입니다(max:50)")
private String srcKey;
/**
* <pre>
* MMS : - max 8
* 1:(), ():2
* </pre>>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "MMS 발송결과 상태 순번", example = " ", allowableValues = {
"1", "2"})
@Digits(integer = 8, fraction = 0, message = "MMS 발송결과 상태 순번(1|2)")
private Integer mmsSndgRsltSqno;
/**
* <pre>
* : - 8
*
* </pre>>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "처리일자", example = "20231210")
@Size(min = 8, max = 8, message = "처리일자는 필수 입니다(YYYYMMDD)")
private String prcsDt;
/**
* : - 5
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서코드", example = "00001")
@Size(min = 5, max = 5, message = "문서코드는 필수 입니다(5자리)")
private String mmsBsnsDvcd;
/**
* <pre>
* : - 2
* (01:KT, 02:SKT, 03:LGT)
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "모바일사업자구분", example = "01", allowableValues = {"01","02","03"})
@Size(min = 2, max = 2, message = "모바일 사업자 구분은 필수 입니다(01|02|03)")
private String mblBzowrDvcd;
/**
* <pre>
* TODO::
* : - 2
* 40 MMS/RCS
* 41 MMS
* 42 MMS
* 43 MMS ( 24 )
* 47 MMS , ,
* 48 MMS
* 49 MMS
* 4A MMS UNKNOWN/()
* 4D MMS (),
* 4J MMS
* 4N MMS
* 4O MMS LMS()
* 4P MMS LMS()
* 4T MMS ()
* 4Q MMS
* 4R MMS
* 4V MMS
* 4W MMS
* 50
* 60 (MMS=2, )
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송결과코드", example = "40")
@Size(min = 2, max = 2, message = "발송결과코드는 필수 입니다")
private String mmsRsltDvcd;
//private String mmsSndgRsltDvcd;
/**
* <pre>
* : - 14
* YYYYMMDDHHMISS
* </pre>>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송타임스탬프", example = "20241030121000")
@Size(min = 14, max = 14, message = "발송타임스탬프는 필수 입니다(YYYYMMDDHHMISS)")
private String mmsSndgTmst;
/**
* <pre>
* : - 1
* RCS/xMS (RCS :1, xMS: 2)
* </pre>
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송 메시지 타입", example = "2", allowableValues = {"1",
"2"})
@Size(min = 1, max = 1, message = "발송 메시지 타입은 필수 입니다")
private String msgType;
//-------------------------------------------------------------------
/**
* <pre>
* () : max 20
* (****0323)
* </pre>
*/
@Schema(title = "실제발송번호(일부)", example = " ")
@Size(max = 20, message = "실제발송번호(일부)는 20자를 넘을 수 없습니다.")
private String rlMmsSndgTelno;
/**
* <pre>
* : 14
* (mms_sndg_rslt_sqno 1 )
* </pre>>
*/
@Schema(title = "수신타임스탬프", example = " ")
@Size(max = 14, message = "수신타임스탬프는 14자리 입니다")
private String mmsRcvTmst;
/**
* <pre>
* : 14
* (mms_sndg_rslt_sqno 2 )
* </pre>>
*/
@Schema(title = "열람타임스탬프", example = " ")
@Size(max = 14, message = "열람타임스탬프는 14자리 입니다")
private String mmsRdgTmst;
/**
* <pre>
* : 1
* Y: ( )
* N: ( )
* </pre>
*/
@Schema(title = "기동의발송여부", example = "2", allowableValues = {"Y", "N"})
@Size(max = 1, message = "기동의발송여부는 1자리 입니다(Y|N)")
private String prevApproveYn;
/**
* API :
*/
@Schema(requiredMode = Schema.RequiredMode.AUTO, title = "발송결과코드메세지", example = "MMS/RCS 발송 수신성공")
@Size(max = 100, message = "발송결과코드메세지는 100자를 넘을 수 없습니다")
private String mmsRsltDvcdMsg;
/**
* MENS
*/
@Schema(title = "발송구분코드", example = " ")
private String sndngSeCode;
}
//-------------------------------------------------------------------
// 메세지 발송/수신결과 전송
//-------------------------------------------------------------------
}

@ -0,0 +1,18 @@
package kr.xit.biz.ens.model.ktgbs;
/**
* <pre>
* description :
* packageName : kr.xit.biz.ens.model.ktgbs
* fileName : KtGbsDTO
* author : limju
* date : 2024-08-19
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-19 limju
*
* </pre>
*/
public class KtGbsDTO {
}

@ -159,6 +159,25 @@ public class ApiWebClientUtil {
return exchange(url, method, body, rtnClzz, headerMap); return exchange(url, method, body, rtnClzz, headerMap);
} }
/**
* KT-GIBIS WebClient
* (.onStatus status.is4xxClientError() || status.is5xxServerError())
* -> {@link WebClientConfig responseFilter}
* @param url String
* @param method HttpMethod
* @param body Object
* @param rtnClzz Class<T>
* @param ensDTO CmmEnsRlaybsnmDTO
* @return rtnClzz<T>
*/
public <T> T exchangeKtGbs(final String url, final HttpMethod method, final Object body, final Class<T> rtnClzz, final CmmEnsRlaybsnmDTO ensDTO) {
final Map<String,String> headerMap = new HashMap<>();
headerMap.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headerMap.put(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", ensDTO.getKtAccessToken()));
return exchange(url, method, body, rtnClzz, headerMap);
}
/** /**
* <pre> * <pre>
* WebClient * WebClient

Loading…
Cancel
Save