전화번호 정규화 유틸 추가 및 적용:
- PhoneNumberUtil 도입: 한국번호 정규화/숫자 추출 지원 - 유틸 적용: 모든 저장 및 조회에 정규형 강제 - 초대 매칭 오류 수정: 휴대폰 형식 차이 대응
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package com.eactive.apim.portal.common.util;
|
||||
|
||||
/**
|
||||
* 한국 전화번호/연락처 정규화 유틸 (portal·admin 공유).
|
||||
*
|
||||
* 전화번호 저장은 본 유틸로 하이픈 구분 정규형으로 통일한다. 저장 형식이 경로별로
|
||||
* 달라(가입=원본, 초대=하이픈, SSO=숫자만) 휴대폰 기반 조회/초대 매칭이 어긋나는 것을 막는다.
|
||||
* 암호화 컨버터가 붙은 필드는 {@code @PrePersist}/{@code @PreUpdate} 에서 본 메서드로 평문을
|
||||
* 정규화한 뒤 암호화되므로 암복호화에 영향이 없다.
|
||||
*/
|
||||
public final class PhoneNumberUtil {
|
||||
|
||||
private PhoneNumberUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 한국 전화번호를 하이픈 구분 정규형으로 변환한다.
|
||||
* 숫자만 추출 후 prefix/길이로 포맷하며, 해당 규칙에 맞지 않는 값은 원본을 그대로 반환한다.
|
||||
* 멱등(이미 정규형이면 동일 결과)이며 null/blank 는 원본을 반환한다.
|
||||
*
|
||||
* <pre>
|
||||
* 휴대폰 01X 11자리 → XXX-XXXX-XXXX (010-1234-5678)
|
||||
* 휴대폰 01X 10자리 → XXX-XXX-XXXX (011-123-4567)
|
||||
* 서울 02 9자리 → 02-XXX-XXXX (02-123-4567)
|
||||
* 서울 02 10자리 → 02-XXXX-XXXX (02-1234-5678)
|
||||
* 지역/070 0XX 10자리 → 0XX-XXX-XXXX (031-234-5678)
|
||||
* 지역/070 0XX 11자리 → 0XX-XXXX-XXXX (070-1234-5678)
|
||||
* 안심 050X 12자리 → 0XXX-XXXX-XXXX (0507-1234-5678)
|
||||
* 대표 15/16/18XX 8자리 → XXXX-XXXX (1588-1234)
|
||||
* 그 외/null → 원본 그대로
|
||||
* </pre>
|
||||
*/
|
||||
public static String normalize(String raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
String digits = raw.replaceAll("[^0-9]", "");
|
||||
int len = digits.length();
|
||||
if (len == 0) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
// 대표번호 15XX/16XX/18XX (8자리, 지역번호 없음)
|
||||
if (len == 8 && (digits.startsWith("15") || digits.startsWith("16") || digits.startsWith("18"))) {
|
||||
return digits.substring(0, 4) + "-" + digits.substring(4);
|
||||
}
|
||||
// 안심번호 050X (12자리)
|
||||
if (len == 12 && digits.startsWith("050")) {
|
||||
return digits.substring(0, 4) + "-" + digits.substring(4, 8) + "-" + digits.substring(8);
|
||||
}
|
||||
// 서울 02
|
||||
if (digits.startsWith("02")) {
|
||||
if (len == 9) {
|
||||
return "02-" + digits.substring(2, 5) + "-" + digits.substring(5);
|
||||
}
|
||||
if (len == 10) {
|
||||
return "02-" + digits.substring(2, 6) + "-" + digits.substring(6);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
// 휴대폰/지역/070 등 0XX
|
||||
if (digits.startsWith("0")) {
|
||||
if (len == 10) {
|
||||
return digits.substring(0, 3) + "-" + digits.substring(3, 6) + "-" + digits.substring(6);
|
||||
}
|
||||
if (len == 11) {
|
||||
return digits.substring(0, 3) + "-" + digits.substring(3, 7) + "-" + digits.substring(7);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 숫자만 추출(발송 게이트웨이 전달·등가 비교용). null 은 그대로 반환.
|
||||
*/
|
||||
public static String digitsOnly(String raw) {
|
||||
return raw == null ? null : raw.replaceAll("[^0-9]", "");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.eactive.apim.portal.invitation.entity;
|
||||
|
||||
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||
import com.eactive.apim.portal.invitation.entity.UserInvitationEnums.InvitationStatus;
|
||||
import com.eactive.apim.portal.jpa.PersonalDataEncryptConverter;
|
||||
import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14;
|
||||
@@ -62,4 +63,11 @@ public class UserInvitation {
|
||||
@Comment("만료일시")
|
||||
private LocalDateTime expiresOn;
|
||||
|
||||
/** 저장 시 초대 휴대폰을 하이픈 구분 정규형으로 통일 */
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
private void normalizePhones() {
|
||||
this.invitationMobile = PhoneNumberUtil.normalize(this.invitationMobile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.eactive.apim.portal.portalorg.entity;
|
||||
|
||||
import com.eactive.apim.portal.common.entity.Auditable;
|
||||
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.ApprovalStatus;
|
||||
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.OrgStatus;
|
||||
import lombok.Data;
|
||||
@@ -95,4 +96,12 @@ public class PortalOrg extends Auditable implements Serializable, com.eactive.ea
|
||||
@Column(name = "reverse_proxy_path", length = 255)
|
||||
@Comment("리버스 프록시 경로")
|
||||
private String reverseProxyPath;
|
||||
|
||||
/** 저장 시 전화번호를 하이픈 구분 정규형으로 통일 */
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
private void normalizePhones() {
|
||||
this.orgPhoneNumber = PhoneNumberUtil.normalize(this.orgPhoneNumber);
|
||||
this.scPhoneNumber = PhoneNumberUtil.normalize(this.scPhoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.eactive.apim.portal.portaluser.entity;
|
||||
|
||||
import com.eactive.apim.portal.common.entity.Auditable;
|
||||
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||
import com.eactive.apim.portal.jpa.PersonalDataEncryptConverter;import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums.ApprovalStatus;
|
||||
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums.RoleCode;
|
||||
@@ -98,4 +99,12 @@ public class PortalUser extends Auditable implements Serializable, com.eactive.e
|
||||
@Column(name = "withdrawal_reason", length=200)
|
||||
@Comment("회원탈퇴사유")
|
||||
private String withdrawalReason;
|
||||
|
||||
/** 저장 시 전화번호를 하이픈 구분 정규형으로 통일 */
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
private void normalizePhones() {
|
||||
this.phoneNumber = PhoneNumberUtil.normalize(this.phoneNumber);
|
||||
this.mobileNumber = PhoneNumberUtil.normalize(this.mobileNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.eactive.apim.portal.user.entity;
|
||||
|
||||
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||
import com.eactive.apim.portal.jpa.PersonalDataEncryptConverter;
|
||||
import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14;
|
||||
import com.eactive.eai.data.converter.StringTrimConverter;
|
||||
@@ -139,4 +140,12 @@ public class UserInfo extends AbstractEntity<String> implements Serializable {
|
||||
public @NonNull String getId() {
|
||||
return userid;
|
||||
}
|
||||
|
||||
/** 저장 시 전화번호를 하이픈 구분 정규형으로 통일 */
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
private void normalizePhones() {
|
||||
this.cphnno = PhoneNumberUtil.normalize(this.cphnno);
|
||||
this.ofctelno = PhoneNumberUtil.normalize(this.ofctelno);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user