feat: 카카오톡 전자우편 API 신규 추가 - D10_2
parent
4545e29e3a
commit
adffdca5c5
@ -0,0 +1,95 @@
|
|||||||
|
package kr.xit.ens.kakao.v2.service;
|
||||||
|
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDocDTO;
|
||||||
|
import kr.xit.core.model.ApiResponseDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* description : 카카오 페이 전자 문서 발송 요청 인터 페이스
|
||||||
|
* packageName : kr.xit.ens.kakao.v1.service
|
||||||
|
* fileName : IKkopayEltrcDocService
|
||||||
|
* author : julim
|
||||||
|
* date : 2023-04-28
|
||||||
|
* ======================================================================
|
||||||
|
* 변경일 변경자 변경 내용
|
||||||
|
* ----------------------------------------------------------------------
|
||||||
|
* 2023-04-28 julim 최초 생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface IKkotalkEltrcDocService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 모바일웹 연계 문서발송 요청
|
||||||
|
* -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDocDTO.SendRequest
|
||||||
|
* @return KkotalkDocDTO.SendResponse
|
||||||
|
*/
|
||||||
|
KkotalkDTO.SendResponse requestSend(final KkotalkDTO.SendRequest reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 토큰 유효성 검증(Redirect URL 접속 허용/불허)
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDocDTO.ValidTokenRequest
|
||||||
|
* @return KkotalkDocDTO.ValidTokenResponse>
|
||||||
|
*/
|
||||||
|
KkotalkDocDTO.ValidTokenResponse validToken(final KkotalkDocDTO.ValidTokenRequest reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람 처리 API
|
||||||
|
* -.문서에 대해서 열람 상태로 변경. 사용자가 문서열람 시(OTT 검증 완료 후 페이지 로딩 완료 시점) 반드시 문서 열람 상태 변경 API를 호출해야 함.
|
||||||
|
* -.미 호출 시 아래와 같은 문제 발생
|
||||||
|
* 1)유통증명시스템을 사용하는 경우 해당 API를 호출한 시점으로 열람정보가 등록되어 미 호출 시 열람정보가 등록 되지 않음.
|
||||||
|
* 2)문서상태조회 API(/v1/envelopes/${ENVELOPE_ID}/read) 호출 시 read_at최초 열람시간) 데이터가 내려가지 않음.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.EnvelopeId
|
||||||
|
*/
|
||||||
|
void modifyStatus(final KkotalkDTO.EnvelopeId reqDTO);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 상태 조회 API
|
||||||
|
* -.이용기관 서버에서 카카오페이 전자문서 서버로 문서 상태에 대한 조회를 요청 합니다.
|
||||||
|
* : 발송된 문서의 진행상태를 알고 싶은 경우, flow와 상관없이 요청 가능
|
||||||
|
* : polling 방식으로 호출할 경우, 호출 간격은 5초를 권장.
|
||||||
|
* -.doc_box_status 상태변경순서
|
||||||
|
* : RECEIVE(수신, 미처리) > READ(열람)/EXPIRED
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.EnvelopeId
|
||||||
|
* @return KkotalkDocDTO.EnvelopeStatusResponse
|
||||||
|
*/
|
||||||
|
KkotalkDocDTO.EnvelopeStatusResponse findStatus(final KkotalkDocDTO.EnvelopeId reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 대량(bulk) 문서발송 요청
|
||||||
|
* -.이용기관 서버에서 카카오페이 내문서함 서버로 대량(bulk) 문서발송 처리를 요청합니다.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkopayDocBulkDTO.BulkSendRequests
|
||||||
|
* @return KkopayDocBulkDTO.BulkSendResponses
|
||||||
|
*/
|
||||||
|
KkotalkDTO.BulkSendResponse requestSendBulk(final KkotalkDTO.BulkSendRequest reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 대량(bulk) 문서 상태 조회 API
|
||||||
|
* -.이용기관 서버에서 카카오페이 전자문서 서버로 문서 상태에 대한 조회를 요청 합니다.
|
||||||
|
* : 발송된 문서의 진행상태를 알고 싶은 경우, flow와 상관없이 요청 가능
|
||||||
|
* : polling 방식으로 호출할 경우, 호출 간격은 5초를 권장.
|
||||||
|
* : RECEIVED(수신,미수신) > READ(열람)/EXPIRED
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.BulkStatusRequest
|
||||||
|
* @return KkotalkDTO.BulkStatusResponse
|
||||||
|
*/
|
||||||
|
KkotalkDTO.BulkStatusResponse findBulkStatus(final KkotalkDTO.BulkStatusRequest reqDTO);
|
||||||
|
|
||||||
|
|
||||||
|
ApiResponseDTO<KkotalkDocDTO.ValidTokenResponse> findMyDocReadyAndMblPage(KkotalkDocDTO.ValidTokenRequest reqDTO);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,332 @@
|
|||||||
|
package kr.xit.ens.kakao.v2.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.Validation;
|
||||||
|
import javax.validation.Validator;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import kr.xit.biz.common.ApiConstants.SndngSeCode;
|
||||||
|
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
|
||||||
|
import kr.xit.biz.ens.model.cmm.CmmEnsRlaybsnmDTO;
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDocDTO;
|
||||||
|
import kr.xit.core.exception.BizRuntimeException;
|
||||||
|
import kr.xit.core.model.ApiResponseDTO;
|
||||||
|
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.Checks;
|
||||||
|
import kr.xit.core.support.utils.JsonUtils;
|
||||||
|
import kr.xit.ens.cmm.CmmEnsUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* description : 카카오 페이 전자 문서 발송 요청 서비스
|
||||||
|
* packageName : kr.xit.ens.kakao.v1.service
|
||||||
|
* fileName : KkopayEltrcDocService
|
||||||
|
* author : julim
|
||||||
|
* date : 2023-04-28
|
||||||
|
* ======================================================================
|
||||||
|
* 변경일 변경자 변경 내용
|
||||||
|
* ----------------------------------------------------------------------
|
||||||
|
* 2023-04-28 julim 최초 생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Component
|
||||||
|
public class KkotalkEltrcDocService extends AbstractService implements
|
||||||
|
IKkotalkEltrcDocService {
|
||||||
|
|
||||||
|
@Value("${app.contract.kakao.api.talk.host}")
|
||||||
|
private String HOST;
|
||||||
|
|
||||||
|
@Value("#{'${app.contract.kakao.api.talk.send}'.split(';')}")
|
||||||
|
private String[] API_SEND;
|
||||||
|
|
||||||
|
@Value("#{'${app.contract.kakao.api.talk.bulksend}'.split(';')}")
|
||||||
|
private String[] API_BULKSEND;
|
||||||
|
|
||||||
|
@Value("#{'${app.contract.kakao.api.talk.validToken}'.split(';')}")
|
||||||
|
private String[] API_VALID_TOKEN;
|
||||||
|
|
||||||
|
@Value("#{'${app.contract.kakao.api.talk.modifyStatus}'.split(';')}")
|
||||||
|
private String[] API_MODIFY_STATUS;
|
||||||
|
|
||||||
|
|
||||||
|
@Value("#{'${app.contract.kakao.api.talk.bulkstatus}'.split(';')}")
|
||||||
|
private String[] API_BULKSTATUS;
|
||||||
|
|
||||||
|
private final ApiWebClientUtil webClient;
|
||||||
|
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||||
|
private static final CharSequence ENVELOPE_ID = "{ENVELOPE_ID}";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 모바일웹 연계 문서발송 요청 : POST
|
||||||
|
* -.이용기관 서버에서 전자문서 서버로 문서발송 처리 요청
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkoPayEltrDocDTO.RequestSendReq
|
||||||
|
* @return ApiResponseDTO<KkopayDocDTO.SendResponse>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public KkotalkDTO.SendResponse requestSend(final KkotalkDTO.SendRequest reqDTO) {
|
||||||
|
if(Checks.isEmpty(reqDTO.getProductCode())){
|
||||||
|
throw BizRuntimeException.create("상품 코드는 필수 입니다.");
|
||||||
|
}
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
errors = validate(reqDTO.getEnvelope(), errors);
|
||||||
|
|
||||||
|
final KkotalkDocDTO.Envelope envelope = reqDTO.getEnvelope();
|
||||||
|
if(envelope.getReviewExpiresAt() != null){
|
||||||
|
if(envelope.getReviewExpiresAt().compareTo(envelope.getReadExpiresAt()) < 0){
|
||||||
|
errors.add("reviewExpiresAt=재열람 만료일시를 최조 열람 만료일시 보다 큰 날짜로 입력해주세요.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Checks.isEmpty(envelope.getCi())){
|
||||||
|
if(Checks.isEmpty(envelope.getName())) Objects.requireNonNull(errors).add("name=받는이 이름은 필수입니다.");
|
||||||
|
if(Checks.isEmpty(envelope.getPhoneNumber())) Objects.requireNonNull(errors).add("phoneNumber=받는이 전화번호는 필수입니다.");
|
||||||
|
if(Checks.isEmpty(envelope.getBirthday())) Objects.requireNonNull(errors).add("birthday=받는이 생년월일은 필수입니다.");
|
||||||
|
}
|
||||||
|
if(!Objects.requireNonNull(errors).isEmpty()) throw BizRuntimeException.create(errors.toString());
|
||||||
|
return webClient.exchangeKkopay(
|
||||||
|
HOST + API_SEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
|
||||||
|
HttpMethod.valueOf(API_SEND[1]),
|
||||||
|
JsonUtils.toJson(envelope),
|
||||||
|
KkotalkDTO.SendResponse.class,
|
||||||
|
getRlaybsnmInfo(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 토큰 유효성 검증(Redirect URL 접속 허용/불허) : GET
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkopayDocDTO.ValidTokenRequest
|
||||||
|
* @return ApiResponseDTO<KkopayDocDTO.ValidTokenResponse>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public KkotalkDocDTO.ValidTokenResponse validToken(final KkotalkDocDTO.ValidTokenRequest reqDTO) {
|
||||||
|
validate(reqDTO, null);
|
||||||
|
|
||||||
|
return webClient.exchangeKkotalk(
|
||||||
|
HOST
|
||||||
|
+ API_VALID_TOKEN[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId())
|
||||||
|
.replace("{TOKEN}", reqDTO.getToken()),
|
||||||
|
HttpMethod.valueOf(API_VALID_TOKEN[1]),
|
||||||
|
null,
|
||||||
|
KkotalkDocDTO.ValidTokenResponse.class,
|
||||||
|
getRlaybsnmInfo(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람 처리 API : POST
|
||||||
|
* -.문서에 대해서 열람 상태로 변경. 사용자가 문서열람 시(OTT 검증 완료 후 페이지 로딩 완료 시점) 반드시 문서 열람 상태 변경 API를 호출해야 함.
|
||||||
|
* -.미 호출 시 아래와 같은 문제 발생
|
||||||
|
* 1)유통증명시스템을 사용하는 경우 해당 API를 호출한 시점으로 열람정보가 등록되어 미 호출 시 열람정보가 등록 되지 않음.
|
||||||
|
* 2)문서상태조회 API(/v1/envelopes/${ENVELOPE_ID}/read) 호출 시 read_at최초 열람시간) 데이터가 내려가지 않음.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkopayDocAttrDTO.EnvelopeId
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public void modifyStatus(final KkotalkDTO.EnvelopeId reqDTO){
|
||||||
|
validate(reqDTO.getEnvelopeId(), null);
|
||||||
|
|
||||||
|
final String url = HOST + API_MODIFY_STATUS[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId());
|
||||||
|
|
||||||
|
webClient.exchangeKkopay(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), null, Void.class, getRlaybsnmInfo(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 상태 조회 API : GET
|
||||||
|
* -.이용기관 서버에서 카카오페이 전자문서 서버로 문서 상태에 대한 조회를 요청 합니다.
|
||||||
|
* : 발송된 문서의 진행상태를 알고 싶은 경우, flow와 상관없이 요청 가능
|
||||||
|
* : polling 방식으로 호출할 경우, 호출 간격은 5초를 권장.
|
||||||
|
* : RECEIVE(수신,미수신) > READ(열람)/EXPIRED
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.EnvelopeId
|
||||||
|
* @return KkotalkDocDTO.EnvelopeStatusResponse
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public KkotalkDocDTO.EnvelopeStatusResponse findStatus(final KkotalkDocDTO.EnvelopeId reqDTO){
|
||||||
|
validate(reqDTO, null);
|
||||||
|
|
||||||
|
|
||||||
|
KkotalkDTO.BulkStatusResponse res = webClient.exchangeKkotalk(
|
||||||
|
HOST + API_BULKSTATUS[0],
|
||||||
|
HttpMethod.valueOf(API_BULKSTATUS[1]),
|
||||||
|
JsonUtils.toJson(List.of(reqDTO.getEnvelopeId())),
|
||||||
|
KkotalkDTO.BulkStatusResponse.class,
|
||||||
|
getRlaybsnmInfo(reqDTO));
|
||||||
|
return res.getEnvelopeStatus().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 모바일웹 연계 문서발송 요청 : POST
|
||||||
|
* -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.BulkSendRequest
|
||||||
|
* @return KkotalkDTO.BulkSendResponse
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public KkotalkDTO.BulkSendResponse requestSendBulk(final KkotalkDTO.BulkSendRequest reqDTO) {
|
||||||
|
if(Checks.isEmpty(reqDTO.getProductCode())){
|
||||||
|
throw BizRuntimeException.create("상품 코드는 필수 입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
List<KkotalkDocDTO.Envelope> envelopes = reqDTO.getEnvelopes();
|
||||||
|
for(int idx = 0; idx < envelopes.size(); idx++) {
|
||||||
|
final Set<ConstraintViolation<KkotalkDocDTO.Envelope>> list = validator.validate(envelopes.get(idx));
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
|
||||||
|
int finalIdx = idx;
|
||||||
|
errors.addAll(list.stream()
|
||||||
|
.map(row -> String.format("%s[%d]=%s", row.getPropertyPath(), finalIdx +1, row.getMessageTemplate()))
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int idx = 0; idx < envelopes.size(); idx++) {
|
||||||
|
final KkotalkDocDTO.Envelope envelope = envelopes.get(idx);
|
||||||
|
|
||||||
|
if(envelope.getReviewExpiresAt() != null){
|
||||||
|
if(envelope.getReviewExpiresAt().compareTo(envelope.getReadExpiresAt()) < 0){
|
||||||
|
errors.add("reviewExpiresAt=재열람 만료일시를 최조 열람 만료일시 보다 큰 날짜로 입력해주세요.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Checks.isEmpty(envelope.getCi())) {
|
||||||
|
if (Checks.isEmpty(envelope.getName())) errors.add(String.format("받는이 이름은 필수입니다(name[%d] 번째 오류)", idx+1));
|
||||||
|
if (Checks.isEmpty(envelope.getPhoneNumber())) errors.add(String.format("받는이 전화번호는 필수입니다(phoneNumber[%d] 번째 오류)", idx+1));
|
||||||
|
if (Checks.isEmpty(envelope.getBirthday())) errors.add(String.format("받는이 생년월일은 필수입니다(birthday[%d] 번째 오류)", idx+1));
|
||||||
|
} else {
|
||||||
|
final StringBuilder sb = new StringBuilder()
|
||||||
|
.append(StringUtils.defaultString(envelope.getName(), StringUtils.EMPTY))
|
||||||
|
.append(StringUtils.defaultString(envelope.getPhoneNumber(), StringUtils.EMPTY))
|
||||||
|
.append(StringUtils.defaultString(envelope.getBirthday(), StringUtils.EMPTY));
|
||||||
|
|
||||||
|
if(Checks.isNotEmpty(sb.toString())){
|
||||||
|
errors.add(String.format("CI가 지정 되었습니다(받는이 정보 불필요:[%d] 번째 오류) .", idx+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!errors.isEmpty()){
|
||||||
|
throw BizRuntimeException.create(errors.toString());
|
||||||
|
}
|
||||||
|
return webClient.exchangeKkotalk(
|
||||||
|
HOST + API_SEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
|
||||||
|
HttpMethod.valueOf(API_BULKSEND[1]),
|
||||||
|
JsonUtils.toJson(envelopes),
|
||||||
|
KkotalkDTO.BulkSendResponse.class,
|
||||||
|
getRlaybsnmInfo(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 대량(bulk) 문서 상태 조회 API : POST
|
||||||
|
* -.이용기관 서버에서 카카오페이 전자문서 서버로 문서 상태에 대한 조회를 요청 합니다.
|
||||||
|
* : 발송된 문서의 진행상태를 알고 싶은 경우, flow와 상관없이 요청 가능
|
||||||
|
* : polling 방식으로 호출할 경우, 호출 간격은 5초를 권장.
|
||||||
|
* : RECEIVE(수신,미수신) > READ(열람)/EXPIRED
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.BulkStatusRequest
|
||||||
|
* @return KkotalkDTO.BulkStatusResponse
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@TraceLogging
|
||||||
|
public KkotalkDTO.BulkStatusResponse findBulkStatus(final KkotalkDTO.BulkStatusRequest reqDTO) {
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> envelopes = reqDTO.getEnvelopes();
|
||||||
|
for(int idx = 0; idx < envelopes.size(); idx++) {
|
||||||
|
final String binderUuid = envelopes.get(idx);
|
||||||
|
if (Checks.isEmpty(binderUuid) || binderUuid.length() > 40) {
|
||||||
|
errors.add(String.format("문서 식별 번호는 40자를 넘을 수 없습니다[%d번째]", idx+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!errors.isEmpty()) {
|
||||||
|
throw BizRuntimeException.create(errors.toString());
|
||||||
|
}
|
||||||
|
return webClient.exchangeKkopay(
|
||||||
|
HOST + API_BULKSTATUS[0],
|
||||||
|
HttpMethod.valueOf(API_BULKSTATUS[1]),
|
||||||
|
JsonUtils.toJson(envelopes),
|
||||||
|
KkotalkDTO.BulkStatusResponse.class,
|
||||||
|
getRlaybsnmInfo(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResponseDTO<KkotalkDocDTO.ValidTokenResponse> findMyDocReadyAndMblPage(final KkotalkDocDTO.ValidTokenRequest reqDTO) {
|
||||||
|
final String url = HOST + API_VALID_TOKEN[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId())
|
||||||
|
.replace("{TOKEN}", reqDTO.getToken());
|
||||||
|
|
||||||
|
// 유효성 검증
|
||||||
|
final KkotalkDocDTO.ValidTokenResponse validTokenRes = webClient.exchangeKkotalk(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null,
|
||||||
|
KkotalkDocDTO.ValidTokenResponse.class, getRlaybsnmInfo(reqDTO));
|
||||||
|
|
||||||
|
// FIXME: USED ??
|
||||||
|
if(!"USED".equals(validTokenRes.getStatus())){
|
||||||
|
return ApiResponseDTO.error(validTokenRes.getErrorCode(), validTokenRes.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 문서상태 변경
|
||||||
|
final String url2 = HOST + API_MODIFY_STATUS[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId());
|
||||||
|
|
||||||
|
// 정상 : HttpStatus.NO_CONTENT(204) return
|
||||||
|
// error : body에 error_code, error_message return
|
||||||
|
final KkotalkDocDTO.KkotalkErrorDTO errorDTO = webClient.exchangeKkotalk(url2, HttpMethod.valueOf(API_MODIFY_STATUS[1]), null, KkotalkDocDTO.KkotalkErrorDTO.class, getRlaybsnmInfo(reqDTO));
|
||||||
|
if(errorDTO != null){
|
||||||
|
return ApiResponseDTO.error(errorDTO.getErrorCode(), errorDTO.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ApiResponseDTO.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------------------------
|
||||||
|
private static <T> List<String> validate(T t, List<String> errList) {
|
||||||
|
final Set<ConstraintViolation<T>> list = validator.validate(t);
|
||||||
|
|
||||||
|
if(!list.isEmpty()) {
|
||||||
|
final List<String> errors = list.stream()
|
||||||
|
.map(row -> String.format("%s=%s", row.getPropertyPath(), row.getMessageTemplate()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// 추가적인 유효성 검증이 필요 없는 경우
|
||||||
|
if(errList == null){
|
||||||
|
if(!errors.isEmpty()) throw BizRuntimeException.create(errors.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
errList.addAll(errors);
|
||||||
|
}
|
||||||
|
return errList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CmmEnsRlaybsnmDTO getRlaybsnmInfo(final CmmEnsRequestDTO request){
|
||||||
|
return CmmEnsUtils.getRlaybsnmInfo(request.getSignguCode(), request.getFfnlgCode(), SndngSeCode.KAKAO);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,201 @@
|
|||||||
|
package kr.xit.ens.kakao.v2.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.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDTO;
|
||||||
|
import kr.xit.biz.ens.model.kakao.v2.KkotalkDocDTO;
|
||||||
|
import kr.xit.core.model.ApiResponseDTO;
|
||||||
|
import kr.xit.core.model.IApiResponse;
|
||||||
|
import kr.xit.ens.kakao.v2.service.IKkotalkEltrcDocService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* description : 카카오톡 전자 문서 발송 controller
|
||||||
|
* packageName : kr.xit.ens.kakao.v2.web
|
||||||
|
* fileName : KkotalkEltrcDocController
|
||||||
|
* author : julim
|
||||||
|
* date : 2024-08-12
|
||||||
|
* ======================================================================
|
||||||
|
* 변경일 변경자 변경 내용
|
||||||
|
* ----------------------------------------------------------------------
|
||||||
|
* 2024-08-12 julim 최초 생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Tag(name = "KkotalkEltrcDocController", description = "카카오톡 전자문서 API")
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/api/ens/kakao/v2")
|
||||||
|
public class KkotalkEltrcDocController {
|
||||||
|
private final IKkotalkEltrcDocService service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 모바일웹 연계 문서발송 요청
|
||||||
|
* -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkopayDocDTO.SendRequest
|
||||||
|
* @return ApiResponseDTO<KkopayDocDTO.SendResponse>
|
||||||
|
*/
|
||||||
|
@Operation(summary = "문서발송 요청", description = "카카오톡 전자문서 서버로 문서발송 처리를 요청")
|
||||||
|
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
|
||||||
|
@Content(mediaType = "application/json", examples = {
|
||||||
|
@ExampleObject(
|
||||||
|
name = "D10",
|
||||||
|
value = """
|
||||||
|
{
|
||||||
|
"productCode": "D10_1",
|
||||||
|
"envelope": {
|
||||||
|
"title": "전자문서",
|
||||||
|
"content": {
|
||||||
|
"link": "https://nps.or.kr"
|
||||||
|
},
|
||||||
|
"guide": "국민연금 공단에서 보내는 문서입니다.",
|
||||||
|
"payload": "이용기관 페이로드",
|
||||||
|
"readExpiresAt": "2023-12-31T10:00:00",
|
||||||
|
"reviewExpiresAt": "2023-12-31T13:00:00",
|
||||||
|
"useNonPersonalizedNotification": true,
|
||||||
|
"phoneNumber": "01099999999",
|
||||||
|
"name": "홍길동",
|
||||||
|
"birthday": "20000303",
|
||||||
|
"externalId": "external_id1"
|
||||||
|
},
|
||||||
|
"signguCode": "51110",
|
||||||
|
"ffnlgCode": "11"
|
||||||
|
}
|
||||||
|
"""),
|
||||||
|
@ExampleObject(
|
||||||
|
name = "D11",
|
||||||
|
value = """
|
||||||
|
{
|
||||||
|
"productCode": "D11_1",
|
||||||
|
"envelope": {
|
||||||
|
"title": "전자문서",
|
||||||
|
"content": {
|
||||||
|
"html": "<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>"
|
||||||
|
},
|
||||||
|
"guide": "국민연금 공단에서 보내는 문서입니다.",
|
||||||
|
"readExpiresAt": "2023-12-31T10:00:00",
|
||||||
|
"reviewExpiresAt": "2023-12-31T13:00:00",
|
||||||
|
"ci": "${CI}"
|
||||||
|
},
|
||||||
|
"signguCode": "51110",
|
||||||
|
"ffnlgCode": "11"
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
@PostMapping(value = "/envelopes", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse requestSend(
|
||||||
|
@RequestBody final KkotalkDTO.SendRequest reqDTO
|
||||||
|
) {
|
||||||
|
return ApiResponseDTO.success(service.requestSend(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 토큰 유효성 검증(Redirect URL 접속 허용/불허)
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkopayDocDTO.ValidTokenRequest
|
||||||
|
* @return ApiResponseDTO<KkopayDocDTO.ValidTokenResponse>
|
||||||
|
*/
|
||||||
|
@Operation(summary = "토큰 유효성 검증", description = "Redirect URL 접속 허용/불허")
|
||||||
|
@PostMapping(value = "/validToken", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse validToken(
|
||||||
|
@RequestBody final KkotalkDTO.ValidTokenRequest reqDTO
|
||||||
|
) {
|
||||||
|
return ApiResponseDTO.success(service.validToken(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람처리 API
|
||||||
|
* -.문서에 대해서 열람 상태로 변경. 사용자가 문서열람 시(OTT 검증 완료 후 페이지 로딩 완료 시점) 반드시 문서 열람 상태 변경 API를 호출해야 함.
|
||||||
|
* -.미 호출 시 아래와 같은 문제 발생
|
||||||
|
* 1)유통증명시스템을 사용하는 경우 해당 API를 호출한 시점으로 열람정보가 등록되어 미 호출 시 열람정보가 등록 되지 않음.
|
||||||
|
* 2)문서상태조회 API(/v1/envelopes/${ENVELOPE_ID}/read) 호출 시 read_at최초 열람시간) 데이터가 내려가지 않음.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDocDTO.EnvelopeStatusResponse
|
||||||
|
* @return ApiResponseDTO<Void>
|
||||||
|
*/
|
||||||
|
@Operation(summary = "문서열람처리(문서 상태 변경)", description = "문서열람처리(문서 상태 변경)")
|
||||||
|
@PostMapping(value = "/modifyStatus", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse modifyStatus(
|
||||||
|
@RequestBody final KkotalkDocDTO.EnvelopeId reqDTO
|
||||||
|
) {
|
||||||
|
service.modifyStatus(reqDTO);
|
||||||
|
return ApiResponseDTO.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 상태 조회 API
|
||||||
|
* -.이용기관 서버에서 카카오페이 전자문서 서버로 문서 상태에 대한 조회를 요청 합니다.
|
||||||
|
* : 발송된 문서의 진행상태를 알고 싶은 경우, flow와 상관없이 요청 가능
|
||||||
|
* : polling 방식으로 호출할 경우, 호출 간격은 5초를 권장.
|
||||||
|
* -.doc_box_status 상태변경순서
|
||||||
|
* : SENT(송신) > RECEIVED(수신) > READ(열람)/EXPIRED(미열람자료의 기한만료)
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDTO.EnvelopeId
|
||||||
|
* @return ApiResponseDTO<KkotalkDocDTO.EnvelopeStatusResponse>
|
||||||
|
*/
|
||||||
|
@Operation(summary = "문서 상태 조회", description = "문서 상태 조회")
|
||||||
|
@PostMapping(value = "/findStatus", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse findStatus(
|
||||||
|
@RequestBody final KkotalkDocDTO.EnvelopeId reqDTO
|
||||||
|
) {
|
||||||
|
return ApiResponseDTO.success(service.findStatus(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * <pre>
|
||||||
|
// * 모바일웹 연계 문서발송 요청
|
||||||
|
// * -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
|
||||||
|
// * </pre>
|
||||||
|
// * @param reqDTO KkopayDocBulkDTO.BulkSendRequests
|
||||||
|
// * @return BulkStatusResponses.BulkSendResponses
|
||||||
|
// */
|
||||||
|
// /*
|
||||||
|
// @Operation(summary = "대량 문서발송 요청 -> batch sendBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청 -> batch sendBulks 에서 호출")
|
||||||
|
// @PostMapping(value = "/documents/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
// public BulkSendResponses requestSendBulk(
|
||||||
|
// @RequestBody final BulkSendRequests reqDTO
|
||||||
|
// ) {
|
||||||
|
// return service.requestSendBulk(reqDTO);
|
||||||
|
// }
|
||||||
|
// */
|
||||||
|
@Operation(summary = "대량 문서발송 요청 -> batch sendBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청 -> batch sendBulks 에서 호출")
|
||||||
|
@PostMapping(value = "/envelopes/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse requestSendBulk(
|
||||||
|
@RequestBody final KkotalkDTO.BulkSendRequest reqDTO
|
||||||
|
) {
|
||||||
|
return ApiResponseDTO.success(service.requestSendBulk(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 모바일웹 연계 문서발송 요청
|
||||||
|
* -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
|
||||||
|
* </pre>
|
||||||
|
* @param reqDTO KkotalkDocDTO.BulkStatusRequest
|
||||||
|
* @return KkotalkDocDTO.BulkStatusResponse
|
||||||
|
*/
|
||||||
|
@Operation(summary = "대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출")
|
||||||
|
@PostMapping(value = "/documents/bulk/status", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public IApiResponse findBulkStatus(
|
||||||
|
@RequestBody final KkotalkDTO.BulkStatusRequest reqDTO
|
||||||
|
) {
|
||||||
|
return ApiResponseDTO.success(service.findBulkStatus(reqDTO));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
package kr.xit.biz.ens.model.kakao.v2;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
|
||||||
|
import kr.xit.core.model.IApiResponse;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* description : 카카오톡 전자문서 요청 파라메터 및 응답 DTO
|
||||||
|
*
|
||||||
|
* packageName : kr.xit.ens.model.kakao.v2
|
||||||
|
* fileName : KkotalkDTO
|
||||||
|
* author : limju
|
||||||
|
* date : 2024-08-12
|
||||||
|
* ======================================================================
|
||||||
|
* 변경일 변경자 변경 내용
|
||||||
|
* ----------------------------------------------------------------------
|
||||||
|
* 2024-08-12 limju 최초 생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class KkotalkDTO extends KkotalkDocDTO {
|
||||||
|
|
||||||
|
//------------------ envelop ----------------------------------------------------------------------
|
||||||
|
@Schema(name = "SendRequest DTO", description = "문서발송 request DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class SendRequest extends CmmEnsRequestDTO {
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 상품 코드 - 필수
|
||||||
|
* D10_1|D10_2|D11_1|D11_2
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "상품코드", example = "D10_2", allowableValues = {"D10_1","D10_2","D11_1","D11_2"})
|
||||||
|
@Size(min = 3, max = 5, message = "상품 코드는 필수 입니다(\"D10_1\",\"D10_2\",\"D11_1\",\"D11_2\"")
|
||||||
|
@Builder.Default
|
||||||
|
private String productCode = "D10_2";
|
||||||
|
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@Valid
|
||||||
|
private Envelope envelope;
|
||||||
|
}
|
||||||
|
//------------------ envelop ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------ bulk ----------------------------------------------------------------------
|
||||||
|
@Schema(name = "BulkSendRequest DTO", description = "문서발송[bulk] request DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class BulkSendRequest extends CmmEnsRequestDTO {
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 상품 코드 - 필수
|
||||||
|
* D10_1|D10_2|D11_1|D11_2
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "상품코드", example = "D10_2", allowableValues = {"D10_1","D10_2","D11_1","D11_2"})
|
||||||
|
@Size(min = 3, max = 5, message = "상품 코드는 필수 입니다(\"D10_1\",\"D10_2\",\"D11_1\",\"D11_2\"")
|
||||||
|
@Builder.Default
|
||||||
|
private String productCode = "D10_2";
|
||||||
|
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@Valid
|
||||||
|
private List<Envelope> envelopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "BulkSendResponse DTO", description = "문서발송(bulk) response DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class BulkSendResponse extends KkotalkErrorDTO {
|
||||||
|
private List<EnvelopeRes> envelopeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "BulkStatusRequest DTO", description = "문서상태조회[bulk] request DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class BulkStatusRequest extends CmmEnsRequestDTO {
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@Valid
|
||||||
|
private List<String> envelopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "BulkStatusResponse DTO", description = "문서상태조회(bulk) response DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public static class BulkStatusResponse implements IApiResponse {
|
||||||
|
private List<KkotalkDocDTO.EnvelopeStatusResponse> envelopeStatus;
|
||||||
|
}
|
||||||
|
//------------------ bulk ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,427 @@
|
|||||||
|
package kr.xit.biz.ens.model.kakao.v2;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import kr.xit.biz.common.ApiConstants;
|
||||||
|
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
|
||||||
|
import kr.xit.core.model.IApiResponse;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* description : 카카오톡 전자문서 DTO
|
||||||
|
* API 호출시 속성값이 없는 경우 속성을 json에 포함시키지 않는다.
|
||||||
|
* => @JsonInclude(JsonInclude.Include.NON_EMPTY) 설정
|
||||||
|
* packageName : kr.xit.biz.ens.model.kakao.v2
|
||||||
|
* fileName : KkotalkDocDTO
|
||||||
|
* author : limju
|
||||||
|
* date : 2024-08-12
|
||||||
|
* ======================================================================
|
||||||
|
* 변경일 변경자 변경 내용
|
||||||
|
* ----------------------------------------------------------------------
|
||||||
|
* 2024-08-12 limju 최초 생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class KkotalkDocDTO {
|
||||||
|
|
||||||
|
//------------------- Envelope ------------------------------------------------------------------------------------------------
|
||||||
|
@Schema(name = "Envelope", description = "문서발송(단건) 요청 파라메터 DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public static class Envelope implements IApiResponse {
|
||||||
|
/**
|
||||||
|
* 발송할 문서의 제목 : 필수 - max 40자
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송할 문서의 제목", example = "문서 제목")
|
||||||
|
@Size(max = 40, message = "발송할 문서의 제목은 필수 입니다(max:40)")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@Valid
|
||||||
|
private Content content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 원문(열람정보)에 대한 hash 값
|
||||||
|
* D10_2 상품 사용시 필수
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "문서 원문(열람정보)에 대한 hash 값", example = "6EFE827AC88914DE471C621AE")
|
||||||
|
@Pattern(regexp = "^$|^[a-fA-F0-9]{44}$|^[a-fA-F0-9]{64}$", message = "문서 해시값은 44자 또는 64자의 16진수여야 합니다")
|
||||||
|
private String hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 문서 정보 안내 화면에 노출할 문구(최대: 500자) - 필수
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 정보 안내 화면에 노출할 문구(최대: 500자)", example = "문서 정보 안내 화면에 노출할 문구")
|
||||||
|
@Size(min=1, max = 200, message = "문서 정보 안내 화면에 노출할 문구(max=500)")
|
||||||
|
private String guide;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* payload
|
||||||
|
*/
|
||||||
|
@Schema(title = "payload", example = "payload 파라미터 입니다.")
|
||||||
|
@Size(max = 200, message = "payload(max=200)")
|
||||||
|
private String payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 최초 열람 만료 일시 지정(최대: 요청 일시로부터 6개월 이내) - 필수
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "최초열람마감시간(yyyy-MM-dd'T'HH:mm:ss)", example = "2023-12-31T10:00:00")
|
||||||
|
@Size(min = 19, max = 19, message = "최초열람마감시간(yyyy-MM-dd'T'HH:mm:ss)")
|
||||||
|
private String readExpiresAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 재열람 만료 일시 지정
|
||||||
|
* 최소: readExpiredAt 이후의 시각
|
||||||
|
* 최대값: 9999-12-31'T'23:59:59, null 값이면 무제한
|
||||||
|
* 비고: DX0 상품인 경우 최대값은 요청일로부터 6개월 이내
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "재열람 만료 일시(yyyy-MM-dd'T'HH:mm:ss)", example = "2023-12-31T13:00:00")
|
||||||
|
@Size(max = 19, message = "재열람 만료 일시(yyyy-MM-dd'T'HH:mm:ss)")
|
||||||
|
private String reviewExpiresAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 알림톡 내용에 개인정보 제거 여부
|
||||||
|
* default: false
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "알림톡 내용에 개인정보 제거 여부", example = " ", defaultValue = "false", allowableValues = {"true", "false"})
|
||||||
|
@Builder.Default
|
||||||
|
private Boolean useNonPersonalizedNotification = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 수신자 CI
|
||||||
|
*/
|
||||||
|
@Schema(title = "받는이 CI", example = " ")
|
||||||
|
@Size(max=88, message = "수신자 CI(max=88)")
|
||||||
|
private String ci;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 수신자 전화번호
|
||||||
|
* ci 미전송시 필수
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "수신자 전화번호", example = "01012345678")
|
||||||
|
@Pattern(regexp = "^$|^\\d{11}$", message = "수신자 전화번호(max=11)")
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 수신자 이름
|
||||||
|
* ci 미전송시 필수
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "수신자 이름", example = "김페이")
|
||||||
|
@Size(max = 26, message = "수신자 이름(max=26)")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 수신자 생년월일 (YYYY-MM-DD 형식)
|
||||||
|
* ci 미전송시 필수
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.AUTO, title = "수신자 생년월일 (YYYYMMDD 형식)", example = "19801101")
|
||||||
|
@Pattern(regexp = "^$|^(19\\d{2}|20\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])$", message = "수신자 생년월일(YYYYMMDD)")
|
||||||
|
private String birthday;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서매핑용 식별자 - 최대 40자
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.AUTO, title = "문서매핑용 식별자", example = " ")
|
||||||
|
@Size(max=40, message = "문서매핑용 식별자(max=40)")
|
||||||
|
private String externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "Content", description = "문서 원문 웹링크 또는 HTML")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public static class Content {
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 본인인증 후 사용자에게 보여줄 웹페이지 주소
|
||||||
|
* D10 상품 사용시 필수
|
||||||
|
* 1000자 이하의 URL 형식
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Schema(title = "본인인증 후 사용자에게 보여줄 웹페이지 주소", example = "http://ipAddress/api/kakaopay/v1/ott")
|
||||||
|
@Size(max = 1000, message = "본인인증후 사용자에게 보여줄 페이지 주소는 필수입니다(max=1000)")
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* HTML 전문
|
||||||
|
* D11 상품 사용시 필수(최대 64KB)
|
||||||
|
*/
|
||||||
|
@Schema(title = "HTML 전문", example = " ")
|
||||||
|
@Size(max = 65536, message = "HTML 전문(max=64KB)")
|
||||||
|
private String html;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------- ValidToken ------------------------------------------------------------------------------------------------
|
||||||
|
@Schema(name = "ValidTokenRequest DTO", description = "카카오톡 전자문서 토큰 유효성 검증 파라메터 DTO")
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class ValidTokenRequest extends CmmEnsRequestDTO {
|
||||||
|
/**
|
||||||
|
* 문서 고유 ID, 34자로 고정
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
|
||||||
|
// FIXME: 테스트후 주석 제거!!!
|
||||||
|
//@Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
|
||||||
|
private String envelopeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카카오톡 전자문서 서버에서 생성한 일회용 토큰 : 필수
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "카카오톡 전자문서 서버에서 생성한 일회용 토큰", example = "CON-cc375944ae3d11ecb91e42193199ee3c")
|
||||||
|
@NotEmpty(message = "카카오톡 전자문서 서버 토큰은 필수입니다")
|
||||||
|
private String token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "ValidTokenResponse DTO", description = "카카오톡 토큰 검증 response DTO")
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public static class ValidTokenResponse extends KkotalkErrorDTO implements IApiResponse {
|
||||||
|
/**
|
||||||
|
* 문서 고유 ID, 34자로 고정
|
||||||
|
*/
|
||||||
|
private String envelopeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서매핑용 식별자 - 최대 40자
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String externalId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 진행상태 : 토큰검증시 필수
|
||||||
|
* 수신,미열람|열람|최초열람만료일시 또는 재열람 만료일시 초과
|
||||||
|
* RECEIVE|READ|EXPIRED
|
||||||
|
* </pre>
|
||||||
|
* @see ApiConstants.KkotalkDocStatus
|
||||||
|
*/
|
||||||
|
private ApiConstants.KkotalkDocStatus status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 송신 일시 - 토큰검증시 필수
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </
|
||||||
|
*/
|
||||||
|
private String sentAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 수신 일시 - 토큰검증시 필수
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String receivedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람 일시
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String readAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람 인증 일시
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String authenticatedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 토큰 검증 일시
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String ottVerifiedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 사용자의 알림톡 수신 가능 여부
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private Boolean isNotificationUnavailable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 사용자의 알림톡 수신 일시
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String userNotifiedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 문서 발송하기 API 요청 시 전달한 페이로드
|
||||||
|
*/
|
||||||
|
private String payload;
|
||||||
|
}
|
||||||
|
//------------------ ValidToken ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------ DocStatus ----------------------------------------------------------------------
|
||||||
|
@Schema(name = "EnvelopeStatusResponse DTO", description = "카카오톡 상태조회 response DTO")
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public static class EnvelopeStatusResponse extends ValidTokenResponse implements IApiResponse {
|
||||||
|
/** /**
|
||||||
|
* <pre>
|
||||||
|
* 문서 열람 만료 일시
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String readExpiredAt;
|
||||||
|
|
||||||
|
/** /**
|
||||||
|
* <pre>
|
||||||
|
* 유통정보의 수신 시각
|
||||||
|
* 공인전자주소 활성화와 문서 수신이 모두 완료된 시각
|
||||||
|
* yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String distributionReceivedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 에러코드
|
||||||
|
*/
|
||||||
|
private String errorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 에러 메세지
|
||||||
|
*/
|
||||||
|
private String errorMessage;
|
||||||
|
}
|
||||||
|
//------------------ DocStatus ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//------------------ SendResponse ----------------------------------------------------------------------
|
||||||
|
@Schema(name = "EnvelopeRes DTO", description = "문서발송 응답 DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
//@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public static class EnvelopeRes {
|
||||||
|
/**
|
||||||
|
* 문서 고유 ID, 34자로 고정
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
|
||||||
|
@Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
|
||||||
|
private String envelopeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서매핑용 식별자 - 최대 40자
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "KkotalkErrorResponse DTO", description = "카카오톡 에러 응답 DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public static class KkotalkErrorDTO {
|
||||||
|
/**
|
||||||
|
* 에러코드
|
||||||
|
*/
|
||||||
|
private String errorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 에러 메세지
|
||||||
|
*/
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 트래킹(Tracking) ID
|
||||||
|
*/
|
||||||
|
private String edocGtid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(name = "SendResponse DTO", description = "문서발송 응답 DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public static class SendResponse extends KkotalkErrorDTO {
|
||||||
|
/**
|
||||||
|
* 문서 고유 ID, 34자로 고정 - 필수
|
||||||
|
*/
|
||||||
|
private String envelopeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 문서매핑용 식별자 - 최대 40자
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private String externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Schema(name = "EnvelopeId DTO", description = "EnvelopeId DTO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public static class EnvelopeId extends CmmEnsRequestDTO{
|
||||||
|
/**
|
||||||
|
* 문서 고유 ID, 34자로 고정
|
||||||
|
*/
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
|
||||||
|
// FIXME: 테스트후 주석 제거!!!
|
||||||
|
//@Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
|
||||||
|
private String envelopeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue