feat: 카카오톡 추가 반영 - send, status

main
Jonguk. Lim 2 months ago
parent 379653e497
commit 11eb6238fa

@ -1,21 +1,17 @@
package cokr.xit.ens.core.aop;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import com.fasterxml.jackson.annotation.*;
import com.google.gson.annotations.*;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import cokr.xit.ens.core.exception.code.*;
import io.swagger.v3.oas.annotations.media.*;
import lombok.*;
@Getter
@ToString
@Schema(name = "EnsResponseVO")
@NoArgsConstructor
public class EnsResponseVO<T> implements IApiResponse {
public class EnsResponseVO<T> {
@Schema(required = true, title = "에러 코드", example = " ")
@JsonProperty("errCode")

@ -1,9 +1,9 @@
package cokr.xit.ens.modules.kkotalk;
import java.util.Arrays;
import java.util.*;
import cokr.xit.ens.core.exception.BizRuntimeException;
import lombok.Getter;
import cokr.xit.ens.core.exception.*;
import lombok.*;
/**
* <pre>
@ -29,7 +29,7 @@ public class ApiConstants {
/**
* profile : local
*/
public static final boolean IS_PROFILE_LOCAL = PROFILE.matches("local-.*");
public static final boolean IS_PROFILE_LOCAL = PROFILE.matches("local.*");
/**
* profile :

@ -66,20 +66,22 @@ public class SendDetailKkoTalkStatHist {
private String authenticatedAt;
@Column(name = "token_used_at", nullable = true)
private Long tokenUsedAt;
@Column(name = "ott_verified_at", nullable = true)
private String ottVerifiedAt;
@Column(name = "read_at", nullable = true)
private String readAt;
@Column(name = "read_expired_at", nullable = true)
private String readExpiredAt;
@Column(name = "user_notified_at", nullable = true)
private Long userNotifiedAt;
private String userNotifiedAt;
@Column(name = "distribution_received_at", nullable = true)
private String docDistributionReceivedAt;//???
private String distributionReceivedAt;//???
@Column(name = "payload", nullable = true)

@ -5,7 +5,6 @@ import java.util.*;
import org.apache.ibatis.annotations.*;
import cokr.xit.ens.modules.common.domain.*;
import cokr.xit.ens.modules.kkomydoc.domain.*;
import cokr.xit.ens.modules.kkotalk.model.*;
/**
@ -29,6 +28,8 @@ public interface IKkoTalkMapper {
void updateSndDtlKkoTalk(SendDetailKkoTalkDTO sendDetailKkoTalk);
void updateKakaotalkSendBulksResult(SendDetailKkoTalkDTO sendDetailKkoTalk);
void updateKakaotalkStatusBulksResult(SendDetailKkoTalkDTO sendDetailKkoTalkDTO);
List<SendDetailKkoTalkDTO> findAllBySendMastId(Long sendMastId);
@ -37,5 +38,6 @@ public interface IKkoTalkMapper {
List<SendDetailKkoTalkDTO> findAllBySendMastAndEnvlopeIdIsNotNull(SendMast sendMast);
Optional<SendDetailKkoMydoc> findByExternalId(String externalId);
//Optional<SendDetailKkoMydoc> findByExternalId(String externalId);
}

@ -7,7 +7,6 @@ import org.hibernate.validator.constraints.NotEmpty;
import com.fasterxml.jackson.annotation.*;
import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.modules.kkotalk.*;
import io.swagger.v3.oas.annotations.media.*;
import lombok.*;
@ -190,7 +189,7 @@ public class KkotalkApiDTO {
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public static class ValidTokenRequest extends CmmEnsRequestDTO {
public static class ValidTokenRequest {
/**
* ID, 34
*/
@ -212,7 +211,7 @@ public class KkotalkApiDTO {
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static class ValidTokenResponse extends KkotalkErrorDTO implements IApiResponse {
public static class ValidTokenResponse extends KkotalkErrorDTO {
/**
* ID, 34
*/
@ -231,7 +230,6 @@ public class KkotalkApiDTO {
* ,||
* RECEIVE|READ|EXPIRED
* </pre>
* @see ApiConstants.KkotalkDocStatus
*/
private ApiConstants.KkotalkDocStatus status;
@ -305,7 +303,7 @@ public class KkotalkApiDTO {
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@EqualsAndHashCode(callSuper = true)
public static class EnvelopeStatusResponse extends ValidTokenResponse implements IApiResponse {
public static class EnvelopeStatusResponse extends ValidTokenResponse {
/** /**
* <pre>
*
@ -401,7 +399,7 @@ public class KkotalkApiDTO {
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = false)
public static class EnvelopeId extends CmmEnsRequestDTO{
public static class EnvelopeId {
/**
* ID, 34
*/

@ -36,7 +36,7 @@ public class KkotalkDTO extends KkotalkApiDTO {
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = false)
public static class SendRequest extends CmmEnsRequestDTO {
public static class SendRequest {
/**
* <pre>
* -
@ -60,7 +60,7 @@ public class KkotalkDTO extends KkotalkApiDTO {
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = false)
public static class BulkSendRequest extends CmmEnsRequestDTO {
public static class BulkSendRequest {
/**
* <pre>
* -
@ -92,7 +92,7 @@ public class KkotalkDTO extends KkotalkApiDTO {
@AllArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = false)
public static class BulkStatusRequest extends CmmEnsRequestDTO {
public static class BulkStatusRequest {
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
private List<String> envelopes;

@ -4,10 +4,12 @@ import java.time.*;
import java.util.*;
import java.util.stream.*;
import org.apache.commons.lang.*;
import org.springframework.http.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;
import com.google.gson.*;
import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.core.exception.*;
import cokr.xit.ens.core.exception.code.*;
@ -305,55 +307,41 @@ public class KkoTalkService {
OrgMng orgMng = orgMngService.find(orgCd).getResultInfo();
// FIXME: 카카오톡 토큰검증 API 처리
KkotalkApiDTO.ValidTokenResponse resp = kkoTalkApi.validToken(
ResponseEntity<String> resp = kkoTalkApi.validToken(
orgMng,
KkotalkApiDTO.ValidTokenRequest.builder()
.signguCode(orgMng.getOrgCd())
.ffnlgCode("11")
.envelopeId(envelopId)
.token(token)
.build()
);
if (!StringUtils.isEmpty(resp.getErrorCode())){
responseVO = EnsResponseVO.errRsltBuilder()
.errCode(EnsErrCd.ERR600)
.errMsg(String.format("%s %s", resp.getErrorCode(), resp.getErrorMessage()))
.resultInfo(resp)
.build();
}else {
if (resp.getStatusCode() != HttpStatus.OK)
throw new EnsException(EnsErrCd.ERR620, String.format("토큰검증 실패. 실패사유: %s %s", resp.getStatusCode().toString(), resp.getBody()));
Map<String, Object> mResponse = null;
try {
Gson gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
mResponse = gson.fromJson(resp.getBody(), Map.class);
} catch (Exception e) {
throw new EnsException(EnsErrCd.ERR505, String.format("토큰검증 응답데이터 파싱 실패. %s", resp.getBody()));
}
// FIXME: 카카오톡 적용 확인
String envelopeStatus = (String) mResponse.get("envelopeStatus");
if (!CmmnUtil.isEmpty(envelopeStatus)) {
responseVO = EnsResponseVO.okBuilder()
.resultInfo(resp)
.resultInfo(mResponse)
.build();
} else {
String errorCode = (String) mResponse.get("errorCode");
String errorMessage = (String) mResponse.get("errorMessage");
responseVO = EnsResponseVO.errRsltBuilder()
.errCode(EnsErrCd.ERR600)
.errMsg(String.format("%s %s", errorCode, errorMessage))
.resultInfo(mResponse)
.build();
}
// ResponseEntity<String> resp = kkoMydocApi.token(orgMng.getKkoMdAccessToken(), documentBinderUuid, token);
// if (resp.getStatusCode() != HttpStatus.OK)
// throw new EnsException(EnsErrCd.ERR620, String.format("토큰검증 실패. 실패사유: %s %s", resp.getStatusCode().toString(), resp.getBody()));
// Map<String, Object> mResponse = null;
// try {
// Gson gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
// mResponse = gson.fromJson(resp.getBody(), Map.class);
// } catch (Exception e) {
// throw new EnsException(EnsErrCd.ERR505, String.format("토큰검증 응답데이터 파싱 실패. %s", resp.getBody()));
// }
// String tokenUsedAt = (String) mResponse.get("token_status");
// if ("USED".equals(tokenUsedAt)) {
// responseVO = EnsResponseVO.okBuilder()
// .resultInfo(mResponse)
// .build();
// } else {
// String errorCode = (String) mResponse.get("error_code");
// String errorMessage = (String) mResponse.get("error_message");
// responseVO = EnsResponseVO.errRsltBuilder()
// .errCode(EnsErrCd.ERR600)
// .errMsg(String.format("%s %s", errorCode, errorMessage))
// .resultInfo(mResponse)
// .build();
// }
} catch (EnsException e) {
responseVO = EnsResponseVO.errBuilder()
@ -368,6 +356,7 @@ public class KkoTalkService {
} finally {
if (EnsErrCd.OK.equals(responseVO.getErrCode())) {
Map<String, Object> resultInfo = (Map<String, Object>) responseVO.getResultInfo();
// FIXME: 카카오톡 적용 확인 필요??
sendDetailKkoTalkTokenHistRepository.save(SendDetailKkoTalkTokenHist.builder()
.envelopeId(envelopId)
.envelopeId(externalId)
@ -417,21 +406,28 @@ public class KkoTalkService {
OrgMng orgMng = orgMngService.find(orgCd).getResultInfo();
// FIXME: 카카오툭 토큰 확인 API 호출 처리
KkotalkApiDTO.KkotalkErrorDTO resp = kkoTalkApi.modifyStatus(
ResponseEntity<String> resp = kkoTalkApi.modifyStatus(
orgMng,
KkotalkDTO.EnvelopeId.builder()
.envelopeId(envelopeId)
.signguCode(orgMng.getOrgCd())
.ffnlgCode("11")
.build()
);
if (StringUtils.isEmpty(resp.getErrorCode())){
if (resp.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
responseVO = EnsResponseVO.okBuilder().build();
} else {
Map<String, Object> mResponse = null;
try {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
mResponse = gson.fromJson(resp.getBody(), Map.class);
} catch (Exception e) {
throw new EnsException(EnsErrCd.ERR505, String.format("문서상태변경 응답데이터 파싱 실패. %s", resp.getBody()));
}
String errorCode = (String) mResponse.get("error_code");
String errorMessage = (String) mResponse.get("error_message");
responseVO = EnsResponseVO.errBuilder()
.errCode(EnsErrCd.ERR600)
.errMsg(String.format("%s %s", resp.getErrorCode(), resp.getErrorMessage()))
.errMsg(String.format("%s %s", errorCode, errorMessage))
.build();
}

@ -18,6 +18,7 @@ import org.springframework.web.util.*;
import cokr.xit.ens.core.exception.*;
import cokr.xit.ens.core.exception.code.*;
import cokr.xit.ens.core.utils.*;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.*;
import cokr.xit.ens.modules.kkotalk.model.*;
import lombok.*;
import lombok.extern.slf4j.*;
@ -42,6 +43,14 @@ import lombok.extern.slf4j.*;
@Component
public class KkoTalkApiService {
private static final String PROFILE = System.getProperty("spring.profiles.active");
/**
* profile : local
*/
private static final boolean IS_PROFILE_LOCAL = PROFILE.matches("local.*");
private static final String PRODUCT_CD = IS_PROFILE_LOCAL ? "D10_1T" : "D10_2";
@Value("${contract.kakao.talk.host}")
private String HOST;
@ -61,7 +70,6 @@ public class KkoTalkApiService {
@Value("#{'${contract.kakao.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}";
@ -74,10 +82,7 @@ public class KkoTalkApiService {
* @param reqDTO KkoPayEltrDocDTO.RequestSendReq
* @return KkotalkDTO.SendResponse
*/
public KkotalkDTO.SendResponse requestSend(final KkotalkDTO.SendRequest reqDTO) {
if(Checks.isEmpty(reqDTO.getProductCode())){
throw BizRuntimeException.create("상품 코드는 필수 입니다.");
}
public ResponseEntity<String> requestSend(final OrgMng orgMng, final KkotalkDTO.SendRequest reqDTO) {
List<String> errors = new ArrayList<>();
errors = validate(reqDTO.getEnvelope(), errors);
@ -93,13 +98,15 @@ public class KkoTalkApiService {
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.exchangeKkotalk(
HOST + API_SEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
if(!Objects.requireNonNull(errors).isEmpty()){
return new ResponseEntity<String>("{\""+EnsErrCd.SEND405.getCode() +"\":" + errors.toString() +"}", HttpStatus.BAD_REQUEST);
}
return callApi(
HttpMethod.valueOf(API_SEND[1]),
HOST + API_SEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
JsonUtils.toJson(envelope),
KkotalkDTO.SendResponse.class,
getRlaybsnmInfo(reqDTO));
getHeaders(orgMng));
}
/**
@ -109,17 +116,14 @@ public class KkoTalkApiService {
* @param reqDTO KkopayDocDTO.ValidTokenRequest
* @return KkotalkApiDTO.ValidTokenResponse
*/
public KkotalkApiDTO.ValidTokenResponse validToken(final KkotalkApiDTO.ValidTokenRequest reqDTO) {
public ResponseEntity<String> validToken(final OrgMng orgMng, final KkotalkApiDTO.ValidTokenRequest reqDTO) {
validate(reqDTO, null);
return webClient.exchangeKkotalk(
HOST
+ API_VALID_TOKEN[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId())
.replace("{TOKEN}", reqDTO.getToken()),
return callApi(
HttpMethod.valueOf(API_VALID_TOKEN[1]),
HOST + API_VALID_TOKEN[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId()),
null,
KkotalkApiDTO.ValidTokenResponse.class,
getRlaybsnmInfo(reqDTO));
getHeaders(orgMng));
}
/**
@ -132,12 +136,16 @@ public class KkoTalkApiService {
* </pre>
* @param reqDTO KkopayDocAttrDTO.EnvelopeId
*/
public KkotalkApiDTO.KkotalkErrorDTO modifyStatus(final KkotalkDTO.EnvelopeId reqDTO){
public ResponseEntity<String> modifyStatus(final OrgMng orgMng, final KkotalkDTO.EnvelopeId reqDTO){
validate(reqDTO.getEnvelopeId(), null);
final String url = HOST + API_MODIFY_STATUS[0].replace(ENVELOPE_ID, reqDTO.getEnvelopeId());
return webClient.exchangeKkotalk(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), null, KkotalkApiDTO.KkotalkErrorDTO.class, getRlaybsnmInfo(reqDTO));
return callApi(
HttpMethod.valueOf(API_MODIFY_STATUS[1]),
url,
null,
getHeaders(orgMng));
}
/**
@ -151,80 +159,24 @@ public class KkoTalkApiService {
* @param reqDTO KkotalkDTO.EnvelopeId
* @return KkotalkApiDTO.EnvelopeStatusResponse
*/
public KkotalkApiDTO.EnvelopeStatusResponse findStatus(final KkotalkApiDTO.EnvelopeId reqDTO){
public ResponseEntity<String> findStatus(final OrgMng orgMng, final KkotalkApiDTO.EnvelopeId reqDTO){
validate(reqDTO, null);
String param = "{\"envelopeIds\":" + JsonUtils.toJson(Collections.singletonList(reqDTO.getEnvelopeId())) + "}";
KkotalkDTO.BulkStatusResponse res = webClient.exchangeKkotalk(
HOST + API_BULKSTATUS[0],
return callApi(
HttpMethod.valueOf(API_BULKSTATUS[1]),
HOST + API_BULKSTATUS[0],
param,
KkotalkDTO.BulkStatusResponse.class,
getRlaybsnmInfo(reqDTO));
return res.getEnvelopeStatus().get(0);
}
getHeaders(orgMng));
/**
* <pre>
* : POST
* -. .
* </pre>
* @param reqDTO KkotalkDTO.BulkSendRequest
* @return KkotalkDTO.BulkSendResponse
*/
public KkotalkDTO.BulkSendResponse requestSendBulk(final KkotalkDTO.BulkSendRequest reqDTO) {
if(Checks.isEmpty(reqDTO.getProductCode())){
throw BizRuntimeException.create("상품 코드는 필수 입니다.");
}
List<String> errors = new ArrayList<>();
List<KkotalkApiDTO.Envelope> envelopes = reqDTO.getEnvelopes();
for(int idx = 0; idx < envelopes.size(); idx++) {
final Set<ConstraintViolation<KkotalkApiDTO.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()))
.collect(Collectors.toList())
);
}
}
for(int idx = 0; idx < envelopes.size(); idx++) {
final KkotalkApiDTO.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());
}
String param = "{\"envelopes\":" + JsonUtils.toJson(envelopes) + "}";
return webClient.exchangeKkotalk(
HOST + API_BULKSEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
HttpMethod.valueOf(API_BULKSEND[1]),
param,
KkotalkDTO.BulkSendResponse.class,
getRlaybsnmInfo(reqDTO));
// KkotalkDTO.BulkStatusResponse res = webClient.exchangeKkotalk(
// HOST + API_BULKSTATUS[0],
// HttpMethod.valueOf(API_BULKSTATUS[1]),
// param,
// KkotalkDTO.BulkStatusResponse.class,
// getRlaybsnmInfo(reqDTO));
// return res.getEnvelopeStatus().get(0);
}
/**
@ -235,12 +187,9 @@ public class KkoTalkApiService {
* @param reqDTO KkotalkDTO.BulkSendRequest
* @return KkotalkDTO.BulkSendResponse
*/
public ResponseEntity<String> requestSendBulk2(final KkotalkDTO.BulkSendRequest reqDTO) {
public ResponseEntity<String> requestSendBulk(final OrgMng orgMng, final KkotalkDTO.BulkSendRequest reqDTO) {
ResponseEntity<String> resEntity = null;
if(Checks.isEmpty(reqDTO.getProductCode())){
return new ResponseEntity<String>("{\""+EnsErrCd.SEND405.getCode() +"\":\"상품 코드는 필수 입니다\"}", HttpStatus.BAD_REQUEST);
}
reqDTO.setProductCode(PRODUCT_CD);
List<String> errors = new ArrayList<>();
@ -289,7 +238,7 @@ public class KkoTalkApiService {
HttpMethod.valueOf(API_BULKSEND[1]),
HOST + API_BULKSEND[0].replace("{PRODUCT_CODE}", reqDTO.getProductCode()),
param,
getHeaders());
getHeaders(orgMng));
}
/**
@ -303,7 +252,7 @@ public class KkoTalkApiService {
* @param reqDTO KkotalkDTO.BulkStatusRequest
* @return KkotalkDTO.BulkStatusResponse
*/
public KkotalkDTO.BulkStatusResponse findBulkStatus(final KkotalkDTO.BulkStatusRequest reqDTO) {
public ResponseEntity<String> findBulkStatus(final OrgMng orgMng, final KkotalkDTO.BulkStatusRequest reqDTO) {
List<String> errors = new ArrayList<>();
List<String> envelopes = reqDTO.getEnvelopes();
@ -314,15 +263,15 @@ public class KkoTalkApiService {
}
}
if(!errors.isEmpty()) {
throw BizRuntimeException.create(errors.toString());
return new ResponseEntity<String>("{\""+EnsErrCd.SEND405.getCode() +"\":" + errors.toString() +"}", HttpStatus.BAD_REQUEST);
}
String param = "{\"envelopeIds\":" + JsonUtils.toJson(envelopes) + "}";
return webClient.exchangeKkotalk(
HOST + API_BULKSTATUS[0],
return callApi(
HttpMethod.valueOf(API_BULKSTATUS[1]),
HOST + API_BULKSTATUS[0],
param,
KkotalkDTO.BulkStatusResponse.class,
getRlaybsnmInfo(reqDTO));
getHeaders(orgMng));
}
//-------------------------------------------------------------------------------------------------------------------
@ -336,7 +285,9 @@ public class KkoTalkApiService {
// 추가적인 유효성 검증이 필요 없는 경우
if(errList == null){
if(!errors.isEmpty()) throw BizRuntimeException.create(errors.toString());
if(!errors.isEmpty()){
throw BizRuntimeException.create(errors.toString());
}
return null;
}
errList.addAll(errors);
@ -344,16 +295,6 @@ public class KkoTalkApiService {
return errList;
}
// FIXME: 카카오톡 API 호출 시 API 호출 정보 추가 필요
private CmmEnsRlaybsnmDTO getRlaybsnmInfo(final CmmEnsRequestDTO request){
//return null;//CmmEnsUtils.getRlaybsnmInfo(request.getSignguCode(), request.getFfnlgCode(), SndngSeCode.KAKAO);
return CmmEnsRlaybsnmDTO.builder()
.kakaoDealerRestApiKey("kakaoDealerRestApiKey")
.kakaoPartnerRestApiKey("kakaoPartnerRestApiKey")
.kakaoSettleId("kakaoSettleId")
.build();
}
/**
* <pre> : API
* </pre>
@ -435,13 +376,12 @@ public class KkoTalkApiService {
}
// FIXME: 카카오톡 API 호출 시 API 호출 정보 추가 필요
private HttpHeaders getHeaders(){
private HttpHeaders getHeaders(final OrgMng orgMng){
HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_JSON);
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
headers.set(HttpHeaders.AUTHORIZATION, String.format("KakaoAK %s", "KakaoDealerRestApiKey"));
headers.set("Target-Authorization", "KakaoPartnerRestApiKey");
headers.set("settle-Id", "KakaoSettleId");
headers.set(HttpHeaders.AUTHORIZATION, String.format("KakaoAK %s", orgMng.getKakaoDealerRestApiKey()));
headers.set("Target-Authorization", orgMng.getKakaoPartnerRestApiKey());
headers.set("settle-Id", IS_PROFILE_LOCAL ? orgMng.getKakaoDevSettleId() : orgMng.getKakaoProdSettleId());
return headers;
}

@ -5,6 +5,7 @@ import java.util.stream.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.*;
import org.springframework.http.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;
@ -23,9 +24,9 @@ import cokr.xit.ens.modules.common.domain.*;
import cokr.xit.ens.modules.common.domain.repository.*;
import cokr.xit.ens.modules.common.domain.support.*;
import cokr.xit.ens.modules.common.event.*;
import cokr.xit.ens.modules.kkomydoc.domain.repository.*;
import cokr.xit.ens.modules.kkotalk.code.*;
import cokr.xit.ens.modules.kkotalk.domain.*;
import cokr.xit.ens.modules.kkotalk.domain.repository.*;
import cokr.xit.ens.modules.kkotalk.mapper.*;
import cokr.xit.ens.modules.kkotalk.model.*;
import lombok.*;
@ -41,11 +42,10 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
private final SendMastRepository sendMastRepository;
private final IKkoTalkMapper talkMapper;
private final SendDetailKkoMydocStatHistRepository sendDetailKkoMydocStatHistRepository;
private final SendDetailKkoTalkStatHistRepository sendDetailKkoTalkStatHistRepository;
private final OrgMngService orgMngService;
private final KkoTalkApiService kkoTalkApi;
//private final KkoMydocApiSpec kkoMydocApi;
@Value("${contract.kakao.pay.mydoc.api.bulksend-batch-unit}")
@Value("${contract.kakao.talk.bulksend-batch-unit}")
private int SEND_BATCH_UNIT;
@Override
@ -68,100 +68,61 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
Lists.partition(sendDetails, SEND_BATCH_UNIT).stream()
.forEach(list -> {
List<String> envelopeIds = null;
String sendRespBody = null;
String jsonStr = null;
try {
List<String> envelopeIds = this.makeMessage(list);
KkotalkDTO.BulkStatusResponse resp = kkoTalkApi.findBulkStatus(
envelopeIds = this.makeMessage(list);
ResponseEntity<String> resp = kkoTalkApi.findBulkStatus(
orgMng,
KkotalkDTO.BulkStatusRequest.builder()
.envelopes(envelopeIds)
.signguCode(orgMng.getOrgCd())
.ffnlgCode("11")
.build()
);
resp.getEnvelopeStatus().forEach(t -> {}
);
/*
list.stream().forEach(row ->
this.modifyStatInfoByDocumentBinderUuid(row, resp.getEnvelopeStatus())
);
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) mResponse.getResultInfo()).get("documents");
Map<String, KkoMydocApiRespVO> mApiRespVOByDocumentBinderUuid = documents.stream()
.map(row -> this.toApiRespVOMap(row))
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoMydocApiRespVO) m.get("value"), (k1, k2) -> k1));
list.stream().forEach(row -> this.modifyStatInfoByDocumentBinderUuid(row, mApiRespVOByDocumentBinderUuid));
*/
/*
EnsResponseVO message = this.makeMessage(list);
if (!(EnsErrCd.OK.equals(message.getErrCode()) || null == message.getErrCode()))
throw new EnsException(message.getErrCode(), message.getErrMsg());
jsonStr = String.valueOf(message.getResultInfo());
ResponseEntity<String> resp = kkoMydocApi.bulkStatus(orgMng.getKkoMdAccessToken(), orgMng.getKkoMdContractUuid(), jsonStr);
if (log.isDebugEnabled()) {
StringBuffer sb = new StringBuffer();
sb.append("\n==============================================================================")
.append("\n[ Kakao Mydoc - StatFetch ]")
.append("\n### Request Info...")
.append("\n" + jsonStr)
.append("\n### Response Info...")
.append("\n" + resp.getBody())
.append("\n==============================================================================");
log.debug(sb.toString());
}
sendRespBody = resp.getBody();
if (resp.getStatusCode() != HttpStatus.OK)
throw new EnsException(EnsErrCd.RSLT620, String.format("문서상태조회 중.. %s %s", resp.getStatusCode().toString(), resp.getBody()));
EnsResponseVO mResponse = this.respMsgToMap(resp.getBody());
throw new EnsException(EnsErrCd.SEND620, String.format("카카오톡 상태 조회 중.. %s %s", resp.getStatusCode().toString(), resp.getBody()));
EnsResponseVO<?> mResponse = this.respMsgToMap(sendRespBody);
if (!EnsErrCd.OK.equals(mResponse.getErrCode()))
throw new EnsException(mResponse.getErrCode(), mResponse.getErrMsg());
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) mResponse.getResultInfo()).get("documents");
List<Map<String, Object>> envelopeStatus = (List<Map<String, Object>>) ((Map<String, Object>) mResponse.getResultInfo()).get("envelopeStatus");
Map<String, KkoMydocApiRespVO> mApiRespVOByDocumentBinderUuid = documents.stream()
Map<String, KkoTalkApiRespVO> mApiRespVO = envelopeStatus.stream()
.map(row -> this.toApiRespVOMap(row))
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoMydocApiRespVO) m.get("value"), (k1, k2) -> k1));
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoTalkApiRespVO) m.get("value"), (k1, k2) -> k1));
list.stream().forEach(row -> this.modifyStatInfoByDocumentBinderUuid(row, mApiRespVOByDocumentBinderUuid));
list.stream().forEach(row -> this.modifyStatInfoByEnvelopeId(row, mApiRespVO));
} catch (EnsException e) {
list.stream()
.forEach(row -> row.setError(FieldError.initBuilder()
list.forEach(row -> row.setError(FieldError.initBuilder()
.errorCode(e.getErrCd().getCode())
.errorMessage(e.getMessage())
.build())
);
} catch (Exception e) {
list.stream()
.forEach(row -> row.setError(FieldError.initBuilder()
list.forEach(row -> row.setError(FieldError.initBuilder()
.errorCode(EnsErrCd.RSLT500.getCode())
.errorMessage(e.getMessage())
.build())
);
*/
} finally {
// if (!CmmnUtil.isEmpty(jsonStr))
// sendDetailKkoMydocStatHistRepository.saveAll(this.toSendDetailStatHist(list, sendRespBody));
// FIXME: 카카오톡 추가 - 카카오톡 테이블 업데이트
list.stream()
.forEach(talkMapper::updateKakaotalkStatusBulksResult);
if (!CmmnUtil.isEmpty(envelopeIds))
sendDetailKkoTalkStatHistRepository.saveAll(this.toSendDetailStatHist(list, sendRespBody));
}
});
respVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
} catch (EnsException e) {
@ -245,40 +206,46 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
* -. / Error
*
*/
private void modifyStatInfoByDocumentBinderUuid(SendDetailKkoTalkDTO row, List<KkotalkDTO.BulkStatusResponse> resList) {
/*
List<KkotalkApiDTO.EnvelopeStatusResponse> resList = response.getEnvelopeStatus();
if (CmmnUtil.isEmpty(envelopeStatus..getError_code())) {
private void modifyStatInfoByEnvelopeId(SendDetailKkoTalkDTO row, Map<String, KkoTalkApiRespVO> resMap) {
KkoTalkApiRespVO apiRespVO = resMap.get(row.getEnvelopeId());
if (CmmnUtil.isEmpty(apiRespVO.getErrorCode())) {
Map<String, Object> statusData = (Map<String, Object>) apiRespVO.getData();
String docBoxStatus = statusData.containsKey("doc_box_status") ? (String) statusData.get("doc_box_status") : null;
Long docBoxSentAt = statusData.containsKey("doc_box_sent_at") ? (Long) statusData.get("doc_box_sent_at") : null;
Long docBoxReceivedAt = statusData.containsKey("doc_box_received_at") ? (Long) statusData.get("doc_box_received_at") : null;
Long authenticatedAt = statusData.containsKey("authenticated_at") ? (Long) statusData.get("authenticated_at") : null;
Long tokenUsedAt = statusData.containsKey("token_used_at") ? (Long) statusData.get("token_used_at") : null;
Long docBoxReadAt = statusData.containsKey("doc_box_read_at") ? (Long) statusData.get("doc_box_read_at") : null;
Long userNotifiedAt = statusData.containsKey("user_notified_at") ? (Long) statusData.get("user_notified_at") : null;
row.setKkoDocStat(CmmnUtil.isEmpty(docBoxStatus) ? row.getKkoDocStat() : KkoMydocStatusCd.valueOfEnum(docBoxStatus));
row.setKkoDocSentDt(CmmnUtil.isEmpty(row.getKkoDocSentDt()) ? DateUtil.absTimeSecToDate(docBoxSentAt, "yyyyMMddHHmmss") : row.getKkoDocSentDt());
row.setKkoDocReceivedDt(CmmnUtil.isEmpty(row.getKkoDocReceivedDt()) ? DateUtil.absTimeSecToDate(docBoxReceivedAt, "yyyyMMddHHmmss") : row.getKkoDocReceivedDt());
row.setKkoDocAuthFrstDt(CmmnUtil.isEmpty(row.getKkoDocAuthFrstDt()) ? DateUtil.absTimeSecToDate(authenticatedAt, "yyyyMMddHHmmss") : row.getKkoDocAuthFrstDt());
row.setKkoDocTokenVrfyFrstDt(CmmnUtil.isEmpty(row.getKkoDocTokenVrfyFrstDt()) ? DateUtil.absTimeSecToDate(tokenUsedAt, "yyyyMMddHHmmss") : row.getKkoDocTokenVrfyFrstDt());
row.setKkoDocReadFrstDt(CmmnUtil.isEmpty(row.getKkoDocReadFrstDt()) ? DateUtil.absTimeSecToDate(docBoxReadAt, "yyyyMMddHHmmss") : row.getKkoDocReadFrstDt());
row.setKkoDocUserNotiedDt(CmmnUtil.isEmpty(row.getKkoDocUserNotiedDt()) ? DateUtil.absTimeSecToDate(userNotifiedAt, "yyyyMMddHHmmss") : row.getKkoDocUserNotiedDt());
String status = statusData.containsKey("status") ? (String) statusData.get("status") : null;
String sentAt = statusData.containsKey("sentAt") ? (String) statusData.get("sentAt") : null;
String receivedAt = statusData.containsKey("receivedAt") ? (String) statusData.get("receivedAt") : null;
String readAt = statusData.containsKey("readAt") ? (String) statusData.get("readAt") : null;
String readExpiredAt = statusData.containsKey("readExpiredAt") ? (String) statusData.get("readExpiredAt") : null;
String authenticatedAt = statusData.containsKey("authenticatedAt") ? (String) statusData.get("authenticatedAt") : null;
String ottVerifiedAt = statusData.containsKey("ottVerifiedAt") ? (String) statusData.get("ottVerifiedAt") : null;
String userNotifiedAt = statusData.containsKey("userNotifiedAt") ? (String) statusData.get("userNotifiedAt") : null;
String distributionReceivedAt = statusData.containsKey("distributionReceivedAt") ? (String) statusData.get("distributionReceivedAt") : null;
String payload = statusData.containsKey("payload") ? (String) statusData.get("payload") : null;
row.setStatus(CmmnUtil.isEmpty(status) ? row.getStatus() : KkoTalkStatusCd.valueOfEnum(status));
row.setSentAt(CmmnUtil.isEmpty(row.getSentAt()) ? sentAt : row.getSentAt());
row.setReceivedAt(CmmnUtil.isEmpty(row.getReceivedAt()) ? receivedAt : row.getReceivedAt());
row.setReadAt(CmmnUtil.isEmpty(row.getReadAt()) ? readAt : row.getReadAt());
row.setReadExpiresAt(CmmnUtil.isEmpty(row.getReadExpiresAt()) ? readExpiredAt : row.getReadExpiresAt());
row.setAuthenticatedAt(CmmnUtil.isEmpty(row.getAuthenticatedAt()) ? authenticatedAt : row.getAuthenticatedAt());
row.setOttVerifiedAt(CmmnUtil.isEmpty(row.getOttVerifiedAt()) ? ottVerifiedAt : row.getOttVerifiedAt());
row.setUserNotifiedAt(CmmnUtil.isEmpty(row.getUserNotifiedAt()) ? userNotifiedAt : row.getUserNotifiedAt());
row.setDistributionReceivedAt(CmmnUtil.isEmpty(row.getDistributionReceivedAt()) ? distributionReceivedAt : row.getDistributionReceivedAt());
row.setPayload(CmmnUtil.isEmpty(row.getPayload()) ? payload : row.getPayload());
row.setError(FieldError.initBuilder().build());
} else {
if ("NOT_FOUND".equals(apiRespVO.getError_code()) && "documentBinder를 찾을 수 없습니다.".equals(apiRespVO.getError_message()))
row.setKkoDocStat(KkoMydocStatusCd.INTERNAL_SENT_ERR);
if ("NOT_FOUND".equals(apiRespVO.getErrorCode()) && "envelopeStatus를 찾을 수 없습니다.".equals(apiRespVO.getErrorMessage()))
row.setStatus(KkoTalkStatusCd.INTERNAL_SENT_ERR);
row.setError(FieldError.initBuilder()
.errorCode(EnsErrCd.RSLT630.getCode())
.errorMessage(String.format("%s %s", apiRespVO.getError_code(), apiRespVO.getError_message()))
.errorMessage(String.format("%s %s", apiRespVO.getErrorCode(), apiRespVO.getErrorMessage()))
.build());
}
*/
}
/**
@ -288,7 +255,7 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
* @param respMsg
* @return
*/
private List<SendDetailKkoTalkStatHist> toSendDetailStatHist(List<SendDetailKkoTalk> list, String respMsg) {
private List<SendDetailKkoTalkStatHist> toSendDetailStatHist(List<SendDetailKkoTalkDTO> list, String respMsg) {
// Map<String, KkoMydocApiRespVO> mMydocApiRespVOByExtDocUuid =
@ -297,8 +264,8 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) respVO.getResultInfo()).get("envelopes");
Map<String, KkoTalkApiRespVO> mRespVOByExtDocUuid = documents.stream()
List<Map<String, Object>> envelopeStatus = (List<Map<String, Object>>) ((Map<String, Object>) respVO.getResultInfo()).get("envelopeStatus");
Map<String, KkoTalkApiRespVO> mRespVO = envelopeStatus.stream()
.map(row -> this.toApiRespVOMap(row))
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoTalkApiRespVO) m.get("value"), (k1, k2) -> k1));
@ -306,21 +273,21 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
return list.stream()
.map(row -> {
KkoTalkApiRespVO apiRespVO = mRespVOByExtDocUuid.get(row.getEnvelopeId());
KkoTalkApiRespVO apiRespVO = mRespVO.get(row.getEnvelopeId());
Map<String, Object> statusData = (Map<String, Object>) apiRespVO.getData();
return SendDetailKkoTalkStatHist.builder()
.sendDetailId(row.getSendDetailId())
.envelopeId(row.getEnvelopeId())
.externalId(row.getExternalId())
// .respRawMsg(gson.toJson(statusData))
.status(statusData.containsKey("doc_box_status") ? (String) statusData.get("doc_box_status") : null)
// .sentAt(statusData.containsKey("doc_box_sent_at") ? (Long) statusData.get("doc_box_sent_at") : null)
// .receivedAt(statusData.containsKey("doc_box_received_at") ? (Long) statusData.get("doc_box_received_at") : null)
// .authenticatedAt(statusData.containsKey("authenticated_at") ? (Long) statusData.get("authenticated_at") : null)
// .tokenUsedAt(statusData.containsKey("token_used_at") ? (Long) statusData.get("token_used_at") : null)
// .readAt(statusData.containsKey("doc_box_read_at") ? (Long) statusData.get("doc_box_read_at") : null)
// .userNotifiedAt(statusData.containsKey("user_notified_at") ? (Long) statusData.get("user_notified_at") : null)
// .docDistributionReceivedAt(statusData.containsKey("doc_distribution_received_at") ? (Long) statusData.get("doc_distribution_received_at") : null)
.status(statusData.containsKey("status") ? (String) statusData.get("status") : null)
.sentAt(statusData.containsKey("sentAt") ? (String) statusData.get("sentAt") : null)
.receivedAt(statusData.containsKey("receivedAt") ? (String) statusData.get("receivedAt") : null)
.readAt(statusData.containsKey("readAt") ? (String) statusData.get("readAt") : null)
.readExpiredAt(statusData.containsKey("readExpiredAt") ? (String) statusData.get("readExpiredAt") : null)
.authenticatedAt(statusData.containsKey("authenticatedAt") ? (String) statusData.get("authenticatedAt") : null)
.ottVerifiedAt(statusData.containsKey("ottVerifiedAt") ? (String) statusData.get("ottVerifiedAt") : null)
.userNotifiedAt(statusData.containsKey("userNotifiedAt") ? (String) statusData.get("userNotifiedAt") : null)
.distributionReceivedAt(statusData.containsKey("distributionReceivedAt") ? (String) statusData.get("distributionReceivedAt") : null)
.payload(statusData.containsKey("payload") ? (String) statusData.get("payload") : null)
.error(FieldError.initBuilder()
.errorCode(apiRespVO.getErrorCode())
@ -348,21 +315,21 @@ public class KkoTalkRsltFetcher extends ResultProcTemplate {
}
private EnsResponseVO respMsgToMap(String respMsg) {
private EnsResponseVO<?> respMsgToMap(String respMsg) {
Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
EnsErrCd errCode = EnsErrCd.OK;
String errMsg = EnsErrCd.OK.getCodeNm();
Map<String, Object> mResp = null;
try {
mResp = gson.fromJson(respMsg, Map.class);
if (CmmnUtil.isEmpty(mResp.get("documents")))
throw new EnsException(EnsErrCd.RSLT620, String.format("문서상태조회API 오류. documents 키값이 없습니다. %s", respMsg));
if (CmmnUtil.isEmpty(mResp.get("envelopeStatus")))
throw new EnsException(EnsErrCd.RSLT620, String.format("카카오톡 상태조회API 오류. envelopeStatus 키값이 없습니다. %s", respMsg));
} catch (EnsException e) {
errCode = e.getErrCd();
errMsg = e.getMessage();
} catch (Exception e) {
errCode = EnsErrCd.RSLT511;
errMsg = String.format("문서상태조회API 응답 데이터 JSON 객체 변환 실패. %s", respMsg);
errMsg = String.format("카카오톡 상태조회API 응답 데이터 JSON 객체 변환 실패. %s", respMsg);
}
return EnsErrCd.OK.equals(errCode) ?
EnsResponseVO.okBuilder().resultInfo(mResp).build()

@ -77,38 +77,33 @@ public class KkoTalkSender extends SendProcTemplate {
String sendRespBody = null;
try {
envelopes = this.makeMessage(list);
ResponseEntity<String> resp = kkoTalkApi.requestSendBulk2(
ResponseEntity<String> resp = kkoTalkApi.requestSendBulk(
orgMng,
KkotalkDTO.BulkSendRequest.builder()
// FIXME: 카카오톡 신규 추가 - 테스트를 위해 임시로 넣음
.productCode("D10_2")
.envelopes(envelopes)
.signguCode(orgMng.getOrgCd())
.ffnlgCode("11")
.build()
);
sendRespBody = resp.getBody();
if (resp.getStatusCode() != HttpStatus.OK)
throw new EnsException(EnsErrCd.SEND620, String.format("전송요청 중.. %s %s", resp.getStatusCode().toString(), resp.getBody()));
EnsResponseVO mResponse = this.respMsgToMap(sendRespBody);
EnsResponseVO<?> mResponse = this.respMsgToMap(sendRespBody);
if (!EnsErrCd.OK.equals(mResponse.getErrCode()))
throw new EnsException(mResponse.getErrCode(), mResponse.getErrMsg());
List<Map<String, Object>> documents = (List<Map<String, Object>>)((Map<String, Object>)mResponse.getResultInfo()).get(
List<Map<String, Object>> envelopeIds = (List<Map<String, Object>>)((Map<String, Object>)mResponse.getResultInfo()).get(
"envelopeIds");
Map<String, KkoTalkApiRespVO> mApiResp = documents.stream()
Map<String, KkoTalkApiRespVO> mApiResp = envelopeIds.stream()
.map(this::toApiRespVOMap)
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")),
m -> (KkoTalkApiRespVO)m.get("value"), (k1, k2) -> k1));
list.stream()
.forEach(row -> {
this.modifyTalkSendRsltByExtDocUuid(row, mApiResp);
this.modifyTalkSendRsltByExternalId(row, mApiResp);
});
@ -164,12 +159,6 @@ public class KkoTalkSender extends SendProcTemplate {
else
throw new EnsException(EnsErrCd.SEND500, String.format("전체건수 전송 실패(총 %d 건)", sendDetails.size()));
} catch (BizRuntimeException be){
respVO = EnsResponseVO.errBuilder()
.errCode(EnsErrCd.SEND500)
.errMsg(be.getMessage())
.build();
} catch (EnsException e) {
respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
@ -199,13 +188,7 @@ public class KkoTalkSender extends SendProcTemplate {
.build());
}
}
// if (respVO != null && EnsErrCd.OK.equals(respVO.getErrCode())) {
// applicationEventPublisher.publishEvent(KkoMydocSentEvent.builder().sendMastId(sendMastId).build());
// } else {
applicationEventPublisher.publishEvent(SendMastStatUpdateEvent.builder().sendMastId(sendMastId).build());
// }
}
@ -279,7 +262,7 @@ public class KkoTalkSender extends SendProcTemplate {
* @param row SendDetailKkoTalkDTO
* @param map Map<String, KkoTalkApiRespVO>
*/
private void modifyTalkSendRsltByExtDocUuid(SendDetailKkoTalkDTO row, Map<String, KkoTalkApiRespVO> map) {
private void modifyTalkSendRsltByExternalId(SendDetailKkoTalkDTO row, Map<String, KkoTalkApiRespVO> map) {
KkoTalkApiRespVO apiRespVO = map.get(row.getExternalId());
if (CmmnUtil.isEmpty(apiRespVO.getErrorCode())) {
row.setStatus(KkoTalkStatusCd.SENT);
@ -421,7 +404,7 @@ public class KkoTalkSender extends SendProcTemplate {
try {
mResp = gson.fromJson(respMsg, Map.class);
if (CmmnUtil.isEmpty(mResp.get("envelopeIds")))
throw new EnsException(EnsErrCd.SEND620, String.format("전송요청API 오류. envelopeId 키값이 없습니다. %s", respMsg));
throw new EnsException(EnsErrCd.SEND620, String.format("전송요청API 오류. envelopeIds 키값이 없습니다. %s", respMsg));
} catch (EnsException e) {
errCode = e.getErrCd();
errMsg = e.getMessage();

@ -1,250 +1,250 @@
package cokr.xit.ens.modules.kkotalk.web;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.modules.kkotalk.model.*;
import cokr.xit.ens.modules.kkotalk.service.support.*;
import io.swagger.v3.oas.annotations.*;
import io.swagger.v3.oas.annotations.media.*;
import io.swagger.v3.oas.annotations.tags.*;
import lombok.*;
import lombok.extern.slf4j.*;
/**
* <pre>
* description : controller
* packageName : kr.xit.ens.kakao.talk.web
* fileName : KkotalkEltrcDocController
* author : julim
* date : 2024-08-12
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-08-12 julim
*
* </pre>
*/
@Tag(name = "KkotalkApiController", description = "카카오톡 인증톡 API")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/kko/talk/api")
public class KkotalkApiController {
private final KkoTalkApiService 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 = "{\n" +
" \"productCode\": \"D10_1\",\n" +
" \"envelope\": {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"link\": \"https://nps.or.kr\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"payload\": \"이용기관 페이로드\",\n" +
" \"readExpiresAt\": \"2023-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2023-12-31T13:00:00\",\n" +
" \"useNonPersonalizedNotification\": true,\n" +
" \"phoneNumber\": \"01099999999\",\n" +
" \"name\": \"홍길동\",\n" +
" \"birthday\": \"20000303\",\n" +
" \"externalId\": \"external_id1\"\n" +
" },\n" +
" \"signguCode\": \"51110\",\n" +
" \"ffnlgCode\": \"11\"\n" +
"}"
),
@ExampleObject(
name = "D11",
value = "{\n" +
" \"productCode\": \"D11_1\",\n" +
" \"envelope\": {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"readExpiresAt\": \"2023-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2023-12-31T13:00:00\",\n" +
" \"ci\": \"${CI}\"\n" +
" },\n" +
" \"signguCode\": \"51110\",\n" +
" \"ffnlgCode\": \"11\"\n" +
"}"
)
})
}) @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 KkotalkApiDTO.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 KkotalkApiDTO.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<KkotalkApiDTO.EnvelopeStatusResponse>
*/
@Operation(summary = "문서 상태 조회", description = "문서 상태 조회")
@PostMapping(value = "/findStatus", produces = MediaType.APPLICATION_JSON_VALUE)
public IApiResponse findStatus(
@RequestBody final KkotalkApiDTO.EnvelopeId reqDTO
) {
return ApiResponseDTO.success(service.findStatus(reqDTO));
}
@Operation(summary = "대량 문서발송 요청 -> batch sendBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청 -> batch sendBulks 에서 호출")
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(
name = "D10",
value = "{\n" +
" \"productCode\": \"D10_1\",\n" +
" \"signguCode\": \"51110\",\n" +
" \"ffnlgCode\": \"11\",\n" +
" \"envelopes\": [\n" +
" {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
" \"phoneNumber\": \"01099999999\",\n" +
" \"name\": \"홍길동\",\n" +
" \"birthday\": \"20000303\",\n" +
" \"externalId\": \"external_id1\"\n" +
" },\n" +
" {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
" \"hash\": \"b0c34fdc5e2ecb0335919fdad3b2ada28fa3ab90ec16e9055c3e9e05c431c6e8\",\n" +
" \"ci\": \"vMtqVxJX56lBgbf9heK3QTc+jVndTfK77i/UJKAzPmBG4n9CazCdd/8YytlFZnN4qofIqgxHpSoiG0yYzgEpJg==\",\n" +
" \"externalId\": \"external_id2\"\n" +
" }\n" +
" ]\n" +
"}"
),
@ExampleObject(
name = "D11",
value = "{\n" +
" \"productCode\": \"D11_1\",\n" +
" \"signguCode\": \"51110\",\n" +
" \"ffnlgCode\": \"11\",\n" +
" \"envelopes\": [\n" +
" {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"link\": \"https://nps.or.kr\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"payload\": \"이용기관 페이로드\",\n" +
" \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
" \"phoneNumber\": \"01099999999\",\n" +
" \"name\": \"홍길동\",\n" +
" \"birthday\": \"20000303\",\n" +
" \"externalId\": \"external_id1\"\n" +
" },\n" +
" {\n" +
" \"title\": \"전자문서\",\n" +
" \"content\": {\n" +
" \"link\": \"https://nps.or.kr\"\n" +
" },\n" +
" \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
" \"payload\": \"이용기관 페이로드\",\n" +
" \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
" \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
" \"ci\": \"${CI}\",\n" +
" \"externalId\": \"external_id2\"\n" +
" }\n" +
" ]\n" +
"}"
)
})
})
@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 KkotalkApiDTO.BulkStatusRequest
* @return KkotalkApiDTO.BulkStatusResponse
*/
@Operation(summary = "대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출")
@PostMapping(value = "/envelopes/bulk/status", produces = MediaType.APPLICATION_JSON_VALUE)
public IApiResponse findBulkStatus(
@RequestBody final KkotalkDTO.BulkStatusRequest reqDTO
) {
return ApiResponseDTO.success(service.findBulkStatus(reqDTO));
}
}
// package cokr.xit.ens.modules.kkotalk.web;
//
// import org.springframework.http.*;
// import org.springframework.web.bind.annotation.*;
//
// import cokr.xit.ens.core.aop.*;
// import cokr.xit.ens.modules.kkotalk.model.*;
// import cokr.xit.ens.modules.kkotalk.service.support.*;
// import io.swagger.v3.oas.annotations.*;
// import io.swagger.v3.oas.annotations.media.*;
// import io.swagger.v3.oas.annotations.tags.*;
// import lombok.*;
// import lombok.extern.slf4j.*;
//
// /**
// * <pre>
// * description : 카카오톡 전자 문서 발송 controller
// * packageName : kr.xit.ens.kakao.talk.web
// * fileName : KkotalkEltrcDocController
// * author : julim
// * date : 2024-08-12
// * ======================================================================
// * 변경일 변경자 변경 내용
// * ----------------------------------------------------------------------
// * 2024-08-12 julim 최초 생성
// *
// * </pre>
// */
// @Tag(name = "KkotalkApiController", description = "카카오톡 인증톡 API")
// @Slf4j
// @RequiredArgsConstructor
// @RestController
// @RequestMapping(value = "/kko/talk/api")
// public class KkotalkApiController {
// private final KkoTalkApiService 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 = "{\n" +
// " \"productCode\": \"D10_1\",\n" +
// " \"envelope\": {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"link\": \"https://nps.or.kr\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"payload\": \"이용기관 페이로드\",\n" +
// " \"readExpiresAt\": \"2023-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2023-12-31T13:00:00\",\n" +
// " \"useNonPersonalizedNotification\": true,\n" +
// " \"phoneNumber\": \"01099999999\",\n" +
// " \"name\": \"홍길동\",\n" +
// " \"birthday\": \"20000303\",\n" +
// " \"externalId\": \"external_id1\"\n" +
// " },\n" +
// " \"signguCode\": \"51110\",\n" +
// " \"ffnlgCode\": \"11\"\n" +
// "}"
// ),
// @ExampleObject(
// name = "D11",
// value = "{\n" +
// " \"productCode\": \"D11_1\",\n" +
// " \"envelope\": {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"readExpiresAt\": \"2023-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2023-12-31T13:00:00\",\n" +
// " \"ci\": \"${CI}\"\n" +
// " },\n" +
// " \"signguCode\": \"51110\",\n" +
// " \"ffnlgCode\": \"11\"\n" +
// "}"
// )
// })
// }) @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 KkotalkApiDTO.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 KkotalkApiDTO.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<KkotalkApiDTO.EnvelopeStatusResponse>
// */
// @Operation(summary = "문서 상태 조회", description = "문서 상태 조회")
// @PostMapping(value = "/findStatus", produces = MediaType.APPLICATION_JSON_VALUE)
// public IApiResponse findStatus(
// @RequestBody final KkotalkApiDTO.EnvelopeId reqDTO
// ) {
// return ApiResponseDTO.success(service.findStatus(reqDTO));
// }
//
// @Operation(summary = "대량 문서발송 요청 -> batch sendBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청 -> batch sendBulks 에서 호출")
// @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
// @Content(mediaType = "application/json", examples = {
// @ExampleObject(
// name = "D10",
// value = "{\n" +
// " \"productCode\": \"D10_1\",\n" +
// " \"signguCode\": \"51110\",\n" +
// " \"ffnlgCode\": \"11\",\n" +
// " \"envelopes\": [\n" +
// " {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
// " \"phoneNumber\": \"01099999999\",\n" +
// " \"name\": \"홍길동\",\n" +
// " \"birthday\": \"20000303\",\n" +
// " \"externalId\": \"external_id1\"\n" +
// " },\n" +
// " {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"html\": \"<!DOCTYPEhtml><html><body><h1>MyFirstHeading</h1><p>Myfirstparagraph.</p></body></html>\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
// " \"hash\": \"b0c34fdc5e2ecb0335919fdad3b2ada28fa3ab90ec16e9055c3e9e05c431c6e8\",\n" +
// " \"ci\": \"vMtqVxJX56lBgbf9heK3QTc+jVndTfK77i/UJKAzPmBG4n9CazCdd/8YytlFZnN4qofIqgxHpSoiG0yYzgEpJg==\",\n" +
// " \"externalId\": \"external_id2\"\n" +
// " }\n" +
// " ]\n" +
// "}"
// ),
// @ExampleObject(
// name = "D11",
// value = "{\n" +
// " \"productCode\": \"D11_1\",\n" +
// " \"signguCode\": \"51110\",\n" +
// " \"ffnlgCode\": \"11\",\n" +
// " \"envelopes\": [\n" +
// " {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"link\": \"https://nps.or.kr\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"payload\": \"이용기관 페이로드\",\n" +
// " \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
// " \"phoneNumber\": \"01099999999\",\n" +
// " \"name\": \"홍길동\",\n" +
// " \"birthday\": \"20000303\",\n" +
// " \"externalId\": \"external_id1\"\n" +
// " },\n" +
// " {\n" +
// " \"title\": \"전자문서\",\n" +
// " \"content\": {\n" +
// " \"link\": \"https://nps.or.kr\"\n" +
// " },\n" +
// " \"guide\": \"국민연금 공단에서 보내는 문서입니다.\",\n" +
// " \"payload\": \"이용기관 페이로드\",\n" +
// " \"readExpiresAt\": \"2024-12-31T10:00:00\",\n" +
// " \"reviewExpiresAt\": \"2025-03-31T13:00:00\",\n" +
// " \"ci\": \"${CI}\",\n" +
// " \"externalId\": \"external_id2\"\n" +
// " }\n" +
// " ]\n" +
// "}"
// )
// })
// })
// @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 KkotalkApiDTO.BulkStatusRequest
// * @return KkotalkApiDTO.BulkStatusResponse
// */
// @Operation(summary = "대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출", description = "카카오페이 전자문서 서버로 대량 문서 상태 조회 요청 -> batch statusBulks 에서 호출")
// @PostMapping(value = "/envelopes/bulk/status", produces = MediaType.APPLICATION_JSON_VALUE)
// public IApiResponse findBulkStatus(
// @RequestBody final KkotalkDTO.BulkStatusRequest reqDTO
// ) {
// return ApiResponseDTO.success(service.findBulkStatus(reqDTO));
// }
// }

@ -88,15 +88,25 @@
WHERE send_detail_id = #{sendDetailId}
</update>
<!--
, link = #{link}
, read_expires_at = #{readExpiresAt},
, review_expires_at = #{reviewExpiresAt}
, mk_jid = #{mkJid}
, mk_tmplt_msg_json_data = #{mkTmpltMsgJsonData}
, bill_uid = #{billUid}
, send_mast_id = #{sendMastId}
-->
<update id="updateKakaotalkStatusBulksResult" parameterType="cokr.xit.ens.modules.kkotalk.model.SendDetailKkoTalkDTO">
/** iup-kkotalk-mapper|updateKakaotalkStatusBulksResult-카카오톡 문서 상태조회 결과 반영|limju */
UPDATE ens_snd_dtl_kko_talk
SET status = #{status}
, sent_at = #{sentAt}
, received_at = #{receivedAt}
, read_at = #{readAt}
, read_expires_at = #{readExpiredAt}
, authenticated_at = #{authenticatedAt}
, ott_verified_at = #{ottVerifiedAt}
, user_notified_at = #{userNotifiedAt}
, distribution_received_at = #{distributionReceivedAt}
, payload = #{payload}
, error_code = #{errorCode}
, error_message = #{errorMessage}
, last_updt_dt = sysdate
WHERE send_detail_id = #{sendDetailId}
</update>
<select id="findAllBySendMastId" parameterType="long" resultType="cokr.xit.ens.modules.kkotalk.model.SendDetailKkoTalkDTO">
/** iup-kkotalk-mapper|findAllBySendMastId-카카오톡발송대상 조회|julim */
<include refid="sqlSelectSendDetailKkoTalk"/>

Loading…
Cancel
Save