--- src/main/java/itn/com/cmm/util/MsgSendUtils.java
+++ src/main/java/itn/com/cmm/util/MsgSendUtils.java
... | ... | @@ -463,7 +463,7 @@ |
| 463 | 463 |
} |
| 464 | 464 |
} |
| 465 | 465 |
|
| 466 |
- private static Boolean getReplaceYN(String smsTxtTemplate) {// 여러 치환 구문이 포함된 정규식 패턴
|
|
| 466 |
+ public static Boolean getReplaceYN(String smsTxtTemplate) {// 여러 치환 구문이 포함된 정규식 패턴
|
|
| 467 | 467 |
|
| 468 | 468 |
if (smsTxtTemplate == null) {
|
| 469 | 469 |
return false; // null일 경우 false 반환 |
--- src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
... | ... | @@ -1,12 +1,15 @@ |
| 1 | 1 |
package itn.let.kakao.kakaoComm; |
| 2 | 2 |
|
| 3 |
+import java.io.UnsupportedEncodingException; |
|
| 3 | 4 |
import java.text.ParseException; |
| 4 | 5 |
import java.text.SimpleDateFormat; |
| 5 | 6 |
import java.util.ArrayList; |
| 6 | 7 |
import java.util.Calendar; |
| 7 | 8 |
import java.util.Date; |
| 9 |
+import java.util.HashMap; |
|
| 8 | 10 |
import java.util.List; |
| 9 | 11 |
import java.util.Map; |
| 12 |
+import java.util.function.Function; |
|
| 10 | 13 |
import java.util.regex.Matcher; |
| 11 | 14 |
import java.util.regex.Pattern; |
| 12 | 15 |
|
... | ... | @@ -19,6 +22,9 @@ |
| 19 | 22 |
import org.springframework.stereotype.Component; |
| 20 | 23 |
|
| 21 | 24 |
import egovframework.rte.fdl.idgnr.EgovIdGnrService; |
| 25 |
+import itn.com.cmm.MjonFTSendVO; |
|
| 26 |
+import itn.com.cmm.MjonMsgSendVO; |
|
| 27 |
+import itn.com.cmm.util.MsgSendUtils; |
|
| 22 | 28 |
import itn.com.cmm.util.StringUtil; |
| 23 | 29 |
import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave; |
| 24 | 30 |
import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate; |
... | ... | @@ -294,25 +300,23 @@ |
| 294 | 300 |
|
| 295 | 301 |
|
| 296 | 302 |
|
| 297 |
- KakaoReturnVO templateDetail = kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO); |
|
| 298 |
- String templateContent = templateDetail.getTemplateContent(); // 알림톡 템플릿 |
|
| 299 |
- kakaoVO.setTemplateContent(templateContent); |
|
| 300 |
- String templateTitle = templateDetail.getTemplateTitle(); |
|
| 303 |
+ String templateContent = kakaoVO.getTemplateContent(); // 친구톡 내용 |
|
| 304 |
+// kakaoVO.setTemplateContent(templateContent); |
|
| 305 |
+// String templateTitle = templateDetail.getTemplateTitle(); |
|
| 301 | 306 |
|
| 302 | 307 |
|
| 303 | 308 |
// log.info(" + templateDetail :: [{}]", templateDetail);
|
| 304 | 309 |
// templateDetail.getButtonList().forEach(t->log.info(" + ButtonList :: [{}]", t.toString()));
|
| 305 | 310 |
|
| 306 | 311 |
Boolean hasContentReplacement = this.replBooleanStrChecker(templateContent); |
| 307 |
- Boolean hasTitleReplacement = this.replBooleanStrChecker(templateTitle); |
|
| 308 |
- Boolean hasButtonReplacement = this.needsButtonReplacement(templateDetail.getButtonList()); |
|
| 312 |
+// Boolean hasTitleReplacement = this.replBooleanStrChecker(templateTitle); |
|
| 313 |
+// Boolean hasButtonReplacement = this.needsButtonReplacement(templateDetail.getButtonList()); |
|
| 309 | 314 |
|
| 310 | 315 |
/** @jsonStr 필요유무 */ |
| 311 |
- boolean hasTitleOrButtons = StringUtils.isNotEmpty(templateTitle) |
|
| 312 |
- || CollectionUtils.isNotEmpty(templateDetail.getButtonList()); |
|
| 316 |
+ boolean hasTitleOrButtons = CollectionUtils.isNotEmpty(kakaoVO.getButtonVOList()); |
|
| 313 | 317 |
|
| 314 | 318 |
/** @jsonStr 반복유무 */ |
| 315 |
- boolean needsJsonReplacement = hasTitleReplacement || hasButtonReplacement; |
|
| 319 |
+// boolean needsJsonReplacement = hasTitleReplacement || hasButtonReplacement; |
|
| 316 | 320 |
String sharedJsonStr = null; |
| 317 | 321 |
|
| 318 | 322 |
String subMsgTxt = kakaoVO.getSubMsgTxt(); // 실패 대체 문자 |
... | ... | @@ -322,125 +326,105 @@ |
| 322 | 326 |
// 사용자 개인 단가 정보 불러오기 |
| 323 | 327 |
MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(kakaoVO.getUserId()); |
| 324 | 328 |
|
| 325 |
- |
|
| 329 |
+ |
|
| 330 |
+ String smsTxtTemp = templateContent; |
|
| 331 |
+ Boolean replaceYN = MsgSendUtils.getReplaceYN(templateContent); |
|
| 332 |
+ |
|
| 333 |
+ boolean hasPerformedMsgType = false; // 치환 문자가 없는 경우, 스팸 체크가 한 번만 수행되도록 제어 |
|
| 326 | 334 |
|
| 327 | 335 |
|
| 328 | 336 |
/** @MSGID KEY값 */ |
| 329 | 337 |
List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getVarListMap().size()); |
| 330 |
-// for (int i = 0; i < kakaoSendAdvcListVO.size(); i++) {
|
|
| 331 |
-// kakaoSendAdvcListVO.get(i).setMsgId(idList.get(i)); |
|
| 332 |
-// kakaoSendAdvcListVO.get(i).setBizJsonName(idList.get(i)); |
|
| 333 |
-// } |
|
| 338 |
+ |
|
| 339 |
+ |
|
| 340 |
+ Map<String, Function<MjonFTSendVO, String>> placeholders = new HashMap<>(); |
|
| 341 |
+ placeholders.put("[*이름*]", MjonFTSendVO::getName);
|
|
| 342 |
+ placeholders.put("[*1*]", MjonFTSendVO::getRep1);
|
|
| 343 |
+ placeholders.put("[*2*]", MjonFTSendVO::getRep2);
|
|
| 344 |
+ placeholders.put("[*3*]", MjonFTSendVO::getRep3);
|
|
| 345 |
+ placeholders.put("[*4*]", MjonFTSendVO::getRep4);
|
|
| 334 | 346 |
|
| 335 |
- |
|
| 336 |
- |
|
| 347 |
+ |
|
| 348 |
+ |
|
| 349 |
+ String msgTypeResult = null; |
|
| 350 |
+ List<MjonFTSendVO> mjonFTSendVOList = kakaoVO.getMjonFTSendVOList(); |
|
| 351 |
+ |
|
| 337 | 352 |
// 분할 건수 카운터 |
| 338 | 353 |
int counter = 0; |
| 339 |
- /** @Map에 총 갯수가 수신자 갯수와 동일함 */ |
|
| 340 |
- List<Map<String, String>> varList = kakaoVO.getVarListMap(); |
|
| 341 |
- for (int i = 0; i < varList.size(); i++) {
|
|
| 342 |
- // for(Map<String, String> variables : kakaoVO.getVarListMap()) {
|
|
| 343 |
- // 치환 데이터 |
|
| 344 |
- Map<String, String> variables = varList.get(i); |
|
| 345 |
- log.info("");
|
|
| 354 |
+ for (MjonFTSendVO sendVO : mjonFTSendVOList) {
|
|
| 355 |
+ KakaoSendAdvcVO kakaoSendAdvcVO = new KakaoSendAdvcVO(); |
|
| 346 | 356 |
|
| 347 |
- /** @공통 기본값 */ |
|
| 348 |
- KakaoSendAdvcVO sendVO = createSendVO(kakaoVO); |
|
| 349 |
- String msgId = idList.get(i); |
|
| 350 |
- sendVO.setMsgId(msgId); |
|
| 351 |
- |
|
| 352 |
- // step1 |
|
| 353 |
- // Step 1-1: 값 치환 및 수신번호 셋팅 |
|
| 354 |
- // Step 1-2: 수신자 정보 설정 (callToList는 항상 설정). |
|
| 355 |
- if (variables.containsKey("callToList")) {
|
|
| 356 |
- sendVO.setCallTo(variables.get("callToList"));
|
|
| 357 |
- variables.remove("callToList"); // 사용 후 제거.
|
|
| 358 |
- } |
|
| 359 |
- |
|
| 360 |
- /** @Step1-3: 템플릿 치환데이터 설정 */ |
|
| 361 |
- String templateContentTemp = templateContent; |
|
| 362 |
- String templateTitleTemp = templateTitle; |
|
| 363 |
- if (hasContentReplacement) {
|
|
| 364 |
- templateContentTemp = mjonCommon.ATReplaceTemplateVariables(templateContent, variables); |
|
| 365 |
- if(hasTitleReplacement) {
|
|
| 366 |
- templateTitleTemp = mjonCommon.ATReplaceTemplateVariables(templateTitle, variables); |
|
| 357 |
+ kakaoSendAdvcVO.setCallFrom(kakaoVO.getCallFrom()); |
|
| 358 |
+ kakaoSendAdvcVO.setCallTo(sendVO.getPhone()); |
|
| 359 |
+ kakaoSendAdvcVO.setUserId(kakaoVO.getUserId()); |
|
| 360 |
+ |
|
| 361 |
+ String smsTxt = smsTxtTemp; |
|
| 362 |
+ // 치환 문자면 |
|
| 363 |
+ if(replaceYN) {
|
|
| 364 |
+ |
|
| 365 |
+ // 각 치환 구문을 확인하고 치환할 값이 없으면 오류 반환 |
|
| 366 |
+ for (Map.Entry<String, Function<MjonFTSendVO, String>> entry : placeholders.entrySet()) {
|
|
| 367 |
+ String placeholder = entry.getKey(); |
|
| 368 |
+ String value = entry.getValue().apply(sendVO); |
|
| 369 |
+// log.info(" + smsTxtTemp [{}]", smsTxtTemp);
|
|
| 370 |
+// log.info(" + placeholder [{}]", placeholder);
|
|
| 371 |
+// log.info(" + value [{}]", value);
|
|
| 372 |
+// log.info(" + smsTxtTemp.contains(placeholder) [{}]", smsTxtTemp.contains(placeholder));
|
|
| 373 |
+ if (smsTxt.contains(placeholder)) {
|
|
| 374 |
+ if (StringUtils.isEmpty(value)) {
|
|
| 375 |
+ statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "치환 문구중 " + placeholder + " 데이터가 없습니다."); |
|
| 376 |
+ return false; |
|
| 377 |
+ } |
|
| 378 |
+ smsTxt = smsTxt.replace(placeholder, value); |
|
| 379 |
+// log.info(" + smsTxt [{}]", smsTxt);
|
|
| 380 |
+ |
|
| 381 |
+ } |
|
| 367 | 382 |
} |
| 368 | 383 |
} |
| 369 |
- /** @버튼 치환 */ // 버튼 리스트가 있으면 치환 수행, 항상 sendVO에 설정 |
|
| 370 |
- List<KakaoButtonVO> buttonList = templateDetail.getButtonList(); |
|
| 371 |
- if(hasButtonReplacement) {
|
|
| 372 |
- buttonList = replaceButtonLinks(buttonList, variables); |
|
| 384 |
+ |
|
| 385 |
+ String smsSpamChkTxt = smsTxt; |
|
| 386 |
+ if(StringUtils.isNotEmpty(smsTxt)) {
|
|
| 387 |
+ smsSpamChkTxt = smsTxt.replaceAll(String.valueOf((char) 13), ""); |
|
| 373 | 388 |
} |
| 374 |
- sendVO.setButtonList(buttonList); |
|
| 375 |
- |
|
| 376 |
- sendVO.setTemplateTitle(templateTitleTemp); |
|
| 377 |
- sendVO.setTemplateContent(templateContentTemp); |
|
| 389 |
+ |
|
| 378 | 390 |
|
| 379 | 391 |
|
| 380 |
- // Step 1-4: 실패 대체 문자 치환데이터 설정 |
|
| 381 |
- if("Y".equals(kakaoVO.getSubMsgSendYn())) { // 대체문자가 있나?
|
|
| 382 |
- if ("Y".equals(kakaoVO.getSubMsgTxtReplYn())) { // 치환데이터가 있나?
|
|
| 383 |
- subMsgTxt = mjonCommon.ATReplaceTemplateVariables(subMsgTxt, variables); |
|
| 392 |
+ // == 치환 여부에 따라 처리 로직 분기 == |
|
| 393 |
+ // 치환 문자가 아닌 경우 |
|
| 394 |
+ if (!replaceYN) {
|
|
| 395 |
+ if (!hasPerformedMsgType) {
|
|
| 396 |
+ msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 397 |
+ if ("INVALID".equals(msgTypeResult)) {
|
|
| 398 |
+ statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 399 |
+ return null; |
|
| 400 |
+ } |
|
| 401 |
+ hasPerformedMsgType = true; |
|
| 384 | 402 |
} |
| 385 |
- sendVO.setSubMsgTxt(subMsgTxt);// 실패 |
|
| 386 |
- } |
|
| 387 |
- sendVO.setSubMsgSendYn(kakaoVO.getSubMsgSendYn()); |
|
| 388 |
- |
|
| 389 |
- |
|
| 390 |
- /* |
|
| 391 |
- log.info("kakaoSendAdvcVO Details: [callTo={}\n, templateContent=\n{}\n, subMsgTxt=\n{}]\n\n\n\n",
|
|
| 392 |
- kakaoSendAdvcVO.getCallTo(), |
|
| 393 |
- kakaoSendAdvcVO.getTemplateContent(), |
|
| 394 |
- kakaoSendAdvcVO.getSubMsgTxt() |
|
| 395 |
- ); |
|
| 396 |
- */ |
|
| 397 |
- |
|
| 398 |
- // Step1 END |
|
| 399 |
- |
|
| 400 |
- |
|
| 401 |
-// step3 |
|
| 402 |
-// 바이트 수 체크 및 금액설정 |
|
| 403 |
- |
|
| 404 |
- |
|
| 405 |
- Float kakaoAtPrice = mberManageVO.getKakaoAtPrice(); |
|
| 406 |
- // 유효한 단가 계산 |
|
| 407 |
- float shortPrice = getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice()); |
|
| 408 |
- float longPrice = getValidPrice(mberManageVO.getLongPrice(), sysJoinSetVO.getLongPrice()); |
|
| 409 |
- |
|
| 410 |
- |
|
| 411 |
- String shortPStr = Float.toString(shortPrice); |
|
| 412 |
- String mmsPStr = Float.toString(longPrice); |
|
| 413 |
- |
|
| 414 |
- // 공통 가격 설정 |
|
| 415 |
- sendVO.setSmsPrice(shortPStr); |
|
| 416 |
- sendVO.setMmsPrice(mmsPStr); |
|
| 417 |
- |
|
| 418 |
- |
|
| 419 |
- if("Y".equals(kakaoVO.getSubMsgSendYn())) {
|
|
| 420 |
- int smsTxtByte = mjonCommon.getSmsTxtBytes(sendVO.getSubMsgTxt()); |
|
| 421 |
- String sendType = getMsgType(smsTxtByte); |
|
| 422 |
- sendVO.setSubMsgType(sendType); |
|
| 423 |
- |
|
| 424 |
- if ("INVALID".equals(sendType)) {
|
|
| 425 |
- statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "전송 문자 길이를 초과하였습니다.");return kakaoSendAdvcListVO; |
|
| 403 |
+ } |
|
| 404 |
+ else |
|
| 405 |
+ {// 치환 문자인 경우
|
|
| 406 |
+ |
|
| 407 |
+ // 메시지 타입 체크는 매번 수행 |
|
| 408 |
+ msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 409 |
+ if ("INVALID".equals(msgTypeResult)) {
|
|
| 410 |
+ statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 411 |
+ return null; |
|
| 426 | 412 |
} |
| 427 |
- |
|
| 428 |
- boolean isMms = "MMS".equals(sendType); |
|
| 429 |
- sendVO.setEachPrice(isMms ? mmsPStr : shortPStr); |
|
| 430 |
- |
|
| 431 |
- |
|
| 432 |
- } else {
|
|
| 433 |
- kakaoAtPrice = getValidPrice(mberManageVO.getKakaoAtPrice(), sysJoinSetVO.getKakaoAtPrice()); |
|
| 434 |
- sendVO.setEachPrice( Float.toString(kakaoAtPrice) ); |
|
| 435 | 413 |
} |
| 436 | 414 |
|
| 437 | 415 |
|
| 438 | 416 |
|
| 439 |
- // step4 |
|
| 440 |
- // 예약 시간 설정 및 분할 데이터 설정 |
|
| 417 |
+ |
|
| 418 |
+ kakaoSendAdvcVO.setTemplateContent(smsTxt); |
|
| 419 |
+ kakaoSendAdvcVO.setMsgType(msgTypeResult); |
|
| 420 |
+ |
|
| 421 |
+ |
|
| 422 |
+ |
|
| 423 |
+ |
|
| 424 |
+ // 예약 여부 확인 |
|
| 441 | 425 |
if ("Y".equalsIgnoreCase(kakaoVO.getReserveYn())
|
| 442 |
- && "Y".equalsIgnoreCase(kakaoVO.getDivideChk()) |
|
| 443 |
- && counter == Integer.parseInt(kakaoVO.getDivideCnt())) |
|
| 426 |
+ && "Y".equalsIgnoreCase(kakaoVO.getDivideChk()) |
|
| 427 |
+ && counter == Integer.parseInt(kakaoVO.getDivideCnt())) |
|
| 444 | 428 |
{
|
| 445 | 429 |
counter = 0; |
| 446 | 430 |
calendar.add(Calendar.MINUTE, Integer.parseInt(kakaoVO.getDivideTime())); |
... | ... | @@ -448,36 +432,46 @@ |
| 448 | 432 |
counter++; |
| 449 | 433 |
// 즉시 발송인경우 현재 시간 |
| 450 | 434 |
// 예약인 경우 위에 설정한 시간 입력 |
| 451 |
- sendVO.setReqDate(DATE_FORMATTER.format(calendar.getTime())); |
|
| 435 |
+ kakaoSendAdvcVO.setReqDate(DATE_FORMATTER.format(calendar.getTime())); |
|
| 436 |
+ |
|
| 437 |
+ kakaoSendAdvcListVO.add(kakaoSendAdvcVO); |
|
| 452 | 438 |
|
| 453 |
- |
|
| 454 |
- |
|
| 455 |
- /** @step5 전송 메세지 설정 json파일 만들기*/ |
|
| 456 |
- // 타이틀과 버튼이 있고 |
|
| 457 |
- if(hasTitleOrButtons) {
|
|
| 458 |
- // 버튼과 타이틀에 치환데이터가 있으면 json String을 계속 생성 |
|
| 459 |
- if(needsJsonReplacement) {
|
|
| 460 |
- sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail); |
|
| 461 |
- sendVO.setBizJsonName(msgId); |
|
| 462 |
- sendVO.setJsonStr(sharedJsonStr); |
|
| 463 |
- } else if (StringUtils.isEmpty(sharedJsonStr)) {
|
|
| 464 |
- // 치환 데이터가 없고 아직 생성되지 않았으면 한 번만 생성 |
|
| 465 |
- sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail); |
|
| 466 |
- sendVO.setBizJsonName(idList.get(0)); |
|
| 467 |
- sendVO.setJsonStr(sharedJsonStr); |
|
| 468 |
- }else {
|
|
| 469 |
- sendVO.setBizJsonName(idList.get(0)); |
|
| 470 |
- } |
|
| 471 |
- |
|
| 472 |
- } |
|
| 473 |
- log.info(" sendVO :: [{}]", sendVO);
|
|
| 474 |
- kakaoSendAdvcListVO.add(sendVO); |
|
| 475 | 439 |
} |
| 476 | 440 |
|
| 477 | 441 |
|
| 478 | 442 |
return kakaoSendAdvcListVO; |
| 479 | 443 |
} |
| 480 | 444 |
|
| 445 |
+ public static String getMsgTypeWithByteValidation(MjonFTSendVO sendVO, String p_smsTxt) throws UnsupportedEncodingException {
|
|
| 446 |
+ |
|
| 447 |
+ |
|
| 448 |
+ // // 내문자저장함에 저장 후 문자를 발송하는 경우 문자 타입이 숫자가 아닌 문자로 넘어와서 변경 처리함 |
|
| 449 |
+ // if ("P".equals(msgType) || "L".equals(msgType)) {
|
|
| 450 |
+ // msgType = "6"; |
|
| 451 |
+ // } else if ("S".equals(msgType)) {
|
|
| 452 |
+ // msgType = "4"; |
|
| 453 |
+ // } |
|
| 454 |
+ |
|
| 455 |
+ int smsTxtByte = MjonCommon.getSmsTxtBytes(p_smsTxt); |
|
| 456 |
+ String msgType = SHORT_MSG_TYPE; |
|
| 457 |
+ |
|
| 458 |
+ // 1. 2000 Byte 초과는 에러 처리 |
|
| 459 |
+ if (smsTxtByte > 2000) {
|
|
| 460 |
+ return "INVALID"; |
|
| 461 |
+ } |
|
| 462 |
+ |
|
| 463 |
+ // 2. 첨부파일 여부 확인 (첨부파일이 있으면 장문으로 설정) |
|
| 464 |
+ if (StringUtils.isNotEmpty(sendVO.getFilePath1())) {
|
|
| 465 |
+ msgType = LONG_MSG_TYPE; |
|
| 466 |
+ } |
|
| 467 |
+ // 3. 문자 길이에 따라 메시지 타입 설정 (90 Byte 초과는 장문) |
|
| 468 |
+ else if (smsTxtByte > 90) {
|
|
| 469 |
+ msgType = LONG_MSG_TYPE; |
|
| 470 |
+ } |
|
| 471 |
+ return msgType; |
|
| 472 |
+ } |
|
| 473 |
+ |
|
| 474 |
+ |
|
| 481 | 475 |
private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isNotified) throws ParseException {
|
| 482 | 476 |
// 예약 시간 기본값 설정 |
| 483 | 477 |
Date now = new Date(); |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?