이지우 - 카카오 환불 수정. 트랜잭션 분리를 위하여 스케줄 Util에서 반복문으로 처리

This commit is contained in:
JIWOO 2025-08-14 16:56:37 +09:00
parent 28f520c8fa
commit dbc1f2335a
6 changed files with 127 additions and 48 deletions

View File

@ -34,4 +34,8 @@ public interface KakaoAlimTalkService {
//카카오(알림톡, 친구톡 통합) 전송 실패 환불리스트 조회
public void selectKakaoSentRefundList() throws Exception;
//카카오(알림톡, 친구톡 통합) 전송 실패 환불리스트 조회
public List<KakaoVO> selectKakaoSentRefundListForSingle() throws Exception;
public void kakaoSingleRefund(KakaoVO kakaoVO) throws Exception;
}

View File

@ -1,7 +1,6 @@
package itn.let.kakao.user.kakaoAt.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
@ -11,8 +10,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
@ -22,12 +19,13 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
import itn.com.cmm.LoginVO;
import itn.com.cmm.MjonMsgSendVO;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.kakao.kakaoComm.BizKakaoPriceVO;
import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
@ -51,7 +49,6 @@ import itn.let.module.base.PriceAndPoint;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.sym.site.service.impl.SiteManagerDAO;
import itn.let.uss.umt.service.EgovUserManageService;
import itn.let.uss.umt.service.UserManageVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@ -946,7 +943,7 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
private void handleRefund(KakaoVO vo, String msg) throws Exception {
// mj_cash 테이블에 환불 내역 추가 회원 금액 업데이트
// eachPrice는 환불될 금액이므로 양수여야 합니다.
priceAndPoint.insertCashAndPoint(
priceAndPoint.insertCashAndPointNoUpdate(
vo.getUserId(),
Float.parseFloat(vo.getEachPrice()), // 환불 금액은 양수
msg,
@ -1126,8 +1123,33 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
return statusResponse;
}
@Override
public List<KakaoVO> selectKakaoSentRefundListForSingle() throws Exception{
return kakaoAlimTalkDAO.selectKakaoSentRefundList();
}
@Override
public void kakaoSingleRefund(KakaoVO kakaoVO) throws Exception {
System.out.println(kakaoVO.getMsgGroupId() +"________결과 : " +kakaoVO.getRsltCode() +" 대체문자 전송 : "+kakaoVO.getSubMsgSendYn());
kakaoVO.setMsgTypeTxt(AT_MSG_TYPE.equals(kakaoVO.getMsgType()) ? "알림톡" : "친구톡");
if(KAKAO_SUCCESS_CODE.equals(kakaoVO.getRsltCode())) {
//1.카카오톡 발송 성공
processKakaoSendCharge(kakaoVO);
}else if(RESEND_YN_YES.equals(kakaoVO.getSubMsgSendYn())) {//카카오톡 발송 실패, 대체문자 발송 신청 O
//2.카카오톡 발송 실패 + 대체문자 신청 O
handleAlternativeMessageScenario(kakaoVO);
}else {
//3.카카오톡 발송 실패 + 대체문자 신청 X : 전액 환불
handleRefund(kakaoVO, "카카오 " + kakaoVO.getMsgTypeTxt() + " 전송 실패로 인한 결제 금액 환불");
}
//모든 유형 환불 완료 처리
mjonMsgDAO.updateRefundY(kakaoVO);
}
// // 보유 금액이 충분한지 확인하는 메서드
// private boolean isCashSufficient(String userId, List<KakaoSendAdvcVO> kakaoSendAdvcListVO) throws Exception {
@ -1151,33 +1173,4 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
// }
}

View File

@ -9,9 +9,11 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
@ -61,7 +63,6 @@ import itn.com.cmm.util.MJUtil;
import itn.com.cmm.util.StringUtil;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
import itn.let.kakao.kakaoComm.KakaoSendUtil;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave;
@ -79,6 +80,9 @@ import itn.let.mjo.msgdata.service.MjonMsgReturnVO;
import itn.let.mjo.msgholiday.service.MsgAlarmSetVO;
import itn.let.mjo.msgholiday.service.MsgHolidayService;
import itn.let.mjo.msgholiday.service.MsgHolidayVO;
import itn.let.mjo.pay.service.MjonPayService;
import itn.let.mjo.pay.service.MjonPayVO;
import itn.let.org.web.OrgChartManageController;
import itn.let.sym.site.service.EgovSiteManagerService;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.uss.umt.service.EgovUserManageService;
@ -102,6 +106,8 @@ import itn.let.uss.umt.service.UserManageVO;
@Controller
public class KakaoAlimTalkSendController {
private final OrgChartManageController orgChartManageController;
@Resource(name = "egovMjonMsgGroupIdGnrService")
private EgovIdGnrService idgenMjonMsgGroupId;
@ -150,6 +156,13 @@ public class KakaoAlimTalkSendController {
@Autowired
private MjonCommon mjonCommon;
@Resource(name = "mjonPayService")
private MjonPayService mjonPayService;
KakaoAlimTalkSendController(OrgChartManageController orgChartManageController) {
this.orgChartManageController = orgChartManageController;
}
@RequestMapping(value= {"/web/mjon/alimtalk/kakaoAlimtalkMsgDataView.do"})
public String KakaoAlimtalkMsgDataView(ModelMap model
, @ModelAttribute("kakaoVO") KakaoVO kakaoVO) throws Exception {
@ -1541,6 +1554,25 @@ public class KakaoAlimTalkSendController {
return "web/kakao/msgdata/at/KakaoAlimtalkMsgDataView_tmp";
}
public void kakaoRefundSingleTransaction() throws Exception{
System.out.println("=============카카오 환불 싱글 트랜잭션 수행 =============");
List<KakaoVO> kakaoRefundList = kakaoAlimTalkService.selectKakaoSentRefundListForSingle();
Set<String> targetIdSet = new HashSet<>();
for(KakaoVO kakaoVO : kakaoRefundList) {
kakaoAlimTalkService.kakaoSingleRefund(kakaoVO);
targetIdSet.add(kakaoVO.getUserId());
}
MjonPayVO mjonPayVO = new MjonPayVO();
for(String userId : targetIdSet) {
mjonPayVO.setUserId(userId);
mjonPayService.updateMemberCash(mjonPayVO); //회원정보 업데이트
}
}
/**
* @Method Name : kakaoMsgSendRefundTestAjax
* @작성일 : 2025. 8. 6.
@ -1555,7 +1587,7 @@ public class KakaoAlimTalkSendController {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsonView");
kakaoAlimTalkService.selectKakaoSentRefundList();
this.kakaoRefundSingleTransaction();
modelAndView.addObject("result", "success");
return modelAndView;

View File

@ -214,5 +214,35 @@ public class PriceAndPoint {
}
/**
* @methodName : insertCashAndPoint
* @author : 이지우
* @date : 2025. 8. 14.
* @description : insertCashAndPoint 에서 updateMemberCash 제외
* @return : void
* @param userId
* @param totPrice
* @param memo
* @param msgGroupId
* @param userData
* @throws Exception
*
*/
public void insertCashAndPointNoUpdate(
String userId
, float totPrice
, String memo
, String msgGroupId
, String userData
) throws Exception {
MjonPayVO mjonPayVO = buildPayVO(userId, totPrice, memo, msgGroupId);
// 환불로 인해 userData가 추후 사용될 경우 여기에 처리
if (StringUtils.isNotEmpty(userData)) { mjonPayVO.setOrderId(userData); }
mjonPayDAO.insertCash(mjonPayVO); //캐시
}
}

View File

@ -1,12 +1,16 @@
package itn.let.schdlr.service;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
@ -24,12 +28,15 @@ import itn.let.fax.admin.service.FaxAdmService;
import itn.let.fax.admin.service.FaxStatVO;
import itn.let.kakao.admin.kakaoAt.service.MjonKakaoAtStatVO;
import itn.let.kakao.admin.statistics.service.KakaoStatisticsService;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService;
import itn.let.lett.service.LetterService;
import itn.let.mail.service.MailTemplateService;
import itn.let.mjo.msg.service.MjonMsgService;
import itn.let.mjo.msg.service.MjonMsgStatVO;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msgdata.service.impl.MjonMsgDataDAO;
import itn.let.mjo.pay.service.MjonPayVO;
import itn.let.mjo.pay.service.impl.MjonPayDAO;
import itn.let.sts.com.StatsVO;
import itn.let.sts.cst.service.EgovConectStatsService;
import itn.let.uss.umt.service.EgovUserManageService;
@ -82,6 +89,12 @@ public class SchedulerUtil {
@Resource(name="MjonMsgDataDAO")
private MjonMsgDataDAO mjonMsgDataDAO;
@Resource(name="KakaoAlimTalkService")
private KakaoAlimTalkService kakaoAlimTalkService;
@Autowired
private MjonPayDAO mjonPayDAO;
/** 설정값 가져오기 */
@Value("#{globalSettings['Globals.Env']}")
private String GlobalsEnv;
@ -466,20 +479,26 @@ public class SchedulerUtil {
return new JdbcTemplateLockProvider(dataSource);
}
/**
@Scheduled(cron = "0 0/3 * * * ?") // 3분마다 실행
@SchedulerLock(name = "runKakaoOneTime", lockAtMostForString = ONE_MIN, lockAtLeastForString = ONE_MIN)
public void runKakaoOneTime() throws Exception {
// do something...
try {
System.out.println("=============SchedulerUtil=====runKakaoOneTime =============>");
schdlrManageService.kakaoFailPayBack();
}catch(Exception ex) {
ex.printStackTrace();
List<KakaoVO> kakaoRefundList = kakaoAlimTalkService.selectKakaoSentRefundListForSingle();
Set<String> targetIdSet = new HashSet<>();
for(KakaoVO kakaoVO : kakaoRefundList) {
kakaoAlimTalkService.kakaoSingleRefund(kakaoVO);
targetIdSet.add(kakaoVO.getUserId());
}
MjonPayVO mjonPayVO = new MjonPayVO();
for(String userId : targetIdSet) {
mjonPayVO.setUserId(userId);
mjonPayDAO.updateMemberCash(mjonPayVO); //회원정보 업데이트
}
}
*/
//환불 실행
private void PayBack(String p_type) throws Exception {

View File

@ -235,6 +235,7 @@
AND MMD.REFUND_YN = 'N'
AND MMD.RESERVE_C_YN = 'N'
AND MMD.MSG_TYPE IN(8, 9)
ORDER BY MMD.USER_ID ASC
</select>
<select id="kakaoAlimTalkDAO.selectKakaoAtSentRefundList" resultClass="kakaoVO">