package com.eactive.ext.kjb.ums; import com.eactive.apim.portal.portaluser.entity.PortalUser; import com.eactive.apim.portal.template.entity.MessageRequest; import com.eactive.apim.portal.template.repository.MessageRequestRepository; import com.eactive.ext.kjb.common.KjbEaiBatchException; import com.eactive.ext.kjb.common.KjbProperty; import com.eactive.ext.kjb.eai.EaiBatchMessage; import com.eactive.ext.kjb.eai.EaiBatchInterface; import com.eactive.ext.kjb.eai.KjbEaiBatchModule; import com.eactive.ext.kjb.safedb.KjbSafedbWrapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import javax.transaction.Transactional; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; @Slf4j public class EmailJob { private final KjbProperty prop; private final MessageRequest messageRequest; private static final int READY = 1; // Temp 파일 생성 단계 private static final int BEFORE_SEND = 2; private static final int SEND = 3; private final Path eaiFilePath; private final Path backupFilePath; private final Path failedFilePath; private final MessageRequestRepository messageRequestRepository; private final LocalDateTime now = LocalDateTime.now(); private int eaiPhase = 0; private EmailJob(KjbProperty prop, MessageRequest messageRequest, MessageRequestRepository messageRequestRepository) { this.messageRequest = messageRequest; this.prop = prop; String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(now); this.eaiFilePath = Paths.get(prop.getUmsEaiBatchSendDir(), filename); this.backupFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename); this.failedFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename + ".failed"); this.messageRequestRepository = messageRequestRepository; this.doCreateNewFile(); } public static EmailJob create(KjbProperty prop, MessageRequest messageRequest, MessageRequestRepository repository) { if (prop == null) { throw new IllegalArgumentException("Property is null"); } if (messageRequest == null) { throw new IllegalArgumentException("MessageRequest is null"); } validateMessageRequest(messageRequest, false, true); if (messageRequest.getUser() != null) { PortalUser user = messageRequest.getUser(); messageRequest.setUmsUid(UUIDBase62Util.uuidStringToBase62(user.getId())); if (repository != null) { repository.save(messageRequest); } } return new EmailJob(prop, messageRequest, repository); } public static EmailValidationResult validateMessageRequest(MessageRequest messageRequest, boolean forSend, boolean isThrow) { Map errors = new HashMap<>(); if (StringUtils.isEmpty(messageRequest.getId())) { errors.put("id", "ID is required"); } if (forSend) { if (StringUtils.isEmpty(messageRequest.getEmail())) { errors.put("email", "Email is required"); } if (StringUtils.isEmpty(messageRequest.getUsername())) { errors.put("username", "Username is required"); } if (StringUtils.isEmpty(messageRequest.getServiceId())) { errors.put("serviceId", "Service ID is required"); } } // 결과 리턴 if (!errors.isEmpty()) { if (isThrow) { throw new IllegalArgumentException("Invalid MessageRequest: " + errors); } else { return EmailValidationResult.failed(errors); } } return EmailValidationResult.ok(); } @Transactional public void sendEmail() throws KjbEaiBatchException { if (messageRequestRepository != null) { PortalUser user = messageRequest.getUser(); if (user != null) { messageRequest.setUmsUid(UUIDBase62Util.uuidStringToBase62(user.getId())); } messageRequestRepository.save(messageRequest); } try { log.debug("이메일 파일 생성"); doSaveFile(); log.debug("EAI 배치 호출"); eaiBatchCall(); log.debug("발송 성공 처리"); doSuccess(); } catch (KjbEaiBatchException e) { doFail(e); } catch (Exception e) { log.error(e.getMessage(), e); doFail(e); } finally { doDeleteEaiFile(); } } private void doDeleteEaiFile() { // TODO: EAI 발송용 파일 삭제 } private void doFail(Exception e) throws KjbEaiBatchException { // TODO: EAI 발송 실패 처리 if (e instanceof KjbEaiBatchException) { throw (KjbEaiBatchException) e; } else { throw new KjbEaiBatchException("이메일 발송 실패", e); } } private void eaiBatchCall() throws KjbEaiBatchException { KjbEaiBatchModule eaiBatchModule = new KjbEaiBatchModule(prop); EaiBatchInterface eaiBatchInterface = EaiBatchInterface.builder() .id(prop.getUmsEaiBatchInterfaceId()) .sendDir(prop.getUmsEaiBatchSendDir()) .backupDir(prop.getUmsEaiBatchBackupDir()) .errorDir(prop.getUmsEaiBatchErrorDir()) .build(); EaiBatchMessage result = eaiBatchModule.call(eaiBatchInterface, eaiFilePath.getFileName().toString()); if (!"1".equals(result.getResultCode())) { log.error("EAI Batch call failed: {}", result); throw new IllegalStateException("EAI Batch call failed: " + result); } log.debug("EAI Batch call result: {}", result); } private void doSuccess() { // 딱히 뭐 할 거 없음. } public void doCreateNewFile() { if (eaiFilePath.toFile().exists()) { log.error("Mail File exists for ID: {}", messageRequest.getId()); throw new IllegalStateException("Mail File exists for ID: " + messageRequest.getId()); } File mailFile = eaiFilePath.toFile(); try { boolean created = mailFile.createNewFile(); if (!created) { log.error("Cannot create mail file for ID: {}", messageRequest.getId()); throw new IllegalStateException("Cannot create mail file for ID: " + messageRequest.getId()); } } catch (Exception ex) { log.error("Cannot create mail file for ID: {}", messageRequest.getId(), ex); throw new IllegalStateException("Cannot create mail file for ID: " + messageRequest.getId(), ex); } } public void doSaveFile() { String jsonContent = generateJSON(true); log.debug("Generated JSON: \n{}", jsonContent); // 저장은 임시 파일에 euc-kr 인코딩으로 저장 byte[] data = null; try { data = jsonContent.getBytes("euc-kr"); } catch (UnsupportedEncodingException e) { log.error("Cannot encode(euc-kr) JSON: \n{}", jsonContent, e); throw new RuntimeException(e); } try { Files.write(eaiFilePath, data); log.debug("Wrote JSON to file: {}", eaiFilePath.toString()); } catch (IOException e) { log.error("Cannot write JSON to file: {}", eaiFilePath.toString(), e); throw new RuntimeException(e); } } public String generateJSON(boolean isPretty) { validateMessageRequest(messageRequest, true, true); KjbSafedbWrapper safedb = KjbSafedbWrapper.getInstance(); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("MAKE_DATE", DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now())); jsonObject.addProperty("MAKE_SEQNO", "0001"); jsonObject.addProperty("CAMP_ID", messageRequest.getServiceId()); // 전자금융 고객이메일 발송 업무ID (SERVICE_ID) jsonObject.addProperty("ID", messageRequest.getUmsUid()); // 고객 ID jsonObject.addProperty("EMAIL", safedb.encryptNotRnnoString(messageRequest.getEmail())); jsonObject.addProperty("NAME", messageRequest.getUsername()); jsonObject.addProperty("ENCKEY", ""); // 보안메일용으로 기입 불필요 Gson gson = new Gson(); log.debug("Template string to json: {}", messageRequest.getMessage()); JsonObject contentJSon = gson.fromJson(messageRequest.getMessage(), JsonObject.class); contentJSon.entrySet().forEach(entry -> { jsonObject.add(entry.getKey(), entry.getValue()); }); // jsonObject.addProperty("SUBJECT", messageRequest.getSubject()); // jsonObject.addProperty("MESSAGE", messageRequest.getMessage()); String jsonString; if (isPretty) { jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(jsonObject); } else { jsonString = jsonObject.toString(); } return jsonString; } }