UMS 연계 코드 이관 (admin-portal->oline-common)

This commit is contained in:
cho
2026-02-05 17:56:34 +09:00
parent e83c699dc5
commit fcedbabfc9
8 changed files with 357 additions and 0 deletions
@@ -0,0 +1,7 @@
package com.eactive.eai.custom.alarm.ums;
/**
* GSON Serialize 용 Object
*/
public interface IUmsGsonObject {
}
@@ -0,0 +1,12 @@
package com.eactive.eai.custom.alarm.ums;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class ObpMonitoringUmsTemplate implements IUmsGsonObject {
@SerializedName("MOTR_EVAL_CNTN")
private String message;
}
@@ -0,0 +1,19 @@
package com.eactive.eai.custom.alarm.ums;
import lombok.Getter;
public enum UmsBizWorkCode {
MONITORING("B_ELFN_09510", "OBP 모니터링"),
VERIFY_PHONE("S55_ICT_0006", "API Portal 인증번호"),
;
@Getter
private String code;
@Getter
private String displayName;
UmsBizWorkCode(String code, String displayName) {
this.code = code;
this.displayName = displayName;
}
}
@@ -0,0 +1,18 @@
package com.eactive.eai.custom.alarm.ums;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class UmsCallResult {
private String umsMessageId;
private boolean isSuccess;
private String returnCode;
private String returnMessage;
private String returnPayload;
private Throwable throwable;
}
@@ -0,0 +1,103 @@
package com.eactive.eai.custom.alarm.ums;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Data
@Builder
@Getter
public class UmsRequestPayload {
// MSG_IDNT_NO string 메시지식별번호 50 O "발송 구분을 위한 거래 번호 (GUID 권고)
//GUID로 입력이 어려울시
//어플리케이션코드(3자리)+난수 로 유니크한 ID로 채번 권고"
@Length(min = 1, max = 50)
@NotEmpty
@SerializedName("MSG_IDNT_NO")
private String messageIdentityNo;
// MSG_BZWK_CD string 메시지업무코드 30 O UMS에 등록된 메시지업무코드(AS-IS 템플릿ID)
@NotEmpty
@Length(min = 1, max = 30)
@SerializedName("MSG_BZWK_CD")
private String msgBizWorkCode;
// 메시지업무파라미터내용 / 4000 / JSONObject
// MSG_BZWK_PARAM_CTNT object 메시지업무파라미터내용 4000 메시지업무코드의 템플릿에서 사용하는 변수와 변수값
@NotNull
@SerializedName("MSG_BZWK_PARAM_CTNT")
private IUmsGsonObject content;
// 발송예약일시 / 14 / 실 발송 일자(yyyyMMddHHmmss)
// SND_RESR_DTTM string 발송예약일시 14 20240418111500 O 실 발송 일자(현재시간)
@Pattern(regexp = "^[0-9]{14}$")
@NotEmpty
@SerializedName("SND_RESR_DTTM")
@Builder.Default
private String sendReservationDatetime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
// 휴대전화번호 / 44 / 휴대폰번호(평문, 암호화 둘다가능)
// CPNO string 휴대전화번호 44 "암호화 또는 평문 (safedb not rrno)
//문자일 시 암호문
//숫자일 시 전화번호
//고객번호 또는 휴대전화번호 필수"
@NotEmpty
@Pattern(regexp = "^[0-9]{10,11}$")
@SerializedName("CPNO")
private String cellphone;
// 발송부점코드 / 4 /
// SND_BRCD string 발송부점코드 4 O 0333
@NotEmpty
@SerializedName("SND_BRCD")
@Builder.Default
private String sendBranchCode = "0990";
// 발송직원번호 / 7 / ECEB057(텔러번호?)
// SND_EMPNO string 발송직원번호 7 O ? 넣긴해야함
@NotEmpty
@SerializedName("SND_EMPNO")
@Builder.Default
private String sendEmployeeNo = "ECEB057";
// SRVC_ID string 서비스ID 11 요청단 측 서비스ID
@NotEmpty
@SerializedName("SRVC_ID")
@Builder.Default
private String serviceId = "eAPIM";
// MSG_SND_CHNL_CD string 메시지발송채널코드 2
@SerializedName("MSG_SND_CHNL_CD")
@NotNull
@Builder.Default
private ChannelCode msgSndChnlCd = ChannelCode.KM;
// VALDTN_RSLT_CD string 검증결과코드 2 00으로 고정
@SerializedName("VALDTN_RSLT_CD")
@NotEmpty
@Builder.Default
private String validationResultCode = "00";
public enum ChannelCode {
SM, // SMS
LM, // LMS
MM, // MMS
KM, // 카카오-알림톡
FM, // 카카오-친구톡
SR, // RCS-SMS
LR, // RCS-LMS
MR, // RCS-MMS
TR, // RCS-TEMPLATE
IR, // RCS-IMAGE Template
PM // Push
}
}
@@ -0,0 +1,133 @@
package com.eactive.eai.custom.alarm.ums;
import java.io.IOException;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.EntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.util.Timeout;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import com.eactive.eai.common.util.Logger;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@Component
public class UmsService {
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
private final static String UMS_URL = "http://172.31.35.144:9021";
private final static String API_KEY = "API_KEY";
private final static String SEND_URL = "/ums/openapi/send";
private final static String CONTENT_TYPE = "application/json; charset=utf-8";
private final static String AUTHORIZATION_FMT = "Bearer %s";
Future<UmsCallResult> send(String cpno, String message, UmsBizWorkCode code) throws Exception {
if (message == null) {
throw new IllegalArgumentException("content is null");
}
String guid = String.format("APM-%s",
DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now()));
UmsRequestPayload payload = UmsRequestPayload.builder().messageIdentityNo(guid).msgBizWorkCode(code.getCode())
.content(ObpMonitoringUmsTemplate.builder().message(message).build()).cellphone(cpno)
.msgSndChnlCd(UmsRequestPayload.ChannelCode.KM).build();
try {
ValidationUtil.validateOrThrow(payload);
} catch (Exception ex) {
logger.debug(String.format("UMS Request payload validation failed - %s", payload));
throw ex;
}
return call(SEND_URL, payload);
}
private CloseableHttpClient createHttpClient() {
return HttpClients.createDefault();
}
private Future<UmsCallResult> call(String url, UmsRequestPayload requestPayload) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Gson gson = new Gson();
String json = gson.toJson(requestPayload);
HttpPost httpPost = new HttpPost(UMS_URL + url);
httpPost.setHeader("Content-Type", CONTENT_TYPE);
httpPost.setHeader("Authorization", String.format(AUTHORIZATION_FMT, API_KEY));
httpPost.setEntity(EntityBuilder.create().setText(json).setContentType(ContentType.APPLICATION_JSON).build());
if (logger.isDebugEnabled()) {
try {
logger.debug("Header - {}", httpPost.getHeader("Content-Type"));
logger.debug("Header - {}", httpPost.getHeader("Authorization"));
logger.debug("Request Body : {}",
StreamUtils.copyToString(httpPost.getEntity().getContent(), Charset.defaultCharset()));
} catch (ProtocolException | IOException e) {
throw new RuntimeException(e);
}
}
httpPost.setConfig(RequestConfig.custom().setConnectTimeout(Timeout.ofSeconds(3))
.setResponseTimeout(Timeout.ofSeconds(3)).build());
Future<UmsCallResult> future;
try (CloseableHttpClient httpClient = createHttpClient()) {
future = executor.submit(() -> {
return httpClient.execute(httpPost, res -> {
try {
UmsCallResult result;
String body = EntityUtils.toString(res.getEntity());
if (logger.isDebugEnabled()) {
logger.debug("Response - {}", body);
}
result = gson.fromJson(body, UmsCallResult.class);
result.setUmsMessageId(requestPayload.getMessageIdentityNo());
result.setSuccess(true);
return result;
} catch (JsonSyntaxException e) {
logger.error("UMS Call error(JSON Syntax)", e);
return UmsCallResult.builder().umsMessageId(requestPayload.getMessageIdentityNo())
.isSuccess(false).throwable(e).build();
} catch (Exception e) {
logger.error("UMS Call error", e);
return UmsCallResult.builder().umsMessageId(requestPayload.getMessageIdentityNo())
.isSuccess(false).throwable(e).build();
} finally {
logger.debug("Response status - {}", res.getCode());
if (res.getCode() != 200) {
Arrays.asList(res.getHeaders()).forEach(o -> {
logger.warn("[Header] {}: {}", o.getName(), o.getValue());
});
}
}
});
});
return future;
} catch (Exception e) {
logger.error("UMS call exception", e);
throw new Exception("UMS call failed", e);
} finally {
executor.shutdown();
}
}
}
@@ -0,0 +1,53 @@
package com.eactive.eai.custom.alarm.ums;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator;
public class ValidationUtil {
private static final ValidatorFactory factory;
private static final Validator validator;
static {
factory = Validation.byDefaultProvider()
.configure()
.messageInterpolator(new ParameterMessageInterpolator())
.buildValidatorFactory();
validator = factory.getValidator();
}
private ValidationUtil() {
}
public static <T> Set<ConstraintViolation<T>> validate(T target) {
return validator.validate(target);
}
public static <T> void validateOrThrow(T target) {
Set<ConstraintViolation<T>> violations = validate(target);
if (!violations.isEmpty()) {
String message = violations.stream()
.map(v -> v.getPropertyPath() + " : " + v.getMessage())
.collect(Collectors.joining(", "));
throw new ConstraintViolationException("Validation failed: " + message, violations);
}
}
public static <T> String getViolationMessage(T target) {
Set<ConstraintViolation<T>> violations = validate(target);
if (violations.isEmpty()) return null;
return violations.stream()
.map(v -> v.getPropertyPath() + " : " + v.getMessage())
.collect(Collectors.joining(", "));
}
}
@@ -0,0 +1,12 @@
package com.eactive.eai.custom.alarm.ums;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class VerifyPhoneUmsTemplate implements IUmsGsonObject {
@SerializedName("ATHN_NO")
private String authNumber;
}