api 카카오톡 발송 진행

This commit is contained in:
hehihoho3@gmail.com 2025-09-12 14:36:32 +09:00
parent b6e48e0488
commit ea928ed954
16 changed files with 428 additions and 372 deletions

View File

@ -15,5 +15,6 @@ public class BizTemplateRequest extends CmnVO {
private String apiKey;
private String senderKey;
private String templateCode;
private String test_yn;
}

View File

@ -12,9 +12,11 @@ import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.InqryMapper;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.service.InqryService;
import com.itn.mjonApi.util.TestDataUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Response;
import org.jetbrains.annotations.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@ -58,21 +60,36 @@ public class InqryServiceImpl implements InqryService {
}
@Override
public List<MjKakaoProfileInfoVO> getChnlId(String mberId) {
public RestResponse getChnlId(BizTemplateRequest bizTemplateRequest) {
String mberId = bizTemplateRequest.getMberId();
String testYn = bizTemplateRequest.getTest_yn();
// 테스트 모드 확인
if(StringUtils.isNotEmpty(bizTemplateRequest.getTest_yn())) {
return TestDataUtil.getChnlIdTestData(testYn);
}
List<MjKakaoProfileInfoVO> voList = inqryMapper.getChnlIds(mberId);
return voList;
return new RestResponse(voList);
}
@Override
public RestResponse getTemplates(BizTemplateRequest bizTemplateRequest) throws JsonProcessingException {
// 테스트 모드 확인
if(StringUtils.isNotEmpty(bizTemplateRequest.getTest_yn())) {
return TestDataUtil.getTemplateListTestData(bizTemplateRequest.getTest_yn());
}
// SenderKey 검증
RestResponse STAT_2010 = isSenderKeyChk(bizTemplateRequest);
if (STAT_2010 != null) return STAT_2010;
// 1. 템플릿 목록 조회 요청 DTO 생성 (BIZ ID, API Key, senderKey 포함)
BizTemplateRequest requestDto= BizTemplateRequest.builder()
.bizId(BIZ_ID)
@ -99,6 +116,7 @@ public class InqryServiceImpl implements InqryService {
// 5. 템플릿 객체에 대해 가공 처리
templateList.forEach(t -> {
// log.info(" + t.toString() :: [{}]",t.toString());
// 서비스 상태 코드 한글 라벨로 변환 ( : REG REG(등록완료) )
String originalCode = t.getServiceStatus();
String convertedLabel = ServiceStatusEnum.getLabelByCode(originalCode);
@ -116,6 +134,10 @@ public class InqryServiceImpl implements InqryService {
@Override
public RestResponse getTemplateDetail(BizTemplateRequest bizTemplateRequest) throws JsonProcessingException {
// 테스트 모드 확인
if(StringUtils.isNotEmpty(bizTemplateRequest.getTest_yn())) {
return TestDataUtil.getTemplateDetailTestData(bizTemplateRequest.getTest_yn());
}
// SenderKey 검증
RestResponse STAT_2010 = isSenderKeyChk(bizTemplateRequest);
@ -137,8 +159,9 @@ public class InqryServiceImpl implements InqryService {
log.info(" + response :: [{}]", response.toString());
// 6. 최종 응답 반환 (가공된 템플릿 리스트 포함)
return new RestResponse(response);
return new RestResponse(response.getData());
}
@Override
@ -150,7 +173,7 @@ public class InqryServiceImpl implements InqryService {
}
private @Nullable RestResponse isSenderKeyChk(BizTemplateRequest bizTemplateRequest) {
List<MjKakaoProfileInfoVO> chnlIdList = this.getChnlId(bizTemplateRequest.getMberId());
List<MjKakaoProfileInfoVO> chnlIdList = (List<MjKakaoProfileInfoVO>) this.getChnlId(bizTemplateRequest).getData();
log.info("bizTemplateRequest.getSenderKey() :: [{}]", bizTemplateRequest.getSenderKey());
log.info("chnlIdList :: [{}]", chnlIdList.toString());

View File

@ -3,12 +3,9 @@ package com.itn.mjonApi.mjon.api.kakao.at.inqry.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.itn.mjonApi.cmn.domain.biz.template.BizTemplateRequest;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import java.util.List;
public interface InqryService {
List<MjKakaoProfileInfoVO> getChnlId(String mberId);
RestResponse getChnlId(BizTemplateRequest bizTemplateRequest);
RestResponse getTemplates(BizTemplateRequest bizTemplateRequest) throws JsonProcessingException;

View File

@ -3,14 +3,13 @@ package com.itn.mjonApi.mjon.api.kakao.at.inqry.web;
import com.itn.mjonApi.cmn.domain.biz.template.BizTemplateRequest;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.service.InqryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
@ -40,11 +39,13 @@ public class InqryRestContoller {
* @author hylee
*/
@PostMapping("/api/kakao/inqry/chnlId")
public ResponseEntity<RestResponse> getChnlId(MjKakaoProfileInfoVO mjKakaoProfileInfoVO) throws Exception {
public ResponseEntity<RestResponse> getChnlId(BizTemplateRequest bizTemplateRequest) throws Exception {
List<MjKakaoProfileInfoVO> resultList = inqryService.getChnlId(mjKakaoProfileInfoVO.getMberId());
// List<MjKakaoProfileInfoVO> resultList = inqryService.getChnlId(bizTemplateRequest.getMberId(), bizTemplateRequest.getTest_yn());
// List<MjKakaoProfileInfoVO> resultList = inqryService.getChnlId(bizTemplateRequest.getMberId(), bizTemplateRequest.getTest_yn());
return ResponseEntity.ok().body(new RestResponse(resultList));
return ResponseEntity.ok().body(inqryService.getChnlId(bizTemplateRequest));
// return ResponseEntity.ok().body(new RestResponse(resultList));
}
@ -75,7 +76,7 @@ public class InqryRestContoller {
@PostMapping("/api/kakao/inqry/templates/detail")
public ResponseEntity<RestResponse> getTemplateDetail(BizTemplateRequest bizTemplateRequest) throws Exception {
log.info("bizTemplateRequest :: [{}]", bizTemplateRequest.toString());
// log.info("bizTemplateRequest :: [{}]", bizTemplateRequest.toString());
return ResponseEntity.ok().body(inqryService.getTemplateDetail(bizTemplateRequest));
}

View File

@ -1,9 +1,7 @@
package com.itn.mjonApi.mjon.api.kakao.at.send.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itn.mjonApi.cmn.domain.biz.template.BizTemplateRequest;
import com.itn.mjonApi.cmn.domain.biz.template.detail.TemplateDetailResponse;
import com.itn.mjonApi.cmn.domain.biz.template.detail.TemplateDetail;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.service.InqryService;
@ -54,6 +52,7 @@ public class AtParameterProcessingService {
msgAtRequestVO.setVarListMap(new ArrayList<>());
log.info(" msgAtRequestVO :: [{}]", msgAtRequestVO.toString());
// 채널ID 확인
String STAT_2010 = this.validateSenderKey(msgAtRequestVO.getMberId(), msgAtRequestVO.getSenderKey());
if (STAT_2010 != null) return STAT_2010;
@ -95,31 +94,22 @@ public class AtParameterProcessingService {
.build();
RestResponse response = inqryService.getTemplateDetail(request);
JsonNode node = new ObjectMapper().valueToTree(response.getData());
// 전체 출력
if (response.getData() == null) {
return "STAT_2030"; // 템플릿 상세 정보를 가져올 없음
}
TemplateDetail detail = (TemplateDetail) response.getData();
// 로그 출력
log.info("JsonNode :: {}", node.toPrettyString()); // 보기 좋게 출력
if (node.path("data").has("templateTitle") && !node.path("data").get("templateTitle").isNull()) {
// log.info("templateTitle 있음 :: {}", node.path("data").get("templateTitle").asText());
msgAtRequestVO.setHasTemplateTitle(true);
} else {
// log.info("templateTitle 없음 또는 null");
}
if (node.has("resultCode")) {
return "STAT_"+node.get("resultCode").asText();
}
TemplateDetailResponse detail = (TemplateDetailResponse)
response.getData();
// 템플릿 상세 정보 활용
log.info("template detail :: [{}]", detail);
return "200".equals(detail.getCode()) ? null : "STAT_2030";
// templateTitle 존재 여부 확인
if (StringUtils.isNotEmpty(detail.getTemplateTitle())) {
msgAtRequestVO.setHasTemplateTitle(true);
}
return detail != null ? null : "STAT_2030";
} catch (Exception e) {
e.printStackTrace();
@ -131,7 +121,9 @@ public class AtParameterProcessingService {
if (StringUtils.isEmpty(senderKey)) {
return "STAT_2010";
}
List<MjKakaoProfileInfoVO> resultList = inqryService.getChnlId(mberId);
List<MjKakaoProfileInfoVO> resultList = (List<MjKakaoProfileInfoVO>) inqryService.getChnlId(BizTemplateRequest.builder().mberId(mberId).build()).getData();
boolean ok = resultList.stream().anyMatch(p -> senderKey.equals(p.getSenderKey()));
return ok ? null : "STAT_2010";
}

View File

@ -11,6 +11,7 @@ import com.itn.mjonApi.mjon.api.msg.inqry.mapper.PriceMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.SendMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.domain.MjonResponseVO;
import com.itn.mjonApi.mjon.api.msg.send.mapper.domain.SendSucRestResponse;
import com.itn.mjonApi.util.TestDataUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Response;
import org.apache.commons.lang3.StringUtils;
@ -55,9 +56,10 @@ public class SendAtServiceImpl implements SendAtService {
public RestResponse sendAtData(MsgAtRequestVO msgAtRequestVO, HttpServletRequest request) throws JsonProcessingException {
if(StringUtils.isNotEmpty(msgAtRequestVO.getTest_yn())){
// YF => 실패 테스트 데이터
// return this._getTestMsgReturnData(msgRequestVO.getTest_yn());
// YF => 실패 테스트 데이터, YS => 성공 테스트 데이터 (알림톡 전용)
return TestDataUtil.getTestAtSendReturnData(msgAtRequestVO.getTest_yn());
}
@ -67,6 +69,7 @@ public class SendAtServiceImpl implements SendAtService {
return new RestResponse(new FailRestResponse(falseCode,""));
}
MjonResponseVO munjaSendResponse = apiService.postForEntity(
"/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do"
, msgAtRequestVO

View File

@ -2,6 +2,7 @@ package com.itn.mjonApi.mjon.api.kakao.ft.send.service;
import com.itn.mjonApi.cmn.apiServer.ApiService;
import com.itn.mjonApi.cmn.domain.StatusResponse;
import com.itn.mjonApi.cmn.domain.biz.template.BizTemplateRequest;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.service.InqryService;
import com.itn.mjonApi.mjon.api.kakao.ft.send.mapper.domain.MsgFtRequestVO;
@ -93,7 +94,8 @@ public class FtParameterProcessingService {
if (StringUtils.isEmpty(senderKey)) {
return "STAT_2010";
}
List<MjKakaoProfileInfoVO> resultList = inqryService.getChnlId(mberId);
List<MjKakaoProfileInfoVO> resultList = (List<MjKakaoProfileInfoVO>) inqryService.getChnlId(BizTemplateRequest.builder().mberId(mberId).build()).getData();
boolean ok = resultList.stream().anyMatch(p -> senderKey.equals(p.getSenderKey()));
return ok ? null : "STAT_2010";
}

View File

@ -9,6 +9,7 @@ import com.itn.mjonApi.mjon.api.kakao.ft.send.service.SendFtService;
import com.itn.mjonApi.mjon.api.msg.inqry.mapper.PriceMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.SendMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.domain.MjonResponseVO;
import com.itn.mjonApi.util.TestDataUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Response;
import org.apache.commons.lang3.StringUtils;
@ -57,8 +58,8 @@ public class SendFtServiceImpl implements SendFtService {
public RestResponse sendFtData(MsgFtRequestVO msgFtRequestVO, HttpServletRequest request) throws IOException, NoSuchAlgorithmException {
if(StringUtils.isNotEmpty(msgFtRequestVO.getTest_yn())){
// YF => 실패 테스트 데이터
// return this._getTestMsgReturnData(msgRequestVO.getTest_yn());
// YF => 실패 테스트 데이터, YS => 성공 테스트 데이터 (친구톡 전용)
return TestDataUtil.getTestFtSendReturnData(msgFtRequestVO.getTest_yn());
}
// 데이터

View File

@ -1,6 +1,7 @@
package com.itn.mjonApi.mjon.api.kakao.utils;
import com.itn.mjonApi.mjon.api.kakao.ft.send.mapper.domain.MsgFtRequestVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
@ -18,6 +19,7 @@ import java.util.function.Consumer;
* - 서브(MMS): jpg/jpeg/png/gif, 10MB만 검증(권장 640×960은 안내 수준)
* - 실패 코드 문자열 반환(성공 null)
*/
@Slf4j
public class FtFileMetaUtil {
// ===== 실패코드 상수 정의 =====
@ -162,8 +164,25 @@ public class FtFileMetaUtil {
// 용량/콘텐츠타입 1차 검증
if (f.getSize() > 5L * 1024 * 1024) return FT_E_SIZE_GT_5MB;
String ct = f.getContentType();
if (ct == null || !(ct.equalsIgnoreCase("image/jpeg") || ct.equalsIgnoreCase("image/png"))) {
log.info(" + ct :: [{}]", ct);
// MIME 타입이 application/octet-stream이면 파일명으로 추정
if ("application/octet-stream".equalsIgnoreCase(ct)) {
String filename = f.getOriginalFilename();
if (filename != null) {
String ext = filename.toLowerCase();
if (ext.endsWith(".jpg") || ext.endsWith(".jpeg")) {
ct = "image/jpeg";
} else if (ext.endsWith(".png")) {
ct = "image/png";
}
}
}
if (ct == null || !(ct.equalsIgnoreCase("image/jpeg")
|| ct.equalsIgnoreCase("image/png"))) {
return FT_E_CONTENT_TYPE;
}

View File

@ -67,13 +67,31 @@ public class SendSucRestResponse {
private static List<String> getMsgType(String msgType) {
List<String> result = new ArrayList<>();
// msgType이 null이거나 문자열인 경우 리스트 반환
if (msgType == null || msgType.trim().isEmpty()) {
return result;
}
if(msgType.indexOf(",") > 0)
{
result = Arrays.stream(msgType.split(","))
.map(s -> StatMsg.valueOf("msgType"+s).getMsg())
.filter(s -> s != null && !s.trim().isEmpty()) // 문자열 필터링
.map(s -> {
try {
return StatMsg.valueOf("msgType" + s.trim()).getMsg();
} catch (IllegalArgumentException e) {
log.warn("Unknown msgType: {}, skipping", s.trim());
return null;
}
})
.filter(s -> s != null) // null 제거
.collect(Collectors.toList());
}else{
result.add(StatMsg.valueOf("msgType"+ msgType).getMsg());
try {
result.add(StatMsg.valueOf("msgType" + msgType.trim()).getMsg());
} catch (IllegalArgumentException e) {
log.warn("Unknown msgType: {}, returning empty list", msgType.trim());
}
}
return result;
}
@ -109,8 +127,16 @@ public class SendSucRestResponse {
// 메세지 타입
List<String> msgTypeList = mjonResponseVOList.stream()
.filter(s -> s.getMsgType() != null)
.map(s -> StatMsg.valueOf("msgType"+s.getMsgType()).getMsg())
.filter(s -> s.getMsgType() != null && !s.getMsgType().trim().isEmpty())
.map(s -> {
try {
return StatMsg.valueOf("msgType" + s.getMsgType().trim()).getMsg();
} catch (IllegalArgumentException e) {
log.warn("Unknown msgType in list: {}, skipping", s.getMsgType().trim());
return null;
}
})
.filter(s -> s != null)
.collect(Collectors.toList());

View File

@ -3,23 +3,19 @@ package com.itn.mjonApi.mjon.api.msg.send.service.impl;
import com.itn.mjonApi.cmn.apiServer.ApiService;
import com.itn.mjonApi.cmn.msg.FailRestResponse;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.cmn.msg.StatMsg;
import com.itn.mjonApi.mjon.api.msg.inqry.mapper.PriceMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.SendMapper;
import com.itn.mjonApi.mjon.api.msg.send.mapper.domain.*;
import com.itn.mjonApi.mjon.api.msg.send.service.SendService;
import com.itn.mjonApi.util.MunjaUtil;
import com.itn.mjonApi.util.TestDataUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
@Slf4j
@ -49,7 +45,7 @@ public class SendServiceImpl implements SendService {
if(StringUtils.isNotEmpty(msgRequestVO.getTest_yn())){
// YF => 실패 테스트 데이터
return this._getTestMsgReturnData(msgRequestVO.getTest_yn());
return TestDataUtil._getTestMsgReturnData(msgRequestVO.getTest_yn());
}
// step2.수신자 전화번호 정상 여부 체크(정상 번호에 대해서만 발송 가능)
@ -130,63 +126,6 @@ public class SendServiceImpl implements SendService {
private RestResponse _getTestMsgReturnData(String testYn)
{
// YF => 실패 테스트 데이터
if("YF".equals(testYn))
{
// 실패 코드 랜덤으로 리턴
return new RestResponse(new FailRestResponse(StatMsg.randomErrorStatCode(),"YF"));
}else{
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgGroupId("MSGGID_0000000000000") // 전송 메세지 그룹 ID
.successCnt("5") // 성공 건수
.blockCnt("2") // 수신거부 건수
.msgType("LMS")
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
private RestResponse _getTestMsgsReturnData(String testYn)
{
// YF => 실패 테스트 데이터
if("YF".equals(testYn))
{
return new RestResponse(new FailRestResponse(StatMsg.randomErrorStatCode(),"YF"));
}else{ // YS => 성공 테스트 데이터
List<String> gIdList = new ArrayList<>();
gIdList.add("MSGGID_0000000000000");
gIdList.add("MSGGID_0000000000001");
gIdList.add("MSGGID_0000000000002");
List<String> msgTypeList = new ArrayList<>();
msgTypeList.add("SMS");
msgTypeList.add("LMS");
msgTypeList.add("LMS");
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgGroupIdList(gIdList) // 전송 메세지 그룹 ID
.successCnt("2") // 성공 건수
.blockCnt("1") // 수신거부 건수
.msgTypeList(msgTypeList)
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
@Override
@ -197,7 +136,7 @@ public class SendServiceImpl implements SendService {
if(StringUtils.isNotEmpty(msgsRequestVO.getTest_yn())){
return this._getTestMsgsReturnData(msgsRequestVO.getTest_yn());
return TestDataUtil._getTestMsgsReturnData(msgsRequestVO.getTest_yn());
}
// msgsVO -> msgVO List로 변환
@ -237,7 +176,7 @@ public class SendServiceImpl implements SendService {
if(StringUtils.isNotEmpty(msgsRequestVO.getTest_yn())){
return this._getTestMsgsReturnData(msgsRequestVO.getTest_yn());
return TestDataUtil._getTestMsgsReturnData(msgsRequestVO.getTest_yn());
}
// Map 기반 동적 파라미터 처리

View File

@ -0,0 +1,299 @@
package com.itn.mjonApi.util;
import com.itn.mjonApi.cmn.domain.biz.template.detail.TemplateComments;
import com.itn.mjonApi.cmn.domain.biz.template.detail.TemplateDetail;
import com.itn.mjonApi.cmn.domain.biz.template.list.TemplateInfo;
import com.itn.mjonApi.cmn.msg.FailRestResponse;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.cmn.msg.StatMsg;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.msg.send.mapper.domain.SendSucRestResponse;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 카카오 조회 API 테스트 데이터 유틸리티 클래스
* 기존 SMS/LMS 테스트 패턴을 재사용하여 일관성 유지
*
* @author system
* @date 2025-01-09
*/
public class TestDataUtil {
private static FailRestResponse randomFail(){
return new FailRestResponse(StatMsg.randomErrorStatCode(),"YF");
}
public static RestResponse _getTestMsgReturnData(String testYn)
{
// YF => 실패 테스트 데이터
if("YF".equals(testYn))
{
// 실패 코드 랜덤으로 리턴
return new RestResponse(randomFail());
}else{
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgGroupId("MSGGID_0000000000000") // 전송 메세지 그룹 ID
.successCnt("5") // 성공 건수
.blockCnt("2") // 수신거부 건수
.msgType("LMS")
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
/**
* 다중문자발송
*
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse _getTestMsgsReturnData(String testYn)
{
// YF => 실패 테스트 데이터
if("YF".equals(testYn))
{
return new RestResponse(randomFail());
}else{ // YS => 성공 테스트 데이터
List<String> gIdList = new ArrayList<>();
gIdList.add("MSGGID_0000000000000");
gIdList.add("MSGGID_0000000000001");
gIdList.add("MSGGID_0000000000002");
List<String> msgTypeList = new ArrayList<>();
msgTypeList.add("SMS");
msgTypeList.add("LMS");
msgTypeList.add("LMS");
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgGroupIdList(gIdList) // 전송 메세지 그룹 ID
.successCnt("2") // 성공 건수
.blockCnt("1") // 수신거부 건수
.msgTypeList(msgTypeList)
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
/**
* 알림톡 발송 테스트 데이터 생성
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse getTestAtSendReturnData(String testYn) {
if("YF".equals(testYn)) {
// 실패 테스트 데이터
return new RestResponse(randomFail());
} else {
// 성공 테스트: 알림톡 발송 성공 응답
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgGroupId("MSGGID_AT_" + System.currentTimeMillis()) // 알림톡 전용 그룹 ID
.successCnt("2") // 성공 건수
.blockCnt("0") // 수신거부 건수
.msgType("AT") // 알림톡 타입
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
/**
* 친구톡 발송 테스트 데이터 생성
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse getTestFtSendReturnData(String testYn) {
if("YF".equals(testYn)) {
// 실패 테스트 데이터
return new RestResponse(randomFail());
} else {
// 친구톡용 msgGroupIdList 생성
List<String> msgGroupIdList = new ArrayList<>();
long timestamp = System.currentTimeMillis();
msgGroupIdList.add("MSGGID_" + timestamp);
msgGroupIdList.add("MSGGID_" + timestamp);
// 성공 테스트: 친구톡 발송 성공 응답
return new RestResponse(
SendSucRestResponse.builder()
.resultCode("0")
.msgType("FT") // 친구톡 타입
.msgGroupIdList(msgGroupIdList) // 친구톡은 msgGroupIdList 사용
.successCnt("2") // 성공 건수
.failCnt("0")
.test_yn("YS")
.build()
);
}
}
/**
* 채널 ID 조회 테스트 데이터 생성
*
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse getChnlIdTestData(String testYn) {
if ("YF".equals(testYn)) {
return new RestResponse(randomFail());
} else {
Date now = new Date();
// 원하는 포맷
String nowDate = DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss");
// 성공 테스트: 모킹된 채널 정보 반환
List<MjKakaoProfileInfoVO> mockData = new ArrayList<>();
MjKakaoProfileInfoVO channel1 = new MjKakaoProfileInfoVO();
channel1.setSenderKey("test_sender_key_001");
channel1.setPhoneNumber("02-1234-0000");
channel1.setYellowId("@test_channel_001");
channel1.setFrstRegisterId("test_id_one");
channel1.setFrstRegistPnttm(nowDate);
MjKakaoProfileInfoVO channel2 = new MjKakaoProfileInfoVO();
channel2.setSenderKey("test_sender_key_002");
channel2.setPhoneNumber("02-1234-0001");
channel2.setYellowId("@test_channel_002");
channel2.setFrstRegisterId("test_id_tow");
channel2.setFrstRegistPnttm(nowDate);
mockData.add(channel1);
mockData.add(channel2);
return new RestResponse(mockData);
}
}
/**
* 템플릿 목록 조회 테스트 데이터 생성
*
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse getTemplateListTestData(String testYn) {
if ("YF".equals(testYn)) {
return new RestResponse(randomFail());
} else {
// 성공 테스트: 모킹된 템플릿 목록 반환
List<TemplateInfo> mockData = new ArrayList<>();
TemplateInfo template1 = new TemplateInfo();
template1.setSenderKey("test_sender_key_001");
template1.setTemplateCode("TEST_TEMPLATE_001");
template1.setTemplateName("테스트 템플릿 001");
template1.setCreatedAt("2025-01-01 10:00:00");
template1.setModifiedAt("2025-01-01 10:00:00");
template1.setServiceStatus("REG(등록완료)");
TemplateInfo template2 = new TemplateInfo();
template2.setSenderKey("test_sender_key_001");
template2.setTemplateCode("TEST_TEMPLATE_002");
template2.setTemplateName("테스트 템플릿 002");
template2.setCreatedAt("2025-01-01 11:00:00");
template2.setModifiedAt("2025-01-01 11:00:00");
template2.setServiceStatus("REG(등록완료)");
TemplateInfo template3 = new TemplateInfo();
template3.setSenderKey("test_sender_key_002");
template3.setTemplateCode("TEST_TEMPLATE_003");
template3.setTemplateName("테스트 템플릿 003");
template3.setCreatedAt("2025-01-01 12:00:00");
template3.setModifiedAt("2025-01-01 12:00:00");
template3.setServiceStatus("REJ(반려)");
mockData.add(template1);
mockData.add(template2);
mockData.add(template3);
return new RestResponse(mockData);
}
}
/**
* 템플릿 상세 조회 테스트 데이터 생성
*
* @param testYn 테스트 모드 (YS: 성공, YF: 실패)
* @return RestResponse 래핑된 테스트 데이터
*/
public static RestResponse getTemplateDetailTestData(String testYn) {
if ("YF".equals(testYn)) {
return new RestResponse(randomFail());
} else {
// 성공 테스트: 실제 API 응답 구조를 반영한 템플릿 상세 반환
TemplateDetail templateDetail = TemplateDetail.builder()
.block("false")
.categoryCode("0000000")
.createdAt("2024-08-29 10:10:06")
.dormant("false")
.inspectionStatus("APR")
.modifiedAt("2025-03-27 15:41:57")
.securityFlag("false")
.senderKey("test_sender_key_1215123251234234234")
.senderKeyType("S")
.status("A")
.templateCode("bizp_test_template_0000000000000000")
.templateContent("[테스트]\\n안녕하세요 #{이름}님\\n테스트 물건1 #{물건1}\\n테스트 물건2 #{물건2}\\n테스트 물건3 #{물건3}\\n테스트 물건4 #{물건4}\\n테스트 물건5 #{물건5}\\n테스트 물건6 #{물건6}\\n입니다.")
.templateEmphasizeType("NONE")
.templateExtra("")
.templateHeader("")
.templateImageName("")
.templateImageUrl("")
.templateMessageType("BA")
.templateName("테스트 변수 템플릿")
.templateSubtitle("")
.templateTitle("")
.templateItemHighlight(null)
.templateItem(null)
.buttons(new ArrayList<>())
.comments(createMockComments())
.quickReplies(new ArrayList<>())
.build();
return new RestResponse(templateDetail);
}
}
/**
* 테스트용 Mock Comments 생성 헬퍼 메서드
* 실제 API 응답의 comments 구조를 반영
*/
private static List<TemplateComments> createMockComments() {
List<TemplateComments> comments = new ArrayList<>();
// 실제 API 응답과 유사한 comment 구조
TemplateComments comment = new TemplateComments();
comment.setContent("안녕하세요. 카카오톡 알림톡 검수 담당자입니다.\\r\\n\\r\\n테스트 템플릿으로 확인되어 승인합니다.\\r\\n\\r\\n감사합니다.");
comment.setCreatedAt("2024-08-29 13:44:13");
comment.setStatus("APR");
comment.setAttachment(new ArrayList<>());
comments.add(comment);
return comments;
}
}

View File

@ -2,7 +2,7 @@
# DB INFO
spring.datasource.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://192.168.0.125:3306/mjon_advc?serverTimezone=Asia/Seoul
spring.datasource.url=jdbc:log4jdbc:mysql://192.168.0.125:3308/mjon_advc?serverTimezone=Asia/Seoul
#spring.datasource.url=jdbc:log4jdbc:mysql://139.150.72.157:3306/mjon?serverTimezone=Asia/Seoul
spring.datasource.username=mjonUr

View File

@ -2,7 +2,7 @@
# DB INFO
spring.datasource.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://192.168.0.125:3306/mjon_advc?serverTimezone=Asia/Seoul
spring.datasource.url=jdbc:log4jdbc:mysql://192.168.0.60:3308/mjon_advc?serverTimezone=Asia/Seoul
#spring.datasource.url=jdbc:log4jdbc:mysql://139.150.72.157:3306/mjon?serverTimezone=Asia/Seoul
spring.datasource.username=mjonUr

View File

@ -180,10 +180,12 @@
AND DATE_ADD(NOW(), INTERVAL 60 MINUTE) >= B.REQ_DATE
<if test="startDate != null and startDate != ''">
AND b.regdate >= STR_TO_DATE(CONCAT(#{startDate}, '000000'), '%Y%m%d%H%i%s')
-- AND b.regdate >= STR_TO_DATE(CONCAT(#{startDate}, '000000'), '%Y%m%d%H%i%s')
AND b.regdate <![CDATA[ >= ]]> DATE_SUB(NOW(), INTERVAL 90 DAY)
</if>
<if test="startDate == null or startDate == ''">
AND b.regdate >= STR_TO_DATE(date_format(now(),'%Y%m%d000000'), '%Y%m%d%H%i%s')
-- AND b.regdate >= STR_TO_DATE(date_format(now(),'%Y%m%d000000'), '%Y%m%d%H%i%s')
AND b.regdate <![CDATA[ < ]]> DATE_ADD(CURDATE(), INTERVAL 1 DAY)
</if>
<if test="endDate != null and endDate != ''">

View File

@ -1,249 +0,0 @@
package com.itn.mjonApi.common;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itn.mjonApi.cmn.domain.biz.template.BizTemplateRequest;
import com.itn.mjonApi.mjon.api.kakao.at.inqry.mapper.domain.MjKakaoProfileInfoVO;
import com.itn.mjonApi.mjon.api.kakao.at.send.mapper.domain.MsgAtRequestVO;
import com.itn.mjonApi.mjon.api.kakao.at.send.mapper.domain.VarAtListMapVO;
import java.util.ArrayList;
import java.util.List;
/**
* 테스트 유틸리티 클래스
* 공통적으로 사용되는 테스트 데이터 생성 유틸리티 메서드 제공
*
* @author hylee
* @date 2025-08-18
*/
public class TestUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 테스트용 MsgAtRequestVO 객체 생성
*
* @param mberId 멤버 ID
* @param senderKey 발신 프로필
* @param templateCode 템플릿 코드
* @return 테스트용 MsgAtRequestVO 객체
*/
public static MsgAtRequestVO createMsgAtRequestVO(String mberId, String senderKey, String templateCode) {
MsgAtRequestVO vo = new MsgAtRequestVO();
vo.setMberId(mberId);
vo.setAccessKey("testAccessKey");
vo.setSenderKey(senderKey);
vo.setTemplateCode(templateCode);
vo.setSubMsgSendYn("N");
vo.setTest_yn("Y"); // 테스트 모드
// VarListMap 생성 (동적 파라미터)
List<VarAtListMapVO> varListMap = new ArrayList<>();
varListMap.add(createVarListMapVO("01012345678", "테스트사용자1", "테스트사용자1"));
varListMap.add(createVarListMapVO("01087654321", "테스트사용자2", "테스트사용자2"));
vo.setVarListMap(varListMap);
return vo;
}
/**
* 테스트용 VarListMapVO 객체 생성
*
* @param phone 전화번호
* @param name 이름
* @param replaceValue 치환값
* @return 테스트용 VarListMapVO 객체
*/
public static VarAtListMapVO createVarListMapVO(String phone, String name, String replaceValue) {
VarAtListMapVO vo = new VarAtListMapVO();
vo.setCallToList(phone);
vo.setTemplateTitle(name);
vo.setTemplateContent("테스트 메시지 " + name + "님 안녕하세요");
vo.setSubMsgTxt(replaceValue);
return vo;
}
/**
* 테스트용 MjKakaoProfileInfoVO 객체 생성
*
* @param senderKey 발신 프로필
* @param channelName 채널명
* @param status 상태
* @return 테스트용 MjKakaoProfileInfoVO 객체
*/
public static MjKakaoProfileInfoVO createKakaoProfileVO(String senderKey, String channelName, String status) {
MjKakaoProfileInfoVO vo = new MjKakaoProfileInfoVO();
vo.setSenderKey(senderKey);
vo.setYellowId(channelName); // 카카오톡 채널 @ID
vo.setUserId("testMember"); // 회원 아이디
vo.setCategoryName(status); // 상태 정보를 카테고리명으로 사용
return vo;
}
/**
* 테스트용 BizTemplateRequest 객체 생성
*
* @param senderKey 발신 프로필
* @param templateCode 템플릿 코드
* @return 테스트용 BizTemplateRequest 객체
*/
public static BizTemplateRequest createBizTemplateRequest(String senderKey, String templateCode) {
BizTemplateRequest request = new BizTemplateRequest();
request.setSenderKey(senderKey);
request.setTemplateCode(templateCode);
return request;
}
/**
* 승인된 상태의 카카오 프로필 목록 생성
*
* @param count 생성할 프로필 개수
* @return 승인된 프로필 목록
*/
public static List<MjKakaoProfileInfoVO> createApprovedProfiles(int count) {
List<MjKakaoProfileInfoVO> profiles = new ArrayList<>();
for (int i = 1; i <= count; i++) {
profiles.add(createKakaoProfileVO(
"senderKey" + i,
"테스트채널" + i,
"APPROVED"
));
}
return profiles;
}
/**
* 다양한 상태의 카카오 프로필 목록 생성
*
* @return 다양한 상태의 프로필 목록
*/
public static List<MjKakaoProfileInfoVO> createMixedStatusProfiles() {
List<MjKakaoProfileInfoVO> profiles = new ArrayList<>();
profiles.add(createKakaoProfileVO("approved_key", "승인된채널", "APPROVED"));
profiles.add(createKakaoProfileVO("pending_key", "대기중채널", "PENDING"));
profiles.add(createKakaoProfileVO("rejected_key", "거절된채널", "REJECTED"));
profiles.add(createKakaoProfileVO("blocked_key", "차단된채널", "BLOCKED"));
return profiles;
}
/**
* 대체문자 발송 옵션이 포함된 MsgAtRequestVO 생성
*
* @param mberId 멤버 ID
* @param senderKey 발신 프로필
* @param templateCode 템플릿 코드
* @return 대체문자 옵션 포함 MsgAtRequestVO
*/
public static MsgAtRequestVO createMsgAtRequestVOWithSubMsg(String mberId, String senderKey, String templateCode) {
MsgAtRequestVO vo = createMsgAtRequestVO(mberId, senderKey, templateCode);
vo.setSubMsgSendYn("Y");
vo.setCallFrom("0212345678"); // 발신번호 설정
return vo;
}
/**
* JSON 문자열을 객체로 변환
*
* @param json JSON 문자열
* @param clazz 변환할 클래스
* @param <T> 반환 타입
* @return 변환된 객체
*/
public static <T> T fromJson(String json, Class<T> clazz) {
try {
return objectMapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException("JSON 변환 실패: " + e.getMessage(), e);
}
}
/**
* 객체를 JSON 문자열로 변환
*
* @param object 변환할 객체
* @return JSON 문자열
*/
public static String toJson(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (Exception e) {
throw new RuntimeException("JSON 변환 실패: " + e.getMessage(), e);
}
}
/**
* 테스트용 AccessKey 생성
*
* @return 테스트용 AccessKey
*/
public static String getTestAccessKey() {
return "TEST_ACCESS_KEY_" + System.currentTimeMillis();
}
/**
* 테스트용 전화번호 생성
*
* @param index 인덱스
* @return 테스트용 전화번호
*/
public static String getTestPhoneNumber(int index) {
return String.format("010%08d", index);
}
/**
* 테스트용 이름 생성
*
* @param index 인덱스
* @return 테스트용 이름
*/
public static String getTestName(int index) {
return "테스트사용자" + index;
}
/**
* 동적 파라미터용 VarListMapVO 목록 생성
*
* @param count 생성할 개수
* @return VarListMapVO 목록
*/
public static List<VarAtListMapVO> createVarListMap(int count) {
List<VarAtListMapVO> varListMap = new ArrayList<>();
for (int i = 1; i <= count; i++) {
varListMap.add(createVarListMapVO(
getTestPhoneNumber(i),
getTestName(i),
getTestName(i)
));
}
return varListMap;
}
/**
* 에러 코드 검증용 상수
*/
public static class ErrorCodes {
public static final String INVALID_SENDER_KEY = "STAT_2010";
public static final String EMPTY_SENDER_KEY = "STAT_2011";
public static final String TEMPLATE_NOT_FOUND = "TEMPLATE_NOT_FOUND";
public static final String UNAUTHORIZED = "UNAUTHORIZED";
public static final String INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR";
}
/**
* HTTP 상태 코드 상수
*/
public static class HttpStatus {
public static final int OK = 200;
public static final int BAD_REQUEST = 400;
public static final int UNAUTHORIZED = 401;
public static final int FORBIDDEN = 403;
public static final int NOT_FOUND = 404;
public static final int INTERNAL_SERVER_ERROR = 500;
}
}