diff --git a/pom.xml b/pom.xml index b48c556b..bcecf078 100644 --- a/pom.xml +++ b/pom.xml @@ -564,6 +564,20 @@ system ${basedir}/src/main/webapp/WEB-INF/lib/ozsfw80.jar + + + + net.javacrumbs.shedlock + shedlock-spring + 2.5.0 + + + + + net.javacrumbs.shedlock + shedlock-provider-jdbc-template + 2.5.0 + diff --git a/src/main/java/kcc/kccadr/cmm/service/impl/SMSOracleServiceImpl.java b/src/main/java/kcc/kccadr/cmm/service/impl/SMSOracleServiceImpl.java index 8659e1e4..93fb3520 100644 --- a/src/main/java/kcc/kccadr/cmm/service/impl/SMSOracleServiceImpl.java +++ b/src/main/java/kcc/kccadr/cmm/service/impl/SMSOracleServiceImpl.java @@ -13,7 +13,6 @@ import java.net.URLEncoder; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Random; import javax.annotation.Resource; @@ -32,6 +31,8 @@ import kcc.kccadr.adjreqmgr.service.AdjReqMgrVO; import kcc.kccadr.adjreqmgr.service.impl.AdjReqMgrDAO; import kcc.kccadr.cmm.KccadrConstants; import kcc.kccadr.cmm.service.SMSOracleService; +import kcc.kccadr.message.service.KakaoAtSendDAO; +import kcc.kccadr.message.service.KakaoAtSendVO; import kcc.kccadr.msg.service.impl.MsgMgrDAO; import kcc.let.utl.fcc.service.EgovCryptoUtil; @@ -78,7 +79,10 @@ public class SMSOracleServiceImpl extends EgovAbstractServiceImpl implements SM @Resource(name = "adrSmsLogGnrService") private EgovIdGnrService idgenService; - + + //카카오 알림톡 + @Resource(name = "kakaoAtSendDAO") + private KakaoAtSendDAO kakaoAtSendDAO; // 오라클 연동 테스트 public void selectOracleTest() throws Exception { @@ -146,6 +150,19 @@ public class SMSOracleServiceImpl extends EgovAbstractServiceImpl implements SM msgMgrDAO.insertAdrSmsLog(map); // SMS 이력 등록 단문 > 전자조정 } + //카카오 알림톡 DB 저장 + KakaoAtSendVO apiVO = new KakaoAtSendVO(); + + //msgTy별 템플릿 코드 가져오기 + String msgTy = (String) map.get("msgTy"); + String templateCode = msgMgrDAO.selectMsgMgrTemplateCode(msgTy); + + apiVO.setSendTo(rpplPhone); + apiVO.setTemplatecode(templateCode); + apiVO.setMessage(sendMsg); + + kakaoAtSendDAO.insertKakaoAtSendBatch(apiVO); + result = "succ"; } } catch (Exception e) { @@ -606,6 +623,18 @@ public class SMSOracleServiceImpl extends EgovAbstractServiceImpl implements SM } + //카카오 알림톡 DB 저장 + KakaoAtSendVO apiVO = new KakaoAtSendVO(); + + //msgTy별 템플릿 코드 가져오기 + String msgTy = (String) map.get("msgTy"); + String templateCode = msgMgrDAO.selectMsgMgrTemplateCode(msgTy); + + apiVO.setSendTo(rpplPhone); + apiVO.setTemplatecode(templateCode); + apiVO.setMessage(sendMsg); + + kakaoAtSendDAO.insertKakaoAtSendBatch(apiVO); result = "succ"; diff --git a/src/main/java/kcc/kccadr/message/SchedulerUtil.java b/src/main/java/kcc/kccadr/message/SchedulerUtil.java new file mode 100644 index 00000000..adae3b6b --- /dev/null +++ b/src/main/java/kcc/kccadr/message/SchedulerUtil.java @@ -0,0 +1,89 @@ +package kcc.kccadr.message; + +import java.net.InetAddress; +import java.util.List; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import kcc.kccadr.message.service.KakaoAtSendService; +import kcc.kccadr.message.service.KakaoAtSendVO; +import kcc.kccadr.message.web.KakaoAtSendAPI; +import net.javacrumbs.shedlock.core.LockProvider; +import net.javacrumbs.shedlock.core.SchedulerLock; +import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider; +import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock; + + +@Service("SchedulerUtil") +@EnableScheduling +@EnableSchedulerLock(defaultLockAtMostFor = "PT30S") // Scheduler Lock 사용 가능 설정 (기본 30초동안 Lock) +public class SchedulerUtil { + + @Value("#{globalSettings['Globals.BizPpurio.siteUrl']}") + private String apiUrl; + + @Value("#{globalSettings['Globals.prod.islocal']}") + private String isLocal; + + @Resource (name = "KakaoAtSendService") + private KakaoAtSendService kakaoAtSendService; + + private static final String ONE_MIN = "PT1M"; // 1분동안 LOCK + + //로컬 테스트용 아이피 허용 + private String myLocalIp = "192.168.0.40"; + + //운영 외부망 WAS1 + private String dmzIp1 = "222.231.43.66"; + //운영 외부망 WAS2 + private String dmzIp2 = "222.231.43.69"; + + //10분마다 실행 + @Scheduled(cron = "0 0/10 * * * *") + @SchedulerLock(name = "kakaoAtSendPrcs", lockAtMostForString = ONE_MIN, lockAtLeastForString = ONE_MIN) + public void kakaoAtSendPrcs() throws Exception { + + String ip = null; + + try { + ip = InetAddress.getLocalHost().getHostAddress(); + + if(ip.equals(myLocalIp) || ip.equals(dmzIp1) || ip.equals(dmzIp2) ) { + //접속 서버 별 분기처리 필요 + + List list = kakaoAtSendService.selectKakaoAtList(); + + int listSize = list.size(); + + for(int i=0; i selectKakaoAtList() throws Exception{ + return (List) list("kakaoAtSendDAO.selectKakaoAtList"); + } + + public void insertKakaoAtSendBatch(KakaoAtSendVO kakaoAtSendVO) throws Exception{ + insert("kakaoAtSendDAO.insertKakaoAtSendBatch", kakaoAtSendVO); + } + + public void updateKakaoAtDetail(KakaoAtSendVO kakaoAtSendVO) throws Exception{ + update("kakaoAtSendDAO.updateKakaoAtDetail", kakaoAtSendVO); + } + +} diff --git a/src/main/java/kcc/kccadr/message/service/KakaoAtSendService.java b/src/main/java/kcc/kccadr/message/service/KakaoAtSendService.java new file mode 100644 index 00000000..6774a394 --- /dev/null +++ b/src/main/java/kcc/kccadr/message/service/KakaoAtSendService.java @@ -0,0 +1,13 @@ +package kcc.kccadr.message.service; + +import java.util.List; + +public interface KakaoAtSendService { + + List selectKakaoAtList() throws Exception; + + void updateKakaoAtDetail(KakaoAtSendVO kakaoAtSendVO) throws Exception; + + void insertKakaoAtSendBatch(KakaoAtSendVO kakaoAtSendVO) throws Exception; + +} diff --git a/src/main/java/kcc/kccadr/message/service/KakaoAtSendVO.java b/src/main/java/kcc/kccadr/message/service/KakaoAtSendVO.java new file mode 100644 index 00000000..93e66b0e --- /dev/null +++ b/src/main/java/kcc/kccadr/message/service/KakaoAtSendVO.java @@ -0,0 +1,229 @@ +package kcc.kccadr.message.service; + +public class KakaoAtSendVO { + + //token + private String accessToken; + private String type; + private String expired; + + //공통 + private String sendFrom; + private String sendTo; + private String country; + private String content; + private String refkey; + private String userinfo; + private String resend; + private String recontent; + private String resellercode; + private String sendtime; + + //알림톡 + private String message; + private String senderkey; + private String templatecode; + private String quickreply; + private String title; + private String header; + private String kakaoAtSeq; + private String sendFlag; + private String sendTime; + + //global + private String isLocal; + private String apiUrl; + + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getExpired() { + return expired; + } + + public void setExpired(String expired) { + this.expired = expired; + } + public String getSendFrom() { + return sendFrom; + } + + public void setSendFrom(String sendFrom) { + this.sendFrom = sendFrom; + } + + public String getSendTo() { + return sendTo; + } + + public void setSendTo(String sendTo) { + this.sendTo = sendTo; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getRefkey() { + return refkey; + } + + public void setRefkey(String refkey) { + this.refkey = refkey; + } + + public String getUserinfo() { + return userinfo; + } + + public void setUserinfo(String userinfo) { + this.userinfo = userinfo; + } + + public String getResend() { + return resend; + } + + public void setResend(String resend) { + this.resend = resend; + } + + public String getRecontent() { + return recontent; + } + + public void setRecontent(String recontent) { + this.recontent = recontent; + } + + public String getResellercode() { + return resellercode; + } + + public void setResellercode(String resellercode) { + this.resellercode = resellercode; + } + + public String getSendtime() { + return sendtime; + } + + public void setSendtime(String sendtime) { + this.sendtime = sendtime; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getSenderkey() { + return senderkey; + } + + public void setSenderkey(String senderkey) { + this.senderkey = senderkey; + } + + public String getTemplatecode() { + return templatecode; + } + + public void setTemplatecode(String templatecode) { + this.templatecode = templatecode; + } + + public String getQuickreply() { + return quickreply; + } + + public void setQuickreply(String quickreply) { + this.quickreply = quickreply; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getHeader() { + return header; + } + + public void setHeader(String header) { + this.header = header; + } + + public String getIsLocal() { + return isLocal; + } + + public void setIsLocal(String isLocal) { + this.isLocal = isLocal; + } + + public String getApiUrl() { + return apiUrl; + } + + public void setApiUrl(String apiUrl) { + this.apiUrl = apiUrl; + } + + public String getKakaoAtSeq() { + return kakaoAtSeq; + } + + public void setKakaoAtSeq(String kakaoAtSeq) { + this.kakaoAtSeq = kakaoAtSeq; + } + + public String getSendFlag() { + return sendFlag; + } + + public void setSendFlag(String sendFlag) { + this.sendFlag = sendFlag; + } + + public String getSendTime() { + return sendTime; + } + + public void setSendTime(String sendTime) { + this.sendTime = sendTime; + } + +} diff --git a/src/main/java/kcc/kccadr/message/service/impl/KakaoAtSendServiceImpl.java b/src/main/java/kcc/kccadr/message/service/impl/KakaoAtSendServiceImpl.java new file mode 100644 index 00000000..21749ab5 --- /dev/null +++ b/src/main/java/kcc/kccadr/message/service/impl/KakaoAtSendServiceImpl.java @@ -0,0 +1,38 @@ +package kcc.kccadr.message.service.impl; + + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import kcc.kccadr.message.service.KakaoAtSendDAO; +import kcc.kccadr.message.service.KakaoAtSendService; +import kcc.kccadr.message.service.KakaoAtSendVO; + +@Service("KakaoAtSendService") +public class KakaoAtSendServiceImpl implements KakaoAtSendService { + + @Resource(name = "kakaoAtSendDAO") + private KakaoAtSendDAO kakaoAtSendDAO; + + @Override + public List selectKakaoAtList() throws Exception { + return kakaoAtSendDAO.selectKakaoAtList(); + } + + @Override + public void insertKakaoAtSendBatch(KakaoAtSendVO kakaoAtSendVO) throws Exception { + kakaoAtSendDAO.insertKakaoAtSendBatch(kakaoAtSendVO); + } + + + @Override + public void updateKakaoAtDetail(KakaoAtSendVO kakaoAtSendVO) throws Exception { + kakaoAtSendDAO.updateKakaoAtDetail(kakaoAtSendVO); + } + + + +} diff --git a/src/main/java/kcc/kccadr/message/web/KakaoAtSendAPI.java b/src/main/java/kcc/kccadr/message/web/KakaoAtSendAPI.java new file mode 100644 index 00000000..54c034d9 --- /dev/null +++ b/src/main/java/kcc/kccadr/message/web/KakaoAtSendAPI.java @@ -0,0 +1,215 @@ +package kcc.kccadr.message.web; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Base64; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.json.JSONObject; + +import kcc.kccadr.message.service.KakaoAtSendVO; + + + +/** + * @Class Name : KakaoAtSendAPI.java + * @Description : 카카오알림톡 API Class + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ --------- --------- ------------------------------- + * @ 2022.11.29 안주영 최초생성 + * + * @author An Joo Young + * @version 1.0 + * @see + * + * + */ + +public class KakaoAtSendAPI{ + + private static KakaoAtSendAPI bizPpurioAPI = null; + + private String tokenUrl = "/v1/token"; + private String msgUrl = "/v3/message"; + + private String senderkey = "b734cce3d7e2349286ea2ab70804bcb2283facb5"; + + private String input = null; + + StringBuffer result = null; + + URL url = null; + + KakaoAtSendVO vo = new KakaoAtSendVO(); + + + //비즈뿌리오 계정 + private static String BIZPPURIO_ACCOUNT = "adr_copyright"; + + private static String BIZPPURIO_ACCOUNT_PASSWORD = "Copy0723!"; + + + // Token 발행 + private String getAccessToken(String isLocal, String apiUrl) { + + result = new StringBuffer(); + String token = ""; + + try { + + /** SSL 인증서 무시 : 비즈뿌리오 API 운영을 접속하는 경우 해당 코드 필요 없음 **/ + if(!"real".equals(isLocal)) { + TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { return null; } + public void checkClientTrusted(X509Certificate[] chain, String authType) { } + public void checkServerTrusted(X509Certificate[] chain, String authType) { } } }; + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + url = new URL(apiUrl + tokenUrl); + + /** Connection 설정 **/ + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Accept-Charset", "UTF-8"); + + //Base64 인코딩 + String idpw = BIZPPURIO_ACCOUNT + ":" + BIZPPURIO_ACCOUNT_PASSWORD; + String authData = Base64.getEncoder().encodeToString(idpw.getBytes()); + + connection.addRequestProperty("Authorization", "Basic " + authData); + + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setConnectTimeout(15000); + + /** Request **/ + OutputStream os = connection.getOutputStream(); + os.flush(); + + + /** Response **/ + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); + + while ((input = in.readLine()) != null) { + result.append(input); + } + connection.disconnect(); + +// System.out.println("Response : " + result.toString()); + + JSONObject jObject = new JSONObject(result.toString()); + token = jObject.getString("accesstoken"); + + } catch (IOException e) { + // TODO Auto-generated catch block + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return token; + } + + public String sendMessage(KakaoAtSendVO vo, String isLocal, String apiUrl) { + + vo.setAccessToken(getAccessToken(isLocal,apiUrl)); + String status = ""; + + result = new StringBuffer(); + + try { + + /** SSL 인증서 무시 : 비즈뿌리오 API 운영을 접속하는 경우 해당 코드 필요 없음 **/ + if(!"real".equals(isLocal)) { + TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { return null; } + public void checkClientTrusted(X509Certificate[] chain, String authType) { } + public void checkServerTrusted(X509Certificate[] chain, String authType) { } } }; + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + url = new URL(apiUrl + msgUrl); + + /** Connection 설정 **/ + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Accept-Charset", "UTF-8"); + connection.addRequestProperty("Authorization", "Bearer " + vo.getAccessToken()); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setConnectTimeout(15000); + + + /** Request **/ + OutputStream os = connection.getOutputStream(); + + String at = "{\"account\":\""+BIZPPURIO_ACCOUNT+"\",\"refkey\":\"1234\"," + + "\"type\":\"at\",\"from\":\"0226690044\",\"to\":\""+vo.getSendTo()+"\"," + + "\"content\":{\"at\":{\"senderkey\":\""+ senderkey +"\",\"templatecode\":\""+vo.getTemplatecode()+"\",\"message\":\""+vo.getMessage()+"\"}}}"; + + os.write(at.getBytes("UTF-8")); + os.flush(); + + /** Response **/ + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); + while ((input = in.readLine()) != null) { + result.append(input); + } + connection.disconnect(); + + System.out.println("Response : " + result.toString()); + + JSONObject jObject = new JSONObject(result.toString()); + status = jObject.getString("description"); + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return status; + } + + public static KakaoAtSendAPI getInstance() + { + if(bizPpurioAPI==null) + { + bizPpurioAPI = new KakaoAtSendAPI(); + } + return bizPpurioAPI; + } + + private KakaoAtSendAPI() {} + +} diff --git a/src/main/java/kcc/kccadr/message/web/KakaoAtSendController.java b/src/main/java/kcc/kccadr/message/web/KakaoAtSendController.java new file mode 100644 index 00000000..d8f36753 --- /dev/null +++ b/src/main/java/kcc/kccadr/message/web/KakaoAtSendController.java @@ -0,0 +1,58 @@ +package kcc.kccadr.message.web; + +import java.util.List; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import kcc.kccadr.message.service.KakaoAtSendService; +import kcc.kccadr.message.service.KakaoAtSendVO; +import kcc.kccadr.msg.service.MsgMgrService; + +@Controller +public class KakaoAtSendController { + + // 발송문구 관리 서비스단 + @Resource(name = "MsgMgrService") + private MsgMgrService msgMgrService; + + @Resource (name = "KakaoAtSendService") + private KakaoAtSendService kakaoAtSendService; + + @Value("#{globalSettings['Globals.BizPpurio.siteUrl']}") + private String apiUrl; + + @Value("#{globalSettings['Globals.prod.islocal']}") + private String isLocal; + + + /** + * 알림톡 배치 수동 실행 + */ + @RequestMapping(value = "/kccadr/message/kakaoAtSendPrcsTest.do") + public ModelAndView kakaoAtSendPrcsTest(HttpServletRequest request) throws Exception { + + ModelAndView modelAndView = new ModelAndView(); + modelAndView.setViewName("jsonView"); + + List list = kakaoAtSendService.selectKakaoAtList(); + + int listSize = list.size(); + + for(int i=0; i + + + + + diff --git a/src/main/resources/egovframework/sqlmap/kccadr/message/KakaoAtSend_SQL_Mysql.xml b/src/main/resources/egovframework/sqlmap/kccadr/message/KakaoAtSend_SQL_Mysql.xml new file mode 100644 index 00000000..1b096696 --- /dev/null +++ b/src/main/resources/egovframework/sqlmap/kccadr/message/KakaoAtSend_SQL_Mysql.xml @@ -0,0 +1,52 @@ + + + + + + + + + INSERT INTO adr_kakao_at_batch + ( + template_code + ,send_to + ,message + ) + VALUES + ( + #templateCode# + ,#sendTo# + ,#message# + + ) + + + + + + + + + + UPDATE + adr_kakao_at_batch + SET + send_flag = 'Y' + ,send_time = NOW() + WHERE + kakao_at_seq = #kakaoAtSeq# + + + + diff --git a/src/main/resources/egovframework/sqlmap/kccadr/msg/Msg_SQL_Mysql.xml b/src/main/resources/egovframework/sqlmap/kccadr/msg/Msg_SQL_Mysql.xml index ec9698ef..71719e50 100644 --- a/src/main/resources/egovframework/sqlmap/kccadr/msg/Msg_SQL_Mysql.xml +++ b/src/main/resources/egovframework/sqlmap/kccadr/msg/Msg_SQL_Mysql.xml @@ -31,7 +31,8 @@ FRST_REGISTER_ID AS frstRegisterId, TO_CHAR ( FRST_REGIST_PNTTM, 'YYYY/MM/DD' ) AS frstRegistPnttm, TO_CHAR ( LAST_UPDT_PNTTM, 'YYYY/MM/DD' ) AS lastUpdtPnttm, - LAST_UPDUSR_ID AS lastUpdusrId + LAST_UPDUSR_ID AS lastUpdusrId, + TEMPLATE_CODE AS templateCode FROM ADR_MSG_MGR WHERE 1=1 @@ -60,12 +61,24 @@ FRST_REGISTER_ID AS frstRegisterId, FRST_REGIST_PNTTM AS frstRegistPnttm, LAST_UPDT_PNTTM AS lastUpdtPnttm, - LAST_UPDUSR_ID AS lastUpdusrId + LAST_UPDUSR_ID AS lastUpdusrId, + TEMPLATE_CODE AS templateCode FROM ADR_MSG_MGR WHERE MSG_SEQ = #msgSeq# + + +