Merge branch 'jenkins_with_weblogic' into master
This commit is contained in:
@@ -2,3 +2,6 @@ build/
|
||||
.settings
|
||||
.classpath
|
||||
.project
|
||||
out
|
||||
/.apt_generated/
|
||||
/.apt_generated_tests/
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
`eapim-admin-kjb`는 광주은행(KJB) 전용 커스터마이징을 위한 eapim-admin 확장 모듈입니다. 빠른 부팅 속도를 위해 메인 eapim-admin 프로젝트에서 분리되어 독립적으로 테스트할 수 있습니다.
|
||||
|
||||
## 빌드 및 테스트 명령어
|
||||
|
||||
```bash
|
||||
# 빌드
|
||||
gradle build
|
||||
gradle clean build
|
||||
|
||||
# 테스트 실행 (환경변수 필요)
|
||||
KJB_EAPIM_TEST_ENABLED=TRUE gradle :eapim-admin-kjb:test
|
||||
|
||||
# 특정 테스트 클래스 실행
|
||||
KJB_EAPIM_TEST_ENABLED=TRUE gradle :eapim-admin-kjb:test --tests "com.eactive.ext.kjb.ums.test.UmsTest.testSms"
|
||||
KJB_EAPIM_TEST_ENABLED=TRUE gradle :eapim-admin-kjb:test --tests "com.eactive.ext.kjb.ums.test.UmsTest.testEmail"
|
||||
|
||||
# SafeDB 실제 모드로 테스트 (Linux 서버)
|
||||
KJB_EAPIM_TEST_ENABLED=TRUE gradle :eapim-admin-kjb:test -Psafedb
|
||||
```
|
||||
|
||||
**테스트 실행 조건**: `KJB_EAPIM_TEST_ENABLED=TRUE` 환경변수가 설정되어야 UMS/이메일 테스트가 실행됩니다.
|
||||
|
||||
## 모듈 의존성
|
||||
|
||||
```
|
||||
eapim-admin-kjb
|
||||
├── elink-portal-common # JPA 엔티티 (MessageRequest, MessageCode 등)
|
||||
└── kjb-safedb # 암호화 라이브러리
|
||||
```
|
||||
|
||||
의존 모듈들은 `../elink-portal-common/`, `../kjb-safedb/` 경로에 위치합니다.
|
||||
|
||||
## 아키텍처
|
||||
|
||||
### 주요 컴포넌트
|
||||
|
||||
| 컴포넌트 | 위치 | 설명 |
|
||||
|---------|------|------|
|
||||
| `KjbProperty` | `common/` | DB 테이블 `TSEAIRM24`에서 로드되는 설정 관리. `@KjbPropertyValue` 애노테이션으로 키 매핑 |
|
||||
| `KjbEaiBatchModule` | `eai/` | EAI 배치 시스템 HTTP 연동. 파일 기반 배치 전송 및 보관 기간 관리 |
|
||||
| `KjbUmsService` | `ums/` | UMS API를 통한 카카오 알림톡 발송 |
|
||||
| `KjbEmailSendModule` | `ums/` | EAI 배치를 통한 이메일 발송. 파일 생성 후 배치 호출 |
|
||||
| `KjbObpModule` | `obp/` | OBP(Open Banking Platform) API 연동 |
|
||||
|
||||
### 프로퍼티 키 목록 (`KjbProperty.java`)
|
||||
|
||||
**EAI 배치 연동**
|
||||
- `kjb.eai.batch.url` - EAI 배치 서버 URL
|
||||
- `kjb.eai.batch.connection_timeout` - 연결 타임아웃 (초, 기본값: 5)
|
||||
- `kjb.eai.batch.response_timeout` - 응답 타임아웃 (초, 기본값: 5)
|
||||
- `kjb.eai.batch.charset` - 문자셋 (기본값: euc-kr)
|
||||
|
||||
**이메일 발송 (EAI 배치 경유)**
|
||||
- `kjb.ums.eai_batch.send_dir` - 발송 파일 디렉토리
|
||||
- `kjb.ums.eai_batch.backup_dir` - 백업 디렉토리
|
||||
- `kjb.ums.eai_batch.error_dir` - 에러 디렉토리
|
||||
- `kjb.ums.eai_batch.interface_id` - 인터페이스 ID (13자리)
|
||||
- `kjb.ums.eai_batch.retention_date` - 파일 보관 기간 (일, 기본값: 60)
|
||||
|
||||
**UMS (카카오 알림톡)**
|
||||
- `kjb.ums.host` - UMS API 엔드포인트
|
||||
- `kjb.ums.api_key` - API 인증 키 (36자리 UUID 형식)
|
||||
- `kjb.ums.connection_timeout` - 연결 타임아웃 (초, 기본값: 5)
|
||||
- `kjb.ums.response_timeout` - 응답 타임아웃 (초, 기본값: 5)
|
||||
|
||||
**OBP 연동**
|
||||
- `kjb.obp.url` - OBP API URL
|
||||
- `kjb.obp.trust_system.key/value` - 신뢰 시스템 헤더
|
||||
- `kjb.obp.partner_code.key/value` - 파트너 코드 헤더
|
||||
|
||||
### 메시지 채널
|
||||
|
||||
- `KjbUmsService`: 카카오 알림톡 (`MessageCode.Channels.KAKAO_ALIMTALK`)
|
||||
- `KjbEmailSendModule`: 이메일 (`MessageCode.Channels.EMAIL`)
|
||||
|
||||
## 로컬 개발 환경 (Windows)
|
||||
|
||||
테스트 시 `OsUtil.isWindows()` 조건으로 로컬 경로가 자동 설정됩니다:
|
||||
- 발송 디렉토리: `c:\kjb-logs\sendmail\snd`
|
||||
- 백업 디렉토리: `c:\kjb-logs\sendmail\bak`
|
||||
- 에러 디렉토리: `c:\kjb-logs\sendmail\error`
|
||||
|
||||
URL이 빈 문자열로 설정되면 실제 API 호출 없이 모의 응답을 반환합니다.
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- **Java 8**: Gradle toolchain 강제
|
||||
- **Spring Framework 5.3**: 의존성 주입
|
||||
- **Apache HttpClient 5.1**: HTTP 통신
|
||||
- **Gson 2.3.1**: JSON 처리
|
||||
- **Lombok 1.18.28**: 보일러플레이트 코드 생성
|
||||
- **JUnit 5**: 테스트 프레임워크
|
||||
- **Logback 1.2.10**: 로깅
|
||||
|
||||
## 패키지 구조
|
||||
|
||||
```
|
||||
com.eactive.ext.kjb
|
||||
├── common/ # 공통 (KjbProperty, 예외 클래스)
|
||||
├── eai/ # EAI 배치 연동
|
||||
├── obp/ # OBP API 연동
|
||||
│ └── common/ # OBP HTTP 클라이언트
|
||||
├── ums/ # UMS/이메일 발송
|
||||
│ └── gson/ # UMS 요청/응답 JSON 모델
|
||||
└── utils/ # 유틸리티 (JSON, 검증, OS 판별)
|
||||
```
|
||||
@@ -1,2 +1,3 @@
|
||||
/main/
|
||||
/test/
|
||||
/default/
|
||||
|
||||
+15
-2
@@ -9,16 +9,25 @@ group = 'com.eactive.ext.kjb'
|
||||
version = '1.0-SNAPSHOT'
|
||||
|
||||
def springVersion = "5.3.27"
|
||||
def nexusUrl = "https://nexus.eactive.synology.me:8090"
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "${nexusUrl}/repository/maven-public/"
|
||||
allowInsecureProtocol = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
annotationProcessor "org.projectlombok:lombok:1.18.28"
|
||||
|
||||
api project(':elink-portal-common')
|
||||
api project(":kjb-safedb")
|
||||
//api project(":kjb-safedb")
|
||||
|
||||
api 'com.eactive.elink.common:elink-common-data:4.5.5'
|
||||
|
||||
implementation fileTree(dir: "ext-libs", include: ["*.jar"])
|
||||
|
||||
// api "org.springframework:spring-context:${springVersion}"
|
||||
// api "org.springframework:spring-webmvc:${springVersion}"
|
||||
// api "org.springframework.security.oauth:spring-security-oauth2:2.3.8.RELEASE"
|
||||
@@ -27,12 +36,16 @@ dependencies {
|
||||
implementation "org.apache.httpcomponents.client5:httpclient5:5.1"
|
||||
|
||||
|
||||
compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
|
||||
|
||||
compileOnly 'org.slf4j:jul-to-slf4j:1.7.35'
|
||||
compileOnly 'org.slf4j:jcl-over-slf4j:1.7.35'
|
||||
compileOnly 'org.slf4j:log4j-over-slf4j:1.7.35'
|
||||
compileOnly 'org.slf4j:slf4j-api:1.7.35'
|
||||
compileOnly fileTree(dir: "ext-libs/compileOnly", include: ["*.jar"])
|
||||
|
||||
compileOnly "org.jdom:jdom:1.1"
|
||||
|
||||
compileOnly fileTree(dir: "ext-libs/compileOnly", include: ["*.jar"])
|
||||
|
||||
|
||||
testAnnotationProcessor "org.projectlombok:lombok:1.18.28"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
- API Client 그대로 구현
|
||||
@@ -0,0 +1,94 @@
|
||||
GET /api/organizations/organizationFromObp?cacheBuster=1764073311139&licenseNumber=1838700854&organizationId=15 HTTP/1.1
|
||||
Accept: application/json, text/plain, */*
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: ko,en;q=0.9,en-US;q=0.8
|
||||
Connection: keep-alive
|
||||
Cookie: XSRF-TOKEN=0e8e6398-9231-4b2b-859a-a0ace85c9f12; NG_TRANSLATE_LANG_KEY=%22ko%22; JSESSIONID_APIPORTAL=DE09F0098148634E05D434D3D8D9EFE5; loginStatus=success; showNotice=
|
||||
Host: 192.168.246.16:8080
|
||||
Referer: http://192.168.246.16:8080/
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62
|
||||
X-XSRF-TOKEN: 0e8e6398-9231-4b2b-859a-a0ace85c9f12
|
||||
|
||||
|
||||
HTTP/1.1 200
|
||||
X-Application-Context: portalApplication:swagger,dev:8085
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Content-Length: 2126
|
||||
Date: Tue, 25 Nov 2025 12:21:51 GMT
|
||||
Keep-Alive: timeout=20
|
||||
Connection: keep-alive
|
||||
|
||||
|
||||
{
|
||||
"id" : "001-90010001-000001-6000009",
|
||||
"registeredOn" : "2021-07-19T07:25:53.000+0000",
|
||||
"registeredBy" : "001-90010009-000000-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "재팬리미트파이낸스㈜",
|
||||
"state" : "01",
|
||||
"englishName" : null,
|
||||
"description" : "기업회원-재팬리미트파이낸스㈜",
|
||||
"type" : {
|
||||
"id" : "001-90010001-000001-0000001",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "제휴 기업",
|
||||
"alias" : null,
|
||||
"description" : "제휴 기업",
|
||||
"parent" : {
|
||||
"id" : "001-90010001-000000-0000011",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "고객 타입",
|
||||
"alias" : null,
|
||||
"description" : "고객 타입",
|
||||
"parent" : {
|
||||
"id" : "001-90010001-000000-0000010",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "파티",
|
||||
"alias" : null,
|
||||
"description" : "파티 최상위 타입 자체",
|
||||
"parent" : null
|
||||
}
|
||||
}
|
||||
},
|
||||
"partnerId" : null,
|
||||
"status" : "01",
|
||||
"individualCorporateDivision" : "02",
|
||||
"informationOfferLevel" : "10",
|
||||
"signedOnDay" : "20170726",
|
||||
"signedPath" : "31",
|
||||
"statusReason" : null,
|
||||
"addresses" : [ ],
|
||||
"contacts" : [ ],
|
||||
"communityInfo" : null,
|
||||
"individualAgreements" : [ ],
|
||||
"signup" : null,
|
||||
"accountabilities" : null,
|
||||
"businessManRegistrationNo" : "1838700854",
|
||||
"corporateRegistrationNo" : "1101116464905",
|
||||
"closeDivision" : "09",
|
||||
"incorporatedOnDay" : "20170726",
|
||||
"industryClassification" : null,
|
||||
"representativeName" : "호세인사로와",
|
||||
"representativeBirthday" : null,
|
||||
"typeOfBusiness" : null,
|
||||
"businessCondition" : null,
|
||||
"partnerCode" : "000014-01",
|
||||
"corporateEmployee" : [ ],
|
||||
"defaultAddress" : null,
|
||||
"defaultContact" : null
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
```json
|
||||
{
|
||||
"id" : "001-90010001-000001-6000009",
|
||||
"registeredOn" : "2021-07-19T07:25:53.000+0000",
|
||||
"registeredBy" : "001-90010009-000000-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "재팬리미트파이낸스㈜",
|
||||
"state" : "01",
|
||||
"englishName" : null,
|
||||
"description" : "기업회원-재팬리미트파이낸스㈜",
|
||||
"type" : {
|
||||
"id" : "001-90010001-000001-0000001",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "제휴 기업",
|
||||
"alias" : null,
|
||||
"description" : "제휴 기업",
|
||||
"parent" : {
|
||||
"id" : "001-90010001-000000-0000011",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "고객 타입",
|
||||
"alias" : null,
|
||||
"description" : "고객 타입",
|
||||
"parent" : {
|
||||
"id" : "001-90010001-000000-0000010",
|
||||
"registeredOn" : "2016-09-06T01:51:18.000+0000",
|
||||
"registeredBy" : "001-20160721-163701-0000001",
|
||||
"modifiedOn" : null,
|
||||
"modifiedBy" : null,
|
||||
"name" : "파티",
|
||||
"alias" : null,
|
||||
"description" : "파티 최상위 타입 자체",
|
||||
"parent" : null
|
||||
}
|
||||
}
|
||||
},
|
||||
"partnerId" : null,
|
||||
"status" : "01",
|
||||
"individualCorporateDivision" : "02",
|
||||
"informationOfferLevel" : "10",
|
||||
"signedOnDay" : "20170726",
|
||||
"signedPath" : "31",
|
||||
"statusReason" : null,
|
||||
"addresses" : [ ],
|
||||
"contacts" : [ ],
|
||||
"communityInfo" : null,
|
||||
"individualAgreements" : [ ],
|
||||
"signup" : null,
|
||||
"accountabilities" : null,
|
||||
"businessManRegistrationNo" : "1838700854",
|
||||
"corporateRegistrationNo" : "1101116464905",
|
||||
"closeDivision" : "09",
|
||||
"incorporatedOnDay" : "20170726",
|
||||
"industryClassification" : null,
|
||||
"representativeName" : "호세인사로와",
|
||||
"representativeBirthday" : null,
|
||||
"typeOfBusiness" : null,
|
||||
"businessCondition" : null,
|
||||
"partnerCode" : "000014-01",
|
||||
"corporateEmployee" : [ ],
|
||||
"defaultAddress" : null,
|
||||
"defaultContact" : null
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,151 @@
|
||||
POST /api/admin/commission?cacheBuster=1764308323034 HTTP/1.1
|
||||
Accept: application/json, text/plain, */*
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: ko,en;q=0.9,en-US;q=0.8
|
||||
Connection: keep-alive
|
||||
Content-Length: 235
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cookie: XSRF-TOKEN=a8bfa79d-f739-480a-a3d8-ca524efe8928; NG_TRANSLATE_LANG_KEY=%22ko%22; JSESSIONID_APIPORTAL=F53D8E820FAA78EBE1FF7CD197F67650; loginStatus=success; showNotice=
|
||||
Host: 192.168.246.16:8080
|
||||
Origin: http://192.168.246.16:8080
|
||||
Referer: http://192.168.246.16:8080/
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62
|
||||
X-XSRF-TOKEN: a8bfa79d-f739-480a-a3d8-ca524efe8928
|
||||
|
||||
{"provider":{"id":15,"name":"OBP","description":"OBP","type":"PROVIDER","state":"ACTIVE"},"organization":{"id":70,"name":"글로벌머니익스프레스","description":null,"type":"PARTNER","state":"ACTIVE"},"year":"2025","month":"01"}
|
||||
|
||||
|
||||
HTTP/1.1 200
|
||||
X-Application-Context: portalApplication:swagger,dev:8085
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Transfer-Encoding: chunked
|
||||
Date: Fri, 28 Nov 2025 05:38:43 GMT
|
||||
Keep-Alive: timeout=20
|
||||
Connection: keep-alive
|
||||
|
||||
{
|
||||
"status" : "01",
|
||||
"apiTotalValueSum" : "0.00",
|
||||
"apiSum" : "0.00",
|
||||
"apiTotalValueSum2" : "0.00",
|
||||
"apiSum2" : "0.00",
|
||||
"productTotalValueCountSum" : "7",
|
||||
"productTotalValueAmountSum" : "0",
|
||||
"productSum" : "200000.00",
|
||||
"productTotalValueCountSum2" : "7",
|
||||
"productTotalValueAmountSum2" : "0",
|
||||
"productSum2" : "200000.00",
|
||||
"totalValueCountSum" : "7.00",
|
||||
"totalValueCountSum2" : "7.00",
|
||||
"totalValueAmountSum" : "0",
|
||||
"totalValueAmountSum2" : "0",
|
||||
"sum" : "200000.00",
|
||||
"sum2" : "200000.00",
|
||||
"list" : [ {
|
||||
"paymentTargetName" : "예금주성명조회 API",
|
||||
"paymentTargetType" : "01",
|
||||
"value" : "100.00",
|
||||
"minimumAmount" : "0.00",
|
||||
"maximumAmount" : null,
|
||||
"totalCount" : "0",
|
||||
"totalCount2" : "0",
|
||||
"totalValue" : "0.00",
|
||||
"totalValue2" : "0.00",
|
||||
"minimumAmount2" : "0.00",
|
||||
"maximumAmount2" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : "0.00",
|
||||
"sum2" : "0.00",
|
||||
"detailFeeTypeName" : null,
|
||||
"value2" : "100.00",
|
||||
"changeReason2" : "system billing"
|
||||
}, {
|
||||
"paymentTargetName" : "[계좌] 실지명의조회 API",
|
||||
"paymentTargetType" : "01",
|
||||
"value" : "100.00",
|
||||
"minimumAmount" : "0.00",
|
||||
"maximumAmount" : null,
|
||||
"totalCount" : "0",
|
||||
"totalCount2" : "0",
|
||||
"totalValue" : "0.00",
|
||||
"totalValue2" : "0.00",
|
||||
"minimumAmount2" : "0.00",
|
||||
"maximumAmount2" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : "0.00",
|
||||
"sum2" : "0.00",
|
||||
"detailFeeTypeName" : null,
|
||||
"value2" : "100.00",
|
||||
"changeReason2" : "system billing"
|
||||
}, {
|
||||
"paymentTargetName" : "가상계좌 API",
|
||||
"paymentTargetType" : "02",
|
||||
"value" : "400.00",
|
||||
"minimumAmount" : "100000.00",
|
||||
"maximumAmount" : null,
|
||||
"totalCount" : "7",
|
||||
"totalCount2" : "7",
|
||||
"totalValue" : "7.00",
|
||||
"totalValue2" : "7.00",
|
||||
"minimumAmount2" : "100000.00",
|
||||
"maximumAmount2" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : "100000.00",
|
||||
"sum2" : "100000.00",
|
||||
"detailFeeTypeName" : "API",
|
||||
"value2" : "400.00",
|
||||
"changeReason2" : "system billing"
|
||||
}, {
|
||||
"paymentTargetName" : "입금이체(당행) API",
|
||||
"paymentTargetType" : "02",
|
||||
"value" : "100.00",
|
||||
"minimumAmount" : "0.00",
|
||||
"maximumAmount" : null,
|
||||
"totalCount" : "0",
|
||||
"totalCount2" : "0",
|
||||
"totalValue" : "0.00",
|
||||
"totalValue2" : "0.00",
|
||||
"minimumAmount2" : "0.00",
|
||||
"maximumAmount2" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : "0.00",
|
||||
"sum2" : "0.00",
|
||||
"detailFeeTypeName" : "API",
|
||||
"value2" : "100.00",
|
||||
"changeReason2" : "system billing"
|
||||
}, {
|
||||
"paymentTargetName" : "입금이체(타행) API",
|
||||
"paymentTargetType" : "02",
|
||||
"value" : "400.00",
|
||||
"minimumAmount" : "100000.00",
|
||||
"maximumAmount" : null,
|
||||
"totalCount" : "0",
|
||||
"totalCount2" : "0",
|
||||
"totalValue" : "0.00",
|
||||
"totalValue2" : "0.00",
|
||||
"minimumAmount2" : "100000.00",
|
||||
"maximumAmount2" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : "100000.00",
|
||||
"sum2" : "100000.00",
|
||||
"detailFeeTypeName" : "API",
|
||||
"value2" : "400.00",
|
||||
"changeReason2" : "system billing"
|
||||
} ],
|
||||
"documentFormatNo" : null
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
<%@ page language="java" contentType="text/html; charset=EUC-KR"
|
||||
pageEncoding="EUC-KR"%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<%
|
||||
String user_id = (String)session.getAttribute("SSO_ID");
|
||||
String app_id = (String)session.getAttribute("APP_ID");
|
||||
String ext_info = (String)session.getAttribute("EXT_INFO");
|
||||
String retCode = (String)session.getAttribute("RET_CODE");
|
||||
|
||||
%>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
|
||||
<title>Insert title here</title>
|
||||
</head>
|
||||
<body>
|
||||
<h4>Single Sign On [<%=user_id %>]</h4>
|
||||
<font size=2>
|
||||
<b>[ 업무시스템 - (SAMPLE_APP)]</b>
|
||||
</font>
|
||||
|
||||
<table border=0 width=700 cellpadding=4 cellspacing=1 style="border: solid 1px;">
|
||||
<tr>
|
||||
<td width=200 bgcolor=#C3C3C3><font size=2>* 사용자ID</font></td>
|
||||
<td><font size=2><%=user_id%></font></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td width=200 bgcolor=#C3C3C3><font size=2>* SERVICE_NAME</font></td>
|
||||
<td><font size=2><%=app_id%></font></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width=200 bgcolor=#C3C3C3><font size=2>* 확장정보</font></td>
|
||||
<td><font size=2><%=ext_info%></font></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width=200 bgcolor=#C3C3C3><font size=2>* 인증토큰 상태</font></td>
|
||||
<td><font size=2>retCode = [<%=retCode%>] (1000:누락, 1001:시간, 1002:비정상)</font></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<hr width=700 align=left>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,295 @@
|
||||
<%@ page
|
||||
import="sun.misc.*,
|
||||
java.util.*,
|
||||
java.math.*,
|
||||
java.net.*,
|
||||
com.initech.eam.nls.*,
|
||||
com.initech.eam.api.*,
|
||||
com.initech.eam.base.*,
|
||||
com.initech.eam.nls.command.*,
|
||||
com.initech.eam.smartenforcer.*,
|
||||
examples.api.*"
|
||||
%>
|
||||
<%@page import="com.initech.eam.nls.CookieManager"%>
|
||||
<%!
|
||||
/**[INISAFE NEXESS JAVA AGENT]**********************************************************************
|
||||
* 업무시스템 설정 사항 (업무 환경에 맞게 변경)
|
||||
***************************************************************************************************/
|
||||
|
||||
|
||||
/***[SERVICE CONFIGURATION]***********************************************************************/
|
||||
private String SERVICE_NAME = "Web";
|
||||
private String SERVER_URL = "http://test.kjbank.com";
|
||||
private String SERVER_PORT = "8080";
|
||||
private String ASCP_URL = SERVER_URL + ":" + SERVER_PORT + "/se/login_exec.jsp";
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
/***[SSO CONFIGURATION]**]***********************************************************************/
|
||||
private String NLS_URL = "http://sso.kjbank.com";
|
||||
private String NLS_PORT = "13890";
|
||||
private String NLS_LOGIN_URL = NLS_URL + ":" + NLS_PORT + "/nls3/clientLogin.jsp";
|
||||
private String NLS_LOGOUT_URL= NLS_URL + ":" + NLS_PORT + "/nls3/NCLogout.jsp";
|
||||
private String NLS_ERROR_URL = NLS_URL + ":" + NLS_PORT + "/nls3/error.jsp";
|
||||
|
||||
/***[SSO ND LIST 운영]**]***********************************************************************/
|
||||
private static String ND_URL1 = "http://sso.kjbank.com:5480";
|
||||
|
||||
|
||||
private static Vector PROVIDER_LIST = new Vector();
|
||||
|
||||
private static final int COOKIE_SESSTION_TIME_OUT = 3000000;
|
||||
|
||||
// 인증 타입 (ID/PW 방식 : 1, 인증서 : 3)
|
||||
private String TOA = "1";
|
||||
private String SSO_DOMAIN = ".kjbank.com";
|
||||
|
||||
private static final int timeout = 15000;
|
||||
private static NXContext context = null;
|
||||
static{
|
||||
List<String> serverurlList = new ArrayList<String>();
|
||||
serverurlList.add(ND_URL1);
|
||||
|
||||
context = new NXContext(serverurlList,timeout);
|
||||
CookieManager.setEncStatus(true);
|
||||
|
||||
PROVIDER_LIST.add("sso.kjbank.com");
|
||||
SECode.setCookiePadding("_V42");
|
||||
}
|
||||
|
||||
// by Kang
|
||||
public NXContext getContext()
|
||||
{
|
||||
NXContext context = null;
|
||||
try
|
||||
{
|
||||
List serverurlList = new ArrayList();
|
||||
serverurlList.add(ND_URL1);
|
||||
context = new NXContext(serverurlList);
|
||||
CookieManager.setEncStatus(true);
|
||||
|
||||
PROVIDER_LIST.add("sso.kjbank.com");
|
||||
//NLS3 web.xml의 CookiePadding 값과 같아야 한다. 안그럼 검증 페일남
|
||||
SECode.setCookiePadding("_V42");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
// 통합 SSO ID 조회
|
||||
public String getSsoId(HttpServletRequest request) {
|
||||
String sso_id = null;
|
||||
sso_id = CookieManager.getCookieValue(SECode.USER_ID, request);
|
||||
return sso_id;
|
||||
}
|
||||
|
||||
public String getSystemAccount(String sso_id) {
|
||||
NXContext context = null;
|
||||
NXUserAPI userAPI = null;
|
||||
String retValue = null;
|
||||
|
||||
try {
|
||||
context = getContext();
|
||||
userAPI = new NXUserAPI(context);
|
||||
System.out.println("##############################################");
|
||||
System.out.println("sso_id 2: "+sso_id);
|
||||
System.out.println("SERVICE_NAME : "+SERVICE_NAME);
|
||||
System.out.println("##############################################");
|
||||
NXAccount account = userAPI.getUserAccount(sso_id, SERVICE_NAME);
|
||||
System.out.println(account.toString());
|
||||
retValue = account.getAccountName();
|
||||
System.out.println("retValue = " + retValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
// 통합 SSO 로그인페이지 이동
|
||||
public void goLoginPage(HttpServletResponse response, String uurl)
|
||||
throws Exception {
|
||||
com.initech.eam.nls.CookieManager.addCookie(SECode.USER_URL, uurl, SSO_DOMAIN, response);
|
||||
com.initech.eam.nls.CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response);
|
||||
response.sendRedirect(NLS_LOGIN_URL + "?UURL=" + uurl);
|
||||
}
|
||||
|
||||
// 통합 SSO 로그인페이지 이동
|
||||
public void goLoginPage(HttpServletResponse response)throws Exception {
|
||||
CookieManager.addCookie(SECode.USER_URL, ASCP_URL, SSO_DOMAIN, response);
|
||||
CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response);
|
||||
response.sendRedirect(NLS_LOGIN_URL);
|
||||
}
|
||||
|
||||
// 통합인증 세션을 체크 하기 위하여 사용되는 API
|
||||
public String getEamSessionCheck(HttpServletRequest request,HttpServletResponse response){
|
||||
String retCode = "";
|
||||
try {
|
||||
retCode = CookieManager.verifyNexessCookie(request, response, 10, COOKIE_SESSTION_TIME_OUT,PROVIDER_LIST);
|
||||
} catch(Exception npe) {
|
||||
npe.printStackTrace();
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
//ND API를 사용해서 쿠키검증하는것(현재 표준에서는 사용안함, 근데 해도 되기는 함)
|
||||
public String getEamSessionCheck2(HttpServletRequest request,HttpServletResponse response)
|
||||
{
|
||||
String retCode = "";
|
||||
try {
|
||||
NXNLSAPI nxNLSAPI = new NXNLSAPI(context);
|
||||
retCode = nxNLSAPI.readNexessCookie(request, response, 0, 0);
|
||||
} catch(Exception npe) {
|
||||
npe.printStackTrace();
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
// SSO 에러페이지 URL
|
||||
public void goErrorPage(HttpServletResponse response, int error_code)throws Exception {
|
||||
CookieManager.removeNexessCookie(SSO_DOMAIN, response);
|
||||
CookieManager.addCookie(SECode.USER_URL, ASCP_URL, SSO_DOMAIN, response);
|
||||
response.sendRedirect(NLS_ERROR_URL + "?errorCode=" + error_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 기본정보 가져오기.
|
||||
* @param String userid
|
||||
* @return Properties
|
||||
*/
|
||||
public Properties getUserInfos(String userid) throws Exception {
|
||||
|
||||
NXContext context = null;
|
||||
context = getContext();
|
||||
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
Properties propt = null;
|
||||
|
||||
if (userid==null || userid.length() <= 0)
|
||||
return propt;
|
||||
|
||||
try {
|
||||
NXUserInfo userInfo = userAPI.getUserInfo(userid);
|
||||
propt = new Properties();
|
||||
//System.out.println("userInfo.getName()=["+userInfo.getName()+"]");
|
||||
propt.setProperty("USERID", userInfo.getUserId());
|
||||
propt.setProperty("EMAIL", userInfo.getEmail());
|
||||
propt.setProperty("ENABLE", String.valueOf(userInfo.getEnable()));
|
||||
propt.setProperty("STARTVALID", userInfo.getStartValid());
|
||||
propt.setProperty("ENDVALID", userInfo.getEndValid());
|
||||
propt.setProperty("NAME", userInfo.getName());
|
||||
propt.setProperty("ENCPASSWD", userInfo.getEncpasswd());
|
||||
propt.setProperty("LASTPASSWDCHANGE", userInfo.getLastpasswdchange());
|
||||
propt.setProperty("LastLoginIP", userInfo.getLastLoginIp());
|
||||
propt.setProperty("LastLoginTime", userInfo.getLastLoginTime());
|
||||
propt.setProperty("LastLoginAuthLevel", userInfo.getLastLoginAuthLevel());
|
||||
|
||||
} catch (EmptyResultException e) {
|
||||
e.printStackTrace();
|
||||
} catch (APIException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return propt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자의 기본정보 중에서 입력된 키 값만 가지고 온다.
|
||||
* @param String userid
|
||||
* @param String key
|
||||
* @return String
|
||||
*/
|
||||
public String getUserInfo(String userid, String key) throws Exception {
|
||||
if(userid==null||userid.length()<1) return null;
|
||||
|
||||
String userInfo = "";
|
||||
|
||||
try{
|
||||
Properties propt = getUserInfos(userid);
|
||||
userInfo = propt.getProperty(key);
|
||||
} catch (Exception e) {
|
||||
//throw e;
|
||||
e.printStackTrace();
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 확장정보 조회
|
||||
* return : Properties
|
||||
* 사용자가 존재하지 않거나 확장필드가 없다면 return null
|
||||
*/
|
||||
public Properties getUserExFields(String userid)
|
||||
throws Exception {
|
||||
NXContext context = getContext();
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
Properties prop = null;
|
||||
NXExternalFieldSet nxefs = null;
|
||||
|
||||
try {
|
||||
nxefs = userAPI.getUserExternalFields(userid);
|
||||
prop = new Properties();
|
||||
|
||||
if (nxefs != null) {
|
||||
Iterator iter = nxefs.iterator();
|
||||
while(iter.hasNext()) {
|
||||
NXExternalField nxef = (NXExternalField) iter.next();
|
||||
if(nxef.getName().equals("PASSINIT")){
|
||||
String sPassintVal = (String) nxef.getValue();
|
||||
prop.setProperty(nxef.getName(), sPassintVal.equals("") ? "0" : sPassintVal);
|
||||
}
|
||||
else
|
||||
prop.setProperty(nxef.getName(), (String) nxef.getValue());
|
||||
//System.out.println("확장 필드 " + nxef.getName() + " : " + nxef.getValue());
|
||||
}
|
||||
} else {
|
||||
// prop is null
|
||||
}
|
||||
} catch (EmptyResultException e) {
|
||||
// 사용자가 존재하지 않거나 확장필드가 없음
|
||||
} catch (APIException e) {
|
||||
throw e;
|
||||
//e.printStackTrace();
|
||||
}
|
||||
//System.out.println("getUserExFields:[" + prop + "]");
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자의 특정 확장 필드 정보 조회
|
||||
* return : String
|
||||
* 사용자가 존재하지 않거나 확장필드가 없다면 return null
|
||||
*/
|
||||
public String getUserExField(String userid, String exName)
|
||||
throws Exception {
|
||||
NXContext context = getContext();
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
NXExternalField nxef = null;
|
||||
String returnValue = null;
|
||||
|
||||
try {
|
||||
|
||||
System.out.println("getUserExField==="+ userid ) ;
|
||||
nxef = userAPI.getUserExternalField(userid, exName);
|
||||
System.out.println("nxef==="+ (String) nxef.getValue() ) ;
|
||||
returnValue = (String) nxef.getValue();
|
||||
} catch (EmptyResultException e) {
|
||||
// 사용자가 존재하지 않거나 확장필드가 없음
|
||||
} catch (APIException e) {
|
||||
throw e;
|
||||
//e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw e;
|
||||
//e.printStackTrace();
|
||||
}
|
||||
/*
|
||||
System.out.println("getUserExField:[" + userid + ":"
|
||||
+ exName + ":" + returnValue+ "]");
|
||||
*/
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
%>
|
||||
@@ -0,0 +1,69 @@
|
||||
<%@ page language="java" contentType="text/html;charset=EUC-KR" %>
|
||||
<%@ include file="./config.jsp" %>
|
||||
<%
|
||||
|
||||
String uurl = null;
|
||||
String sso_id = null;
|
||||
String service_id = null;
|
||||
String ext_info = null;
|
||||
String retCode = null;
|
||||
//http://test.kjbank.com:8080/se/login_exec.jsp : 꼭 도메인으로 호출해야 된다.
|
||||
//1.SSO ID 수신
|
||||
sso_id = getSsoId(request);
|
||||
|
||||
// 2. UURL 수신
|
||||
uurl = request.getParameter("UURL");
|
||||
|
||||
if (sso_id == null) {
|
||||
//uurl 이 없다면, 근데 여기서 uurl 은 뭘 체크하는거지? uurl 에 test.kjbank.com:8080/se/login_exec.jsp 를 넣는구나.
|
||||
if (uurl == null) uurl = ASCP_URL;
|
||||
|
||||
// 3. SSO 인증 정보가 없으면 통합 로그인 페이지로 이동
|
||||
goLoginPage(response, uurl);
|
||||
return;
|
||||
} else {
|
||||
|
||||
//4.쿠키 유효성 확인 :0(정상)
|
||||
retCode = getEamSessionCheck(request,response);
|
||||
|
||||
if(!retCode.equals("0")){
|
||||
goErrorPage(response, Integer.parseInt(retCode));
|
||||
return;
|
||||
}
|
||||
/***********************************************************************************
|
||||
* < TO-DO >
|
||||
* SSO 통합 인증이 완료되었으므로, 업무 시스템 로그인은 건너뛰도록 코드를 수정합니다.
|
||||
* SSO 에서 제공한 사번은 sso_id 변수에 저장되어 있습니다.
|
||||
* 시스템에서 필요로 하는 세션 정보를 세팅 코드를 여기에 작성합니다.
|
||||
************************************************************************************/
|
||||
|
||||
//5 확장 정보 조회
|
||||
ext_info = getUserExField(sso_id, "CELLPHONENO");
|
||||
service_id = SERVICE_NAME;
|
||||
System.out.println ("SERVICE_NAME : " + service_id);
|
||||
//
|
||||
//6.업무시스템에 읽을 사용자 아이디를 세션으로 생성
|
||||
/* 변경 전
|
||||
String EAM_ID = (String)session.getAttribute("SSO_ID");
|
||||
if(EAM_ID == null || EAM_ID.equals("")) {
|
||||
session.setAttribute("SSO_ID", sso_id);
|
||||
session.setAttribute("APP_ID", service_id);
|
||||
session.setAttribute("EXT_INFO", ext_info);
|
||||
session.setAttribute("RET_CODE", retCode);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*변경 후*/
|
||||
if(!sso_id.replace(" ", "").equals("")) {
|
||||
session.setAttribute("SSO_ID", sso_id);
|
||||
session.setAttribute("APP_ID", service_id);
|
||||
session.setAttribute("EXT_INFO", ext_info);
|
||||
session.setAttribute("RET_CODE", retCode);
|
||||
}
|
||||
|
||||
//7.업무시스템 페이지 호출(세션 페이지 또는 메인페이지 지정) --> 업무시스템에 맞게 URL 수정!
|
||||
response.sendRedirect(SERVER_URL + ":" + SERVER_PORT + "/se/app01.jsp");
|
||||
}
|
||||
%>
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,463 @@
|
||||
POST http://192.168.246.15:8181/api/billing/findBillingForCondition
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=
|
||||
x-obp-partnercode: 100001-01
|
||||
|
||||
{
|
||||
"partnerCode": "000002-01",
|
||||
"targetOnMonth": "202503"
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
|
||||
curl -X POST --location "http://192.168.246.15:8181/api/billing/billing/findBillingForCondition" \
|
||||
-H "Content-Type: application/json; charset=UTF-8" \
|
||||
-H "x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=" \
|
||||
-H "x-obp-partnercode: 100001-01" \
|
||||
-d '{
|
||||
"partnerCode": "000002-01",
|
||||
"targetOnMonth": "202510"
|
||||
}'
|
||||
POST http://192.168.246.15:8181/api/billing/findBillingForCondition
|
||||
x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=
|
||||
x-obp-partnercode: 100001-01
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
{
|
||||
"partnerCode": "000002-01",
|
||||
"targetOnMonth": "202503"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"status" : "01",
|
||||
"apiTotalValueSum" : 0.00,
|
||||
"apiSum" : 100000.00,
|
||||
"apiTotalValueSum2" : 0.00,
|
||||
"apiSum2" : 100000.00,
|
||||
"productTotalValueCountSum" : 0,
|
||||
"productTotalValueAmountSum" : 0.00,
|
||||
"productSum" : 600000.00,
|
||||
"productTotalValueCountSum2" : 0,
|
||||
"productTotalValueAmountSum2" : 0.00,
|
||||
"productSum2" : 600000.00,
|
||||
"totalValueCountSum" : 0.00,
|
||||
"totalValueCountSum2" : 0.00,
|
||||
"totalValueAmountSum" : 0.00,
|
||||
"totalValueAmountSum2" : 0.00,
|
||||
"sum" : 700000.00,
|
||||
"sum2" : 700000.00,
|
||||
"list" : [ {
|
||||
"id" : "001-20250401-060001-0001469",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "[계좌] 실지명의조회",
|
||||
"paymentTargetType" : "01",
|
||||
"paymentTargetId" : "001-20180918-085325-0000353",
|
||||
"detailFeeType" : "11",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "001-20201012-154617-0000969",
|
||||
"feeDetailId" : "001-20221115-105403-0011851",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 100.00,
|
||||
"minimumAmount" : 0.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 0.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 100.00,
|
||||
"minimumAmount2" : 0.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 0.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 0.00,
|
||||
"sum2" : 0.00
|
||||
}, {
|
||||
"id" : "001-20250401-060001-0001468",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "예금주성명조회 API",
|
||||
"paymentTargetType" : "01",
|
||||
"paymentTargetId" : "001-20180419-200001-0000100",
|
||||
"detailFeeType" : "11",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131549-0085992",
|
||||
"feeDetailId" : "101-20180516-131549-0085993",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 100.00,
|
||||
"minimumAmount" : 100000.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 100000.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 100.00,
|
||||
"minimumAmount2" : 100000.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 100000.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : null,
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 100000.00,
|
||||
"sum2" : 100000.00
|
||||
}, {
|
||||
"id" : "001-20250401-060002-0001472",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "P2P 가상계좌(투자자용) API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000003",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0085994",
|
||||
"feeDetailId" : "101-20180516-131550-0085995",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 300.00,
|
||||
"minimumAmount" : 200000.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 200000.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 300.00,
|
||||
"minimumAmount2" : 200000.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 200000.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 200000.00,
|
||||
"sum2" : 200000.00
|
||||
}, {
|
||||
"id" : "001-20250401-060002-0001476",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "P2P 지급이체(당행_프로모션) API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000007",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0085996",
|
||||
"feeDetailId" : "101-20180516-131550-0085997",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 0.00,
|
||||
"minimumAmount" : 0.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 0.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 0.00,
|
||||
"minimumAmount2" : 0.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 0.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 0.00,
|
||||
"sum2" : 0.00
|
||||
}, {
|
||||
"id" : "001-20250401-060002-0001474",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "P2P 지급이체 API(타행)",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000005",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0085998",
|
||||
"feeDetailId" : "101-20180516-131550-0085999",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 300.00,
|
||||
"minimumAmount" : 200000.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 200000.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 300.00,
|
||||
"minimumAmount2" : 200000.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 200000.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 200000.00,
|
||||
"sum2" : 200000.00
|
||||
}, {
|
||||
"id" : "001-20250401-060002-0001473",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "P2P 지급이체(대출실행집금용) API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000004",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0086000",
|
||||
"feeDetailId" : "101-20180516-131550-0086001",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 50.00,
|
||||
"minimumAmount" : 0.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 0.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 50.00,
|
||||
"minimumAmount2" : 0.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 0.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 0.00,
|
||||
"sum2" : 0.00
|
||||
}, {
|
||||
"id" : "001-20250401-060002-0001475",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "P2P 투자금 관리 API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000006",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0086002",
|
||||
"feeDetailId" : "001-20231128-161411-0007408",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "01",
|
||||
"value" : 0.05,
|
||||
"minimumAmount" : 200000.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "02",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 200000.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 0.05,
|
||||
"minimumAmount2" : 200000.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 200000.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "금액",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "율",
|
||||
"sum" : 200000.00,
|
||||
"sum2" : 200000.00
|
||||
}, {
|
||||
"id" : "001-20250401-060001-0001470",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "입금이체(당행) API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000001",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0086004",
|
||||
"feeDetailId" : "101-20180516-131550-0086005",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 50.00,
|
||||
"minimumAmount" : 0.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 0.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 50.00,
|
||||
"minimumAmount2" : 0.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 0.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 0.00,
|
||||
"sum2" : 0.00
|
||||
}, {
|
||||
"id" : "001-20250401-060001-0001471",
|
||||
"billingId" : "001-20250401-060001-0001467",
|
||||
"paymentTargetName" : "입금이체(타행) API",
|
||||
"paymentTargetType" : "02",
|
||||
"paymentTargetId" : "001-20171227-110000-0000002",
|
||||
"detailFeeType" : "21",
|
||||
"revision" : 0,
|
||||
"contractAccountId" : "001-20180430-104631-0798825",
|
||||
"feeId" : "101-20180516-131550-0086006",
|
||||
"feeDetailId" : "101-20180516-131550-0086007",
|
||||
"bank" : "034",
|
||||
"accountNo" : "1107617597186",
|
||||
"valueDivision" : "02",
|
||||
"value" : 300.00,
|
||||
"minimumAmount" : 0.00,
|
||||
"maximumAmount" : null,
|
||||
"paymentBase" : "01",
|
||||
"paymentBaseValue" : 1.00,
|
||||
"paymentTiming" : "02",
|
||||
"totalValue" : 0.00,
|
||||
"withdrawalAmount" : 0.00,
|
||||
"totalCount" : 0,
|
||||
"revision2" : 0,
|
||||
"totalValue2" : 0.00,
|
||||
"value2" : 300.00,
|
||||
"minimumAmount2" : 0.00,
|
||||
"maximumAmount2" : null,
|
||||
"changeReason2" : "system billing",
|
||||
"withdrawalAmount2" : 0.00,
|
||||
"totalCount2" : 0,
|
||||
"detailFeeTypeName" : "상품수수료",
|
||||
"paymentBaseName" : "건",
|
||||
"paymentTimingName" : "사후부과",
|
||||
"valueDivisionName" : "금액",
|
||||
"sum" : 0.00,
|
||||
"sum2" : 0.00
|
||||
} ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$ curl -X POST --location "http://192.168.246.15:8181/api/billing/billing/findBillingForCondition/print" -H "Content-Type: application/json; charset=UTF-8" -H "x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=" -H "x-obp-partnercode: 100001-01" -d '{
|
||||
"partnerCode": "000014-01",
|
||||
"targetOnMonth": "202503"
|
||||
}'
|
||||
{
|
||||
"billingId" : "001-20250401-060004-0001512",
|
||||
"status" : "01",
|
||||
"apiTotalValueSum" : 0,
|
||||
"apiSum" : 0,
|
||||
"apiTotalValueSum2" : 0,
|
||||
"apiSum2" : 0,
|
||||
"productTotalValueCountSum" : 0,
|
||||
"productTotalValueAmountSum" : 0,
|
||||
"productSum" : 0,
|
||||
"productTotalValueCountSum2" : 0,
|
||||
"productTotalValueAmountSum2" : 0,
|
||||
"productSum2" : 0,
|
||||
"totalValueCountSum" : 0,
|
||||
"totalValueCountSum2" : 0,
|
||||
"totalValueAmountSum" : 0,
|
||||
"totalValueAmountSum2" : 0,
|
||||
"sum" : 0,
|
||||
"sum2" : 0,
|
||||
"list" : [ ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
curl -X POST --location "http://192.168.246.15:8181/api/billing/billing/findBillingForCondition/print" -H "Content-Type: application/json; charset=UTF-8" -H "x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=" -H "x-obp-partnercode: 100001-01" -d '{
|
||||
> "partnerCode": "000014-01",
|
||||
> "targetOnMonth": "202503"
|
||||
> }'
|
||||
{
|
||||
"error" : {
|
||||
"code" : "E.BILLING.NOT_PRINT_BEFORE_CONFIRM",
|
||||
"message" : "확정이전에는 출력이 안됩니다."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
weblogic@apigwd01(DEV-eAPIM-GW#1):[/weblogic]
|
||||
$ curl -X POST --location "http://192.168.246.15:8181/api/billing/billing/findBillingForCondition/print" -H "Content-Type: application/json; charset=UTF-8" -H "x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=" -H "x-obp-partnercode: 100001-01" -d '{
|
||||
"partnerCode": "000002-02",
|
||||
"targetOnMonth": "201803"
|
||||
}'
|
||||
{
|
||||
"error" : {
|
||||
"code" : "E.BILLING.NOT_PRINT_BEFORE_CONFIRM",
|
||||
"message" : "확정이전에는 출력이 안됩니다."
|
||||
}
|
||||
}
|
||||
weblogic@apigwd01(DEV-eAPIM-GW#1):[/weblogic]
|
||||
$ curl -X POST --location "http://192.168.246.15:8181/api/billing/billing/findBillingForCondition/print" -H "Content-Type: application/json; charset=UTF-8" -H "x-obp-trust-system: APIMPT-0002-QVBJTVBULTAwMDI=" -H "x-obp-partnercode: 100001-01" -d '{
|
||||
"partnerCode": "000002-02",
|
||||
"targetOnMonth": "199603"
|
||||
}'
|
||||
{
|
||||
"error" : {
|
||||
"code" : "E.BILLING.NOT_PRINT_BEFORE_CONFIRM",
|
||||
"message" : "확정이전에는 출력이 안됩니다."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.eactive.ext.kjb.common;
|
||||
|
||||
public class KjbObpException extends Exception {
|
||||
private int statusCode;
|
||||
|
||||
public KjbObpException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public KjbObpException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public KjbObpException(int statusCode, String message) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,9 @@ package com.eactive.ext.kjb.common;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Pattern;
|
||||
@@ -29,17 +32,17 @@ public class KjbProperty {
|
||||
@NotEmpty
|
||||
private String eaiBatchCharset = "euc-kr";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.send_dir")
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.send_dir", defaultValue = "/Data/eapim/portal/sendmail/snd")
|
||||
@NotEmpty(message = "kjb.ums.eai_batch.send_dir 는 필수값입니다.")
|
||||
private String umsEaiBatchSendDir;
|
||||
private String umsEaiBatchSendDir = "/Data/eapim/portal/sendmail/snd";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.backup_dir")
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.backup_dir", defaultValue = "/Data/eapim/portal/sendmail/bak")
|
||||
@NotEmpty(message = "kjb.ums.eai_batch.backup_dir 는 필수값입니다.")
|
||||
private String umsEaiBatchBackupDir;
|
||||
private String umsEaiBatchBackupDir = "/Data/eapim/portal/sendmail/bak";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.error_dir")
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.error_dir", defaultValue = "/Data/eapim/portal/sendmail/bak")
|
||||
@NotEmpty(message = "kjb.ums.eai_batch.error_dir 는 필수값입니다.")
|
||||
private String umsEaiBatchErrorDir;
|
||||
private String umsEaiBatchErrorDir = "/Data/eapim/portal/sendmail/bak";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.ums.eai_batch.interface_id")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{13}$", message = "kjb.ums.eai_batch.interface_id 는 12자리 영문대소문자 및 숫자 조합이어야 합니다.")
|
||||
@@ -69,4 +72,189 @@ public class KjbProperty {
|
||||
@KjbPropertyValue(key = "kjb.ums.timeout", defaultValue = "10")
|
||||
@Min(1) @Max(30)
|
||||
private int umsTimeout = 10;
|
||||
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.url")
|
||||
@Pattern(regexp = "^(https?://[^\\s/$.?#][^\\s]*)|\\s*$", message = "kjb.obp.url 는 유효한 URL 형식이거나 공백이어야 합니다. 예: http://example.com/api")
|
||||
private String obpUrl;
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.trust_system.key", defaultValue = "x-obp-trust-system")
|
||||
@NotEmpty
|
||||
private String obpTrustSystemKey = "x-obp-trust-system";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.trust_system.value", defaultValue = "APIMPT-0002-QVBJTVBULTAwMDI=")
|
||||
@NotEmpty
|
||||
private String obpTrustSystemValue = "APIMPT-0002-QVBJTVBULTAwMDI=";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.partner_code.key", defaultValue = "x-obp-partnercode")
|
||||
@NotEmpty
|
||||
private String obpPartnerCodeKey = "x-obp-partnercode";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.partner_code.value", defaultValue = "100001-01")
|
||||
@NotEmpty
|
||||
private String obpPartnerCodeValue = "100001-01";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.connection_timeout", defaultValue = "5")
|
||||
@Min(1) @Max(10)
|
||||
private int obpConnectionTimeout = 5;
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.response_timeout", defaultValue = "5")
|
||||
@Min(1) @Max(30)
|
||||
private int obpResponseTimeout = 5;
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.timeout", defaultValue = "10")
|
||||
@Min(1) @Max(30)
|
||||
private int obpTimeout = 10;
|
||||
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.url.commission", defaultValue = "/api/billing/billing/findBillingForCondition")
|
||||
@NotEmpty
|
||||
private String obpUrlCommission = "/api/billing/billing/findBillingForCondition";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.url.commission_print", defaultValue = "/api/billing/billing/findBillingForCondition/print")
|
||||
@NotEmpty
|
||||
private String obpUrlCommissionPrint = "/api/billing/billing/findBillingForCondition/print";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.obp.url.organization_fmt", defaultValue = "/api/customer/findCustomerByBusinessManRegistrationNo/%s")
|
||||
@NotEmpty
|
||||
private String obpUrlOrganizationFmt = "/api/customer/findCustomerByBusinessManRegistrationNo/%s";
|
||||
|
||||
|
||||
// 광주은행 SSO
|
||||
|
||||
@KjbPropertyValue(key = "kjb.url", defaultValue = "https://manage-eapim.kjbank.com")
|
||||
@NotEmpty
|
||||
private String url = "https://manage-eapim.kjbank.com";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.sso.service_name", defaultValue = "Web")
|
||||
@NotEmpty
|
||||
private String ssoServiceName = "Web";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.sso.ascp_url", defaultValue = "/monitoring/sso/login.do")
|
||||
@NotEmpty
|
||||
private String ssoAscpUri = "/monitoring/sso/login.do";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.sso.domain", defaultValue = "sso.kjbank.com")
|
||||
@NotEmpty
|
||||
private String ssoDomain = "sso.kjbank.com";
|
||||
|
||||
@KjbPropertyValue(key = "kjb.sso.nls_port", defaultValue = "13890")
|
||||
@Min(1024) @Max(65535)
|
||||
private int ssoNlsPort = 13890;
|
||||
|
||||
@KjbPropertyValue(key = "kjb.sso.ignore_validation", defaultValue = "false")
|
||||
private boolean ssoIgnoreValidation = false;
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.sso.sync_info",
|
||||
defaultValue = "true",
|
||||
description = "SSO 인증시 사용자 정보 동기화 여부(false 시 이름과 ID를 동일하게 처리. 나머지 정보는 무시)")
|
||||
private boolean ssoSyncInfo = true;
|
||||
|
||||
|
||||
// SMS 2차 인증
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.sms_auth.enabled",
|
||||
defaultValue = "true",
|
||||
description = "SMS 2차 인증 사용 여부. true 시 휴대폰번호 없는 사용자는 ID/PW 로그인 불가")
|
||||
private boolean smsAuthEnabled = false;
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.sms_auth.mode",
|
||||
defaultValue = "real",
|
||||
description = "인증번호 생성 모드: real(랜덤), hhmm00(현재시각+00), fixed(고정값)")
|
||||
@Pattern(regexp = "^(real|hhmm00|fixed)$", message = "kjb.sms_auth.mode는 real, hhmm00, fixed 중 하나여야 합니다.")
|
||||
private String smsAuthMode = "real";
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.sms_auth.fixed_value",
|
||||
defaultValue = "654321",
|
||||
description = "mode가 fixed일 때 사용할 고정 인증번호 (6자리 숫자)")
|
||||
@Pattern(regexp = "^\\d{6}$", message = "kjb.sms_auth.fixed_value는 6자리 숫자여야 합니다.")
|
||||
private String smsAuthFixedValue = "654321";
|
||||
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.api.allow_ip_list",
|
||||
description = "API 접근 허용 IP 목록 (콤마(,)로 구분된 IP들, 예: 192.168.0.1, 192.168.1.*,127.*.*.*",
|
||||
defaultValue = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*"
|
||||
)
|
||||
private String apiAllowIpList = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*";
|
||||
|
||||
|
||||
@KjbPropertyValue(
|
||||
key = "kjb.api_gw_metric.page_size",
|
||||
description = "API GW Metric 조회시 페이지 크기 설정 (Integer, 0 = 무한, 기본값 10000)",
|
||||
defaultValue = "10000"
|
||||
)
|
||||
private Integer apiGwMetricPageSize = 10000;
|
||||
|
||||
|
||||
public String toJsonString(boolean isPretty) {
|
||||
return isPretty
|
||||
? new GsonBuilder().setPrettyPrinting().create().toJson(this)
|
||||
: new Gson().toJson(this);
|
||||
}
|
||||
|
||||
|
||||
// 기본 프로퍼티 목록을 콘솔로 출력 (가이드용)
|
||||
public static void main(String[] args) {
|
||||
System.out.println("| Key | Default Value | Description |");
|
||||
System.out.println("|-----|---------------|-------------|");
|
||||
|
||||
for (java.lang.reflect.Field field : KjbProperty.class.getDeclaredFields()) {
|
||||
KjbPropertyValue annotation = field.getAnnotation(KjbPropertyValue.class);
|
||||
if (annotation != null) {
|
||||
String key = annotation.key();
|
||||
String defaultValue = annotation.defaultValue();
|
||||
String description = annotation.description();
|
||||
System.out.printf("| %s | %s | %s |%n", key, defaultValue, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.eactive.ext.kjb.common;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* KjbProperty 싱글톤 홀더.
|
||||
*
|
||||
* <p>모든 곳에서 {@code KjbPropertyHolder.get()}으로 현재 KjbProperty에 접근합니다.
|
||||
* eapim-admin에서 초기화 시 {@code initialize()}를 호출하고,
|
||||
* MonitoringContext.refresh() 시 {@code reload()}를 호출하여 값을 갱신합니다.</p>
|
||||
*
|
||||
* <p>사용 예시:</p>
|
||||
* <pre>
|
||||
* // 값 접근
|
||||
* String url = KjbPropertyHolder.get().getUmsHostUrl();
|
||||
*
|
||||
* // 초기화 (eapim-admin에서)
|
||||
* KjbPropertyInjector injector = new KjbPropertyInjector(service, "Monitoring");
|
||||
* KjbPropertyHolder.initialize(injector::inject);
|
||||
*
|
||||
* // reload (MonitoringContext.refresh() 시)
|
||||
* KjbPropertyHolder.reload();
|
||||
*
|
||||
* // 테스트용
|
||||
* KjbPropertyHolder.setForTest(mockProperty);
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
public class KjbPropertyHolder {
|
||||
|
||||
private static volatile KjbProperty instance = new KjbProperty();
|
||||
private static volatile Function<KjbProperty, KjbProperty> injector;
|
||||
|
||||
private KjbPropertyHolder() {
|
||||
// 유틸리티 클래스
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 KjbProperty 인스턴스를 반환합니다.
|
||||
*/
|
||||
public static KjbProperty get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 초기화 함수를 등록하고 최초 로딩을 수행합니다.
|
||||
* eapim-admin 부팅 시 MonitoringContextImpl.init()에서 호출됩니다.
|
||||
*
|
||||
* @param injectorFn KjbProperty를 DB에서 로딩하는 함수 (KjbPropertyInjector::inject)
|
||||
*/
|
||||
public static void initialize(Function<KjbProperty, KjbProperty> injectorFn) {
|
||||
injector = injectorFn;
|
||||
reload();
|
||||
log.info("KjbPropertyHolder 초기화 완료");
|
||||
}
|
||||
|
||||
/**
|
||||
* DB에서 프로퍼티를 다시 로딩합니다.
|
||||
* MonitoringContext.refresh() 호출 시 함께 호출됩니다.
|
||||
*/
|
||||
public static void reload() {
|
||||
if (injector != null) {
|
||||
try {
|
||||
instance = injector.apply(new KjbProperty());
|
||||
log.info("KjbProperty reload 완료");
|
||||
} catch (Exception e) {
|
||||
log.error("KjbProperty reload 실패: {}", e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
log.debug("KjbPropertyHolder: injector가 설정되지 않음 (테스트 환경일 수 있음)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트용 - 직접 인스턴스를 설정합니다.
|
||||
*/
|
||||
public static void setForTest(KjbProperty testProperty) {
|
||||
instance = testProperty;
|
||||
log.debug("KjbProperty 테스트 인스턴스 설정");
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트용 - 기본값으로 초기화합니다.
|
||||
*/
|
||||
public static void resetForTest() {
|
||||
instance = new KjbProperty();
|
||||
injector = null;
|
||||
log.debug("KjbPropertyHolder 테스트 초기화");
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,5 @@ import java.lang.annotation.Target;
|
||||
public @interface KjbPropertyValue {
|
||||
String key();
|
||||
String defaultValue() default "";
|
||||
String description() default "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
import com.eactive.ext.kjb.common.KjbObpException;
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.common.KjbPropertyHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@Slf4j
|
||||
public class KjbObpModule {
|
||||
private static final String FAKE_PARTNER_CODE = "999999-99";
|
||||
|
||||
private static volatile KjbObpModule instance;
|
||||
|
||||
private KjbObpModule() {
|
||||
// 싱글톤
|
||||
}
|
||||
|
||||
public static KjbObpModule getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (KjbObpModule.class) {
|
||||
if (instance == null) {
|
||||
instance = new KjbObpModule();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static KjbProperty getProperty() {
|
||||
return KjbPropertyHolder.get();
|
||||
}
|
||||
|
||||
private ObpClient getClient() {
|
||||
return ObpClient.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 사업자등록번호로 partnerCode 조회
|
||||
* @param bizNo 사업자등록번호 (숫자 외 문자 자동 제거)
|
||||
* @return partnerCode
|
||||
* @throws KjbObpException 조회 실패 시
|
||||
*/
|
||||
public String queryPartnerCode(String bizNo) throws KjbObpException {
|
||||
bizNo = ObpUtil.onlyDigit(bizNo);
|
||||
|
||||
if (StringUtils.isEmpty(bizNo)) {
|
||||
throw new IllegalArgumentException("BizNo is empty.");
|
||||
}
|
||||
|
||||
if (bizNo.length() != 10) {
|
||||
throw new IllegalArgumentException("BizNo must be 10 digits. (input: " + bizNo + ")");
|
||||
}
|
||||
|
||||
ObpClient client = getClient();
|
||||
|
||||
// 가상모드: URL 미설정 시 가상 파트너코드 반환
|
||||
if (!client.isRealMode()) {
|
||||
log.info("[OBP] 가상모드 - 가상 partnerCode 반환: {}", FAKE_PARTNER_CODE);
|
||||
return FAKE_PARTNER_CODE;
|
||||
}
|
||||
|
||||
String path = String.format(getProperty().getObpUrlOrganizationFmt(), bizNo);
|
||||
log.debug("[OBP] queryPartnerCode - bizNo: {}, path: {}", bizNo, path);
|
||||
|
||||
ObpResponse response = client.get(path);
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
log.warn("[OBP] queryPartnerCode failed - status: {}, body: {}", response.getStatus(), response.getBody());
|
||||
throw new KjbObpException(response.getStatus(), "OBP 조회 실패: " + response.getBody());
|
||||
}
|
||||
|
||||
ObpOrganization org = ObpOrganization.fromResponse(response);
|
||||
|
||||
if (org == null) {
|
||||
throw new KjbObpException("OBP 응답 파싱 실패");
|
||||
}
|
||||
|
||||
if (!org.hasPartnerCode()) {
|
||||
throw new KjbObpException("partnerCode가 없습니다. bizNo: " + bizNo);
|
||||
}
|
||||
|
||||
return org.getPartnerCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.common.KjbPropertyHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
|
||||
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.io.entity.EntityUtils;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class ObpClient {
|
||||
private static volatile ObpClient instance;
|
||||
|
||||
private ObpClient() {
|
||||
// 싱글톤
|
||||
}
|
||||
|
||||
public static ObpClient getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (ObpClient.class) {
|
||||
if (instance == null) {
|
||||
instance = new ObpClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static KjbProperty getProperty() {
|
||||
return KjbPropertyHolder.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 실제 모드 여부 (URL이 설정되어 있는지 확인)
|
||||
*/
|
||||
public boolean isRealMode() {
|
||||
return StringUtils.isNotEmpty(getProperty().getObpUrl());
|
||||
}
|
||||
|
||||
private RequestConfig createRequestConfig() {
|
||||
KjbProperty prop = getProperty();
|
||||
return RequestConfig.custom()
|
||||
.setConnectTimeout(Timeout.ofSeconds(prop.getObpConnectionTimeout()))
|
||||
.setResponseTimeout(Timeout.ofSeconds(prop.getObpResponseTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 요청
|
||||
* @param path API 경로 (예: /api/customer/...)
|
||||
* @return ObpResponse
|
||||
*/
|
||||
public ObpResponse get(String path) {
|
||||
return get(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 요청 (추가 헤더 포함)
|
||||
* @param path API 경로
|
||||
* @param additionalHeaders 추가 헤더
|
||||
* @return ObpResponse
|
||||
*/
|
||||
public ObpResponse get(String path, Map<String, String> additionalHeaders) {
|
||||
String url = getProperty().getObpUrl() + path;
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
applyDefaultHeaders(httpGet);
|
||||
applyAdditionalHeaders(httpGet, additionalHeaders);
|
||||
httpGet.setConfig(createRequestConfig());
|
||||
|
||||
return execute(httpGet);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 요청 (JSON body)
|
||||
* @param path API 경로
|
||||
* @param jsonBody JSON 문자열
|
||||
* @return ObpResponse
|
||||
*/
|
||||
public ObpResponse post(String path, String jsonBody) {
|
||||
return post(path, jsonBody, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 요청 (JSON body, 추가 헤더 포함)
|
||||
* @param path API 경로
|
||||
* @param jsonBody JSON 문자열
|
||||
* @param additionalHeaders 추가 헤더
|
||||
* @return ObpResponse
|
||||
*/
|
||||
public ObpResponse post(String path, String jsonBody, Map<String, String> additionalHeaders) {
|
||||
String url = getProperty().getObpUrl() + path;
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
applyDefaultHeaders(httpPost);
|
||||
applyAdditionalHeaders(httpPost, additionalHeaders);
|
||||
httpPost.setConfig(createRequestConfig());
|
||||
|
||||
if (StringUtils.isNotEmpty(jsonBody)) {
|
||||
httpPost.setEntity(EntityBuilder.create()
|
||||
.setText(jsonBody)
|
||||
.setContentType(ContentType.APPLICATION_JSON)
|
||||
.build());
|
||||
}
|
||||
|
||||
return execute(httpPost);
|
||||
}
|
||||
|
||||
private void applyDefaultHeaders(HttpUriRequestBase request) {
|
||||
KjbProperty prop = getProperty();
|
||||
request.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
request.setHeader(prop.getObpTrustSystemKey(), prop.getObpTrustSystemValue());
|
||||
request.setHeader(prop.getObpPartnerCodeKey(), prop.getObpPartnerCodeValue());
|
||||
}
|
||||
|
||||
private void applyAdditionalHeaders(HttpUriRequestBase request, Map<String, String> additionalHeaders) {
|
||||
if (additionalHeaders != null) {
|
||||
additionalHeaders.forEach(request::setHeader);
|
||||
}
|
||||
}
|
||||
|
||||
private ObpResponse execute(HttpUriRequestBase request) {
|
||||
if (!isRealMode()) {
|
||||
log.warn("[OBP] URL 미설정으로 실제 호출하지 않음. 요청: {} {}", request.getMethod(), request.getRequestUri());
|
||||
ObpResponse mockResponse = new ObpResponse();
|
||||
mockResponse.setStatus(200);
|
||||
mockResponse.setBody("{}");
|
||||
return mockResponse;
|
||||
}
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||
log.debug("[OBP] 요청: {} {}", request.getMethod(), request.getRequestUri());
|
||||
|
||||
Future<ObpResponse> future = executor.submit(() ->
|
||||
httpClient.execute(request, response -> {
|
||||
ObpResponse obpResponse = new ObpResponse();
|
||||
obpResponse.setStatus(response.getCode());
|
||||
obpResponse.setBody(EntityUtils.toString(response.getEntity(), "UTF-8"));
|
||||
|
||||
Arrays.asList(response.getHeaders()).forEach(header ->
|
||||
obpResponse.getHeaders().put(header.getName(), header.getValue()));
|
||||
|
||||
return obpResponse;
|
||||
})
|
||||
);
|
||||
|
||||
ObpResponse response = future.get(getProperty().getObpTimeout(), TimeUnit.SECONDS);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[OBP] 응답: status={}, body={}", response.getStatus(), response.getBody());
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException | java.io.IOException e) {
|
||||
log.error("[OBP] 호출 실패: {} {}", request.getMethod(), request.getRequestUri(), e);
|
||||
ObpResponse errorResponse = new ObpResponse();
|
||||
errorResponse.setStatus(-1);
|
||||
errorResponse.setBody(e.getMessage());
|
||||
return errorResponse;
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* OBP Organization 조회 응답
|
||||
* - 필수 필드만 명시적으로 선언하고, 나머지는 rawJson으로 보관하여 유연성 확보
|
||||
*/
|
||||
@Data
|
||||
public class ObpOrganization {
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
// 핵심 필드
|
||||
@SerializedName("partnerCode")
|
||||
private String partnerCode;
|
||||
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("state")
|
||||
private String state;
|
||||
|
||||
@SerializedName("status")
|
||||
private String status;
|
||||
|
||||
@SerializedName("businessManRegistrationNo")
|
||||
private String businessManRegistrationNo;
|
||||
|
||||
@SerializedName("corporateRegistrationNo")
|
||||
private String corporateRegistrationNo;
|
||||
|
||||
@SerializedName("representativeName")
|
||||
private String representativeName;
|
||||
|
||||
// 원본 JSON (추가 필드 접근용
|
||||
private transient JsonObject rawJson;
|
||||
|
||||
/**
|
||||
* JSON 문자열에서 파싱
|
||||
*/
|
||||
public static ObpOrganization fromJson(String json) {
|
||||
if (json == null || json.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ObpOrganization org = gson.fromJson(json, ObpOrganization.class);
|
||||
org.rawJson = new JsonParser().parse(json).getAsJsonObject();
|
||||
return org;
|
||||
}
|
||||
|
||||
/**
|
||||
* ObpResponse에서 파싱
|
||||
*/
|
||||
public static ObpOrganization fromResponse(ObpResponse response) {
|
||||
if (response == null || response.getStatus() != 200) {
|
||||
return null;
|
||||
}
|
||||
return fromJson(response.getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* 원본 JSON에서 추가 필드 조회
|
||||
* @param fieldName 필드명 (예: "englishName", "description")
|
||||
* @return 필드 값 (없으면 null)
|
||||
*/
|
||||
public String getField(String fieldName) {
|
||||
if (rawJson == null || !rawJson.has(fieldName) || rawJson.get(fieldName).isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
return rawJson.get(fieldName).getAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 원본 JSON에서 중첩 필드 조회
|
||||
* @param path 경로 (예: "type.name", "type.parent.name")
|
||||
* @return 필드 값 (없으면 null)
|
||||
*/
|
||||
public String getNestedField(String path) {
|
||||
if (rawJson == null || path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] parts = path.split("\\.");
|
||||
JsonObject current = rawJson;
|
||||
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
if (!current.has(parts[i]) || current.get(parts[i]).isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
current = current.getAsJsonObject(parts[i]);
|
||||
}
|
||||
|
||||
String lastField = parts[parts.length - 1];
|
||||
if (!current.has(lastField) || current.get(lastField).isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return current.get(lastField).getAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 원본 JSON 객체 반환
|
||||
*/
|
||||
public JsonObject getRawJson() {
|
||||
return rawJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* partnerCode 유효성 확인
|
||||
*/
|
||||
public boolean hasPartnerCode() {
|
||||
return partnerCode != null && !partnerCode.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
public class ObpRequest {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ObpResponse {
|
||||
private String body;
|
||||
private Map<String, String> headers = new HashMap<>();
|
||||
private int status;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.eactive.ext.kjb.obp;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class ObpUtil {
|
||||
static String onlyDigit(String str) {
|
||||
return str == null ? "" :
|
||||
str.chars().filter(Character::isDigit).mapToObj(c -> String.valueOf((char)c)).collect(Collectors.joining());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.eactive.ext.kjb.sso;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum ExtendedInfo {
|
||||
DATEOFBIRTH("생년월일 + 성별"),
|
||||
CELLPHONENO("핸드폰"),
|
||||
UPPERTCODE("모점점번코드"),
|
||||
PARTCODE("소속부점코드"),
|
||||
LEGACYDEPTCODE("인사부서코드"),
|
||||
LEGACYDEPTNAME("인사부서명"),
|
||||
LEGACYPOSITIONCODE("인사직위코드"),
|
||||
LEGACYPOSITIONNAME("인사직위명"),
|
||||
LEGACYFUNCTIONCODE("인사직책코드"),
|
||||
LEGACYFUNCTIONNAME("인사직책명"),
|
||||
LEGACYROLLCODE("인사직무코드"),
|
||||
LEGACYROLLNAME("인사직무명"),
|
||||
LEGACYOFCLEVELCODE("인사직급코드"),
|
||||
LEGACYOFCLEVELNAME("인사직급명"),
|
||||
PART_GBN("본부(1), 영업점(2)"),
|
||||
STATUS("재직(1),휴가(2),퇴직(9)"),
|
||||
CEF_APPOINTDATE("최종방령일"),
|
||||
OTHERDEPTCODE("겸직/파견 부서코드"),
|
||||
OTHERDEPTNAME("겸직/파견 부서명"),
|
||||
OTHERPOSITIONCODE("겸직/파견 직위코드"),
|
||||
OTHERFIUNCTIONCODE("겸직/파견 직책코드"),
|
||||
OTHERROLLCODE("겸직/파견 직무코드"),
|
||||
OTHEROFCLEVELCODE("겸직/파견 직급코드")
|
||||
;
|
||||
|
||||
|
||||
@Getter
|
||||
private final String description;
|
||||
|
||||
ExtendedInfo(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
package com.eactive.ext.kjb.sso;
|
||||
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.common.KjbPropertyHolder;
|
||||
import com.initech.eam.api.*;
|
||||
import com.initech.eam.base.APIException;
|
||||
import com.initech.eam.base.EmptyResultException;
|
||||
import com.initech.eam.nls.CookieManager;
|
||||
import com.initech.eam.smartenforcer.SECode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
@Slf4j
|
||||
public class KjbSsoModule {
|
||||
private static volatile KjbSsoModule instance;
|
||||
|
||||
private final Vector<String> PROVIDER_LIST = new Vector<String>();
|
||||
private final int COOKIE_SESSTION_TIME_OUT = 3000000;
|
||||
|
||||
// 인증 타입 (ID/PW 방식 : 1, 인증서 : 3)
|
||||
private final String TOA = "1";
|
||||
private final String SSO_DOMAIN = ".kjbank.com";
|
||||
private final String COOKIE_PADDING = "_V42";
|
||||
|
||||
private static final int timeout = 15000;
|
||||
|
||||
private KjbSsoModule() {
|
||||
CookieManager.setEncStatus(true);
|
||||
SECode.setCookiePadding(COOKIE_PADDING);
|
||||
}
|
||||
|
||||
public static KjbSsoModule getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (KjbSsoModule.class) {
|
||||
if (instance == null) {
|
||||
instance = new KjbSsoModule();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static KjbProperty getProperty() {
|
||||
return KjbPropertyHolder.get();
|
||||
}
|
||||
|
||||
private String getServiceName() {
|
||||
return getProperty().getSsoServiceName();
|
||||
}
|
||||
|
||||
public String getAscpUrl() {
|
||||
KjbProperty prop = getProperty();
|
||||
return prop.getUrl() + prop.getSsoAscpUri();
|
||||
}
|
||||
|
||||
private String getNlsUrl() {
|
||||
return "http://" + getProperty().getSsoDomain();
|
||||
}
|
||||
|
||||
private String getNlsPort() {
|
||||
return String.valueOf(getProperty().getSsoNlsPort());
|
||||
}
|
||||
|
||||
private String getNlsLoginUrl() {
|
||||
return getNlsUrl() + ":" + getNlsPort() + "/nls3/clientLogin.jsp";
|
||||
}
|
||||
|
||||
private String getNlsLogoutUrl() {
|
||||
return getNlsUrl() + ":" + getNlsPort() + "/nls3/NCLogout.jsp";
|
||||
}
|
||||
|
||||
private String getNlsErrorUrl() {
|
||||
return getNlsUrl() + ":" + getNlsPort() + "/nls3/error.jsp";
|
||||
}
|
||||
|
||||
private String getNdUrl1() {
|
||||
return "http://" + getProperty().getSsoDomain() + ":5480";
|
||||
}
|
||||
|
||||
public Vector<String> getProviderList() {
|
||||
Vector<String> list = new Vector<>();
|
||||
list.add(getProperty().getSsoDomain());
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public NXContext getContext() {
|
||||
NXContext context = null;
|
||||
try {
|
||||
List<String> serverurlList = new ArrayList<>();
|
||||
serverurlList.add(getNdUrl1());
|
||||
context = new NXContext(serverurlList);
|
||||
CookieManager.setEncStatus(true);
|
||||
SECode.setCookiePadding(COOKIE_PADDING);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("getContext", e);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 통합 SSO ID 조회
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String getSsoId(HttpServletRequest request) {
|
||||
String sso_id = null;
|
||||
sso_id = CookieManager.getCookieValue(SECode.USER_ID, request);
|
||||
return sso_id;
|
||||
}
|
||||
|
||||
public String getSystemAccount(String sso_id) {
|
||||
NXContext context = null;
|
||||
NXUserAPI userAPI = null;
|
||||
String retValue = null;
|
||||
|
||||
try {
|
||||
context = getContext();
|
||||
userAPI = new NXUserAPI(context);
|
||||
String serviceName = getServiceName();
|
||||
log.info("##############################################");
|
||||
log.info("sso_id 2: "+sso_id);
|
||||
log.info("SERVICE_NAME : "+ serviceName);
|
||||
log.info("##############################################");
|
||||
NXAccount account = userAPI.getUserAccount(sso_id, serviceName);
|
||||
log.info(account.toString());
|
||||
retValue = account.getAccountName();
|
||||
log.info("retValue = " + retValue);
|
||||
} catch (Exception e) {
|
||||
log.error("KjbSsoModule Exception", e);
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 통합 SSO 로그인페이지 이동
|
||||
* @param response
|
||||
* @param uurl
|
||||
* @throws Exception
|
||||
*/
|
||||
public void goLoginPage(HttpServletResponse response, String uurl)
|
||||
throws Exception {
|
||||
CookieManager.addCookie(SECode.USER_URL, uurl, SSO_DOMAIN, response);
|
||||
CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response);
|
||||
response.sendRedirect(getNlsLoginUrl() + "?UURL=" + uurl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 통합 SSO 로그인페이지 이동
|
||||
* @param response
|
||||
* @throws Exception
|
||||
*/
|
||||
public void goLoginPage(HttpServletResponse response) throws Exception {
|
||||
CookieManager.addCookie(SECode.USER_URL, getAscpUrl(), SSO_DOMAIN, response);
|
||||
CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response);
|
||||
response.sendRedirect(getNlsLoginUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* 통합인증 세션을 체크 하기 위하여 사용되는 API
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
public String getEamSessionCheck(HttpServletRequest request, HttpServletResponse response) {
|
||||
String retCode = "";
|
||||
try {
|
||||
retCode = CookieManager.verifyNexessCookie(request, response, 10, COOKIE_SESSTION_TIME_OUT, getProviderList());
|
||||
} catch(Exception npe) {
|
||||
log.warn("getEamSessionCheck", npe);
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* ND API를 사용해서 쿠키검증하는것(현재 표준에서는 사용안함, 근데 해도 되기는 함)
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
public String getEamSessionCheck2(HttpServletRequest request, HttpServletResponse response) {
|
||||
String retCode = "";
|
||||
try {
|
||||
NXContext ctx = getContext();
|
||||
NXNLSAPI nxNLSAPI = new NXNLSAPI(ctx);
|
||||
retCode = nxNLSAPI.readNexessCookie(request, response, 0, 0);
|
||||
} catch(Exception npe) {
|
||||
log.error("KjbSsoModule-getEamSessionCheck2 Exception", npe);
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* SSO 에러페이지 URL
|
||||
* @param response
|
||||
* @param error_code
|
||||
* @throws Exception
|
||||
*/
|
||||
public void goErrorPage(HttpServletResponse response, int error_code) throws Exception {
|
||||
CookieManager.removeNexessCookie(SSO_DOMAIN, response);
|
||||
CookieManager.addCookie(SECode.USER_URL, getAscpUrl(), SSO_DOMAIN, response);
|
||||
response.sendRedirect(getNlsErrorUrl() + "?errorCode=" + error_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 기본정보 가져오기.
|
||||
* @param userid
|
||||
* @return Properties
|
||||
*/
|
||||
public Properties getUserInfos(String userid) throws Exception {
|
||||
NXContext context = null;
|
||||
context = getContext();
|
||||
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
Properties propt = null;
|
||||
|
||||
if (userid==null || userid.length() <= 0)
|
||||
return propt;
|
||||
|
||||
try {
|
||||
NXUserInfo userInfo = userAPI.getUserInfo(userid);
|
||||
propt = new Properties();
|
||||
propt.setProperty("USERID", userInfo.getUserId());
|
||||
propt.setProperty("EMAIL", userInfo.getEmail());
|
||||
propt.setProperty("ENABLE", String.valueOf(userInfo.getEnable()));
|
||||
propt.setProperty("STARTVALID", userInfo.getStartValid());
|
||||
propt.setProperty("ENDVALID", userInfo.getEndValid());
|
||||
propt.setProperty("NAME", userInfo.getName());
|
||||
propt.setProperty("ENCPASSWD", userInfo.getEncpasswd());
|
||||
propt.setProperty("LASTPASSWDCHANGE", userInfo.getLastpasswdchange());
|
||||
propt.setProperty("LastLoginIP", userInfo.getLastLoginIp());
|
||||
propt.setProperty("LastLoginTime", userInfo.getLastLoginTime());
|
||||
propt.setProperty("LastLoginAuthLevel", userInfo.getLastLoginAuthLevel());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("KjbSsoModule-getUserInfos Exception", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return propt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자의 기본정보 중에서 입력된 키 값만 가지고 온다.
|
||||
* @param userid
|
||||
* @param key
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String getUserInfo(String userid, String key) throws Exception {
|
||||
if(userid==null|| userid.isEmpty()) return null;
|
||||
|
||||
String userInfo = "";
|
||||
|
||||
try {
|
||||
Properties propt = getUserInfos(userid);
|
||||
userInfo = propt.getProperty(key);
|
||||
} catch (Exception e) {
|
||||
log.error("KjbSsoModule-getUserInfos Exception", e);
|
||||
throw e;
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 확장정보 조회
|
||||
* return : Properties
|
||||
* 사용자가 존재하지 않거나 확장필드가 없다면 return null
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Properties getUserExFields(String userid) throws Exception {
|
||||
NXContext context = getContext();
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
Properties prop = null;
|
||||
NXExternalFieldSet nxefs = null;
|
||||
|
||||
try {
|
||||
nxefs = userAPI.getUserExternalFields(userid);
|
||||
prop = new Properties();
|
||||
|
||||
if (nxefs != null) {
|
||||
Iterator<?> iter = nxefs.iterator();
|
||||
while(iter.hasNext()) {
|
||||
NXExternalField nxef = (NXExternalField) iter.next();
|
||||
if(nxef.getName().equals("PASSINIT")){
|
||||
String sPassintVal = (String) nxef.getValue();
|
||||
prop.setProperty(nxef.getName(), sPassintVal.equals("") ? "0" : sPassintVal);
|
||||
}
|
||||
else
|
||||
prop.setProperty(nxef.getName(), (String) nxef.getValue());
|
||||
//System.out.println("확장 필드 " + nxef.getName() + " : " + nxef.getValue());
|
||||
}
|
||||
} else {
|
||||
// prop is null
|
||||
log.debug("KjbSsoModule-getUserExFields property is null");
|
||||
}
|
||||
} catch (EmptyResultException e) {
|
||||
// 사용자가 존재하지 않거나 확장필드가 없음
|
||||
log.warn("사용자가 존재하지 않거나 확장필드가 없음", e);
|
||||
} catch (APIException e) {
|
||||
log.warn("SSO-APIException", e);
|
||||
throw e;
|
||||
//e.printStackTrace();
|
||||
}
|
||||
//System.out.println("getUserExFields:[" + prop + "]");
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자의 특정 확장 필드 정보 조회
|
||||
* return : String
|
||||
* 사용자가 존재하지 않거나 확장필드가 없다면 return null
|
||||
*/
|
||||
public String getUserExField(String userid, String exName)
|
||||
throws Exception {
|
||||
NXContext context = getContext();
|
||||
NXUserAPI userAPI = new NXUserAPI(context);
|
||||
NXExternalField nxef = null;
|
||||
String returnValue = null;
|
||||
|
||||
try {
|
||||
log.debug("KjbSsoModule-getUserExField userid : {}", userid);
|
||||
nxef = userAPI.getUserExternalField(userid, exName);
|
||||
log.debug("KjbSsoModule-getUserExField nxef === {}", nxef.getValue());
|
||||
returnValue = (String) nxef.getValue();
|
||||
} catch (EmptyResultException e) {
|
||||
// 사용자가 존재하지 않거나 확장필드가 없음
|
||||
log.warn("사용자가 존재하지 않거나 확장필드가 없음", e);
|
||||
} catch (Exception e) {
|
||||
log.error("KjbSsoModule-getUserExField Exception", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,10 @@ import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.eai.EaiBatchInterface;
|
||||
import com.eactive.ext.kjb.eai.EaiBatchMessage;
|
||||
import com.eactive.ext.kjb.eai.KjbEaiBatchModule;
|
||||
import com.eactive.ext.kjb.safedb.KjbSafedbWrapper;
|
||||
//import com.eactive.ext.kjb.safedb.KjbSafedbWrapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -50,7 +51,8 @@ public class EmailJob {
|
||||
this.messageRequest = messageRequest;
|
||||
this.prop = prop;
|
||||
|
||||
String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(now) + ".dat";
|
||||
// String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(now) + ".dat";
|
||||
String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(now) + ".dat";
|
||||
this.eaiFilePath = Paths.get(prop.getUmsEaiBatchSendDir(), filename);
|
||||
this.backupFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename);
|
||||
this.failedFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename + ".failed");
|
||||
@@ -228,30 +230,39 @@ public class EmailJob {
|
||||
|
||||
public String generateJSON(boolean isPretty) {
|
||||
validateMessageRequest(messageRequest, true, true);
|
||||
KjbSafedbWrapper safedb = KjbSafedbWrapper.getInstance();
|
||||
// KjbSafedbWrapper safedb = KjbSafedbWrapper.getInstance();
|
||||
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("MAKE_DATE", DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()));
|
||||
jsonObject.addProperty("MAKE_SEQNO", DateTimeFormatter.ofPattern("HHmmssSSS").format(LocalDateTime.now()));
|
||||
jsonObject.addProperty("CAMP_ID", messageRequest.getServiceId()); // 전자금융 고객이메일 발송 업무ID (SERVICE_ID)
|
||||
jsonObject.addProperty("ID", messageRequest.getUmsUid()); // 고객 ID
|
||||
jsonObject.addProperty("EMAIL", safedb.encryptNotRnnoString(messageRequest.getEmail()));
|
||||
// jsonObject.addProperty("EMAIL", safedb.encryptNotRnnoString(messageRequest.getEmail()));
|
||||
jsonObject.addProperty("EMAIL", 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());
|
||||
});
|
||||
String message = messageRequest.getMessage();
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
log.debug("Template string to json: {}", message);
|
||||
if (StringUtils.isNotEmpty(message)) {
|
||||
JsonObject contentJSon = gson.fromJson(message, JsonObject.class);
|
||||
contentJSon.entrySet().forEach(entry -> {
|
||||
jsonObject.add(entry.getKey(), entry.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
jsonArray.add(jsonObject);
|
||||
|
||||
// jsonObject.addProperty("SUBJECT", messageRequest.getSubject());
|
||||
// jsonObject.addProperty("MESSAGE", messageRequest.getMessage());
|
||||
|
||||
String jsonString;
|
||||
if (isPretty) {
|
||||
jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(jsonObject);
|
||||
// pretty print 제외
|
||||
// jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(jsonArray);
|
||||
jsonString = new GsonBuilder().create().toJson(jsonArray);
|
||||
} else {
|
||||
jsonString = jsonObject.toString();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.common.KjbPropertyHolder;
|
||||
import com.eactive.ext.kjb.utils.ValidationUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -18,24 +19,35 @@ import java.util.function.BiConsumer;
|
||||
public class KjbEmailSendModule {
|
||||
public final static int[] ALLOW_CHANNELS = { MessageCode.Channels.EMAIL.getValue() };
|
||||
|
||||
private static KjbEmailSendModule instance = null;
|
||||
private static KjbProperty prop;
|
||||
private static volatile KjbEmailSendModule instance;
|
||||
private MessageRequestRepository repo;
|
||||
|
||||
private final MessageRequestRepository repo;
|
||||
|
||||
|
||||
public static synchronized KjbEmailSendModule getInstance(KjbProperty property,
|
||||
MessageRequestRepository messageRequestRepository) {
|
||||
|
||||
ValidationUtil.validateOrThrow(property);
|
||||
private KjbEmailSendModule() {
|
||||
// 싱글톤
|
||||
}
|
||||
|
||||
public static KjbEmailSendModule getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new KjbEmailSendModule(property, messageRequestRepository);
|
||||
synchronized (KjbEmailSendModule.class) {
|
||||
if (instance == null) {
|
||||
instance = new KjbEmailSendModule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* MessageRequestRepository 설정 (eapim-admin 초기화 시 호출)
|
||||
*/
|
||||
public void setRepository(MessageRequestRepository repository) {
|
||||
this.repo = repository;
|
||||
}
|
||||
|
||||
private static KjbProperty getProperty() {
|
||||
return KjbPropertyHolder.get();
|
||||
}
|
||||
|
||||
public static boolean isAllowChannel(MessageRequest message) {
|
||||
for (int channel : ALLOW_CHANNELS) {
|
||||
if ((message.getMessageCode().getChannels() & channel) == channel) {
|
||||
@@ -47,6 +59,8 @@ public class KjbEmailSendModule {
|
||||
|
||||
|
||||
public static void environmentCheck() {
|
||||
KjbProperty prop = getProperty();
|
||||
|
||||
if (StringUtils.isEmpty(prop.getEaiBatchUrl())) {
|
||||
log.warn("EAI_BATCH_URL 가 설정되지 않음. 실제 EAI 배치 연동 없이 동작함");
|
||||
}
|
||||
@@ -101,24 +115,13 @@ public class KjbEmailSendModule {
|
||||
log.info("KjbEmailSendModule - Environment check passed.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private KjbEmailSendModule(KjbProperty property,
|
||||
MessageRequestRepository repo) {
|
||||
this.repo = repo;
|
||||
|
||||
if (property != null && prop == null) {
|
||||
prop = property;
|
||||
}
|
||||
|
||||
environmentCheck();
|
||||
}
|
||||
|
||||
public void sendEmail(MessageRequest messageRequest) throws KjbEaiBatchException {
|
||||
String serviceId = "UNKNOWN";
|
||||
|
||||
serviceId = messageRequest.getMessageCode().getServiceId();
|
||||
messageRequest.setServiceId(serviceId);
|
||||
if (StringUtils.isEmpty(messageRequest.getServiceId())) {
|
||||
serviceId = messageRequest.getMessageCode().getServiceId();
|
||||
messageRequest.setServiceId(serviceId);
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(serviceId)) {
|
||||
throw new IllegalArgumentException("MessageRequest MessageCode serviceId is required");
|
||||
@@ -133,7 +136,7 @@ public class KjbEmailSendModule {
|
||||
repo.save(messageRequest);
|
||||
}
|
||||
|
||||
EmailJob job = EmailJob.create(prop, messageRequest, repo);
|
||||
EmailJob job = EmailJob.create(getProperty(), messageRequest, repo);
|
||||
job.sendEmail();
|
||||
|
||||
log.debug("JSON : {}", job.generateJSON(true));
|
||||
|
||||
@@ -3,13 +3,13 @@ package com.eactive.ext.kjb.ums;
|
||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import com.eactive.apim.portal.template.entity.MessageRequest;
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.common.KjbPropertyHolder;
|
||||
import com.eactive.ext.kjb.common.KjbUmsException;
|
||||
import com.eactive.ext.kjb.ums.gson.IUmsGsonObject;
|
||||
import com.eactive.ext.kjb.ums.gson.UmsRequestPayload;
|
||||
import com.eactive.ext.kjb.ums.gson.VerifyPhoneUmsTemplate;
|
||||
import com.eactive.ext.kjb.ums.gson.*;
|
||||
import com.eactive.ext.kjb.utils.JsonUtil;
|
||||
import com.eactive.ext.kjb.utils.ValidationUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -39,34 +39,42 @@ public class KjbUmsService {
|
||||
private final static String CONTENT_TYPE = "application/json; charset=utf-8";
|
||||
private final static String AUTHORIZATION_FMT = "Bearer %s";
|
||||
|
||||
private final KjbProperty property;
|
||||
private final boolean isRealMode;
|
||||
private final CloseableHttpClient httpClient;
|
||||
private final RequestConfig requestConfig;
|
||||
private static volatile KjbUmsService instance;
|
||||
|
||||
private KjbUmsService() {
|
||||
// 싱글톤
|
||||
}
|
||||
|
||||
public KjbUmsService(KjbProperty property) {
|
||||
if (property == null) {
|
||||
log.error("[KJB-UMS] 파라미터 설정 되지 않음");
|
||||
throw new IllegalArgumentException("property is null");
|
||||
public static KjbUmsService getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (KjbUmsService.class) {
|
||||
if (instance == null) {
|
||||
instance = new KjbUmsService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
isRealMode = property.getUmsHostUrl() != null && StringUtils.isNotEmpty(property.getUmsHostUrl().trim());
|
||||
private KjbProperty getProperty() {
|
||||
return KjbPropertyHolder.get();
|
||||
}
|
||||
|
||||
if (isRealMode) {
|
||||
ValidationUtil.validateOrThrow(property);
|
||||
private boolean isRealMode() {
|
||||
String url = getProperty().getUmsHostUrl();
|
||||
return url != null && StringUtils.isNotEmpty(url.trim());
|
||||
}
|
||||
|
||||
httpClient = HttpClients.createDefault();
|
||||
requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(Timeout.ofSeconds(property.getEaiBatchConnectionTimeout()))
|
||||
.setResponseTimeout(Timeout.ofSeconds(property.getEaiBatchResponseTimeout()))
|
||||
.build();
|
||||
} else {
|
||||
httpClient = HttpClients.createDefault();
|
||||
requestConfig = null;
|
||||
}
|
||||
private CloseableHttpClient createHttpClient() {
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
|
||||
this.property = property;
|
||||
private RequestConfig createRequestConfig() {
|
||||
KjbProperty prop = getProperty();
|
||||
return RequestConfig.custom()
|
||||
.setConnectTimeout(Timeout.ofSeconds(prop.getUmsConnectionTimeout()))
|
||||
.setResponseTimeout(Timeout.ofSeconds(prop.getUmsResponseTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,13 +98,10 @@ public class KjbUmsService {
|
||||
throw new IllegalArgumentException("지원하지 않는 발송 채널 - " + messageRequest.getMessageCode().toString());
|
||||
}
|
||||
|
||||
IUmsGsonObject content = null;
|
||||
content = VerifyPhoneUmsTemplate.builder().authNumber(messageRequest.getMessage()).build();
|
||||
|
||||
String umsMessageId = this.sendKakaoAlimTalk(messageRequest.getId(),
|
||||
UmsBizWorkCode.VERIFY_PHONE,
|
||||
messageRequest.getPhone(),
|
||||
content
|
||||
GsonUtil.toJsonObject(messageRequest.getMessage())
|
||||
);
|
||||
|
||||
log.info("MessageRequest sent - {}", umsMessageId);
|
||||
@@ -104,7 +109,13 @@ public class KjbUmsService {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String sendKakaoAlimTalk(String guid, UmsBizWorkCode bizWorkCode, String cpno, IUmsGsonObject content) throws KjbUmsException {
|
||||
public String sendObpMonitoring(String cpno, String message) throws KjbUmsException {
|
||||
log.info("OBP 모니터링 용 메세지 발송 - message: {}", message);
|
||||
|
||||
return this.sendKakaoAlimTalk(null, UmsBizWorkCode.MONITORING, cpno, GsonUtil.toJsonObject(ObpMonitoringUmsTemplate.builder().message(message).build()));
|
||||
}
|
||||
|
||||
public String sendKakaoAlimTalk(String guid, UmsBizWorkCode bizWorkCode, String cpno, JsonObject content) throws KjbUmsException {
|
||||
if (content == null) {
|
||||
throw new IllegalArgumentException("content is null");
|
||||
}
|
||||
@@ -137,13 +148,14 @@ public class KjbUmsService {
|
||||
}
|
||||
|
||||
private UmsCallResult call(String url, UmsRequestPayload requestPayload) throws KjbUmsException {
|
||||
KjbProperty prop = getProperty();
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(requestPayload);
|
||||
|
||||
HttpPost httpPost = new HttpPost(property.getUmsHostUrl() + url);
|
||||
HttpPost httpPost = new HttpPost(prop.getUmsHostUrl() + url);
|
||||
httpPost.setHeader("Content-Type", CONTENT_TYPE);
|
||||
httpPost.setHeader("Authorization", String.format(AUTHORIZATION_FMT, property.getUmsApiKey()));
|
||||
httpPost.setHeader("Authorization", String.format(AUTHORIZATION_FMT, prop.getUmsApiKey()));
|
||||
httpPost.setEntity(EntityBuilder.create().setText(json).setContentType(ContentType.APPLICATION_JSON).build());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -156,52 +168,54 @@ public class KjbUmsService {
|
||||
}
|
||||
}
|
||||
|
||||
httpPost.setConfig(requestConfig);
|
||||
httpPost.setConfig(createRequestConfig());
|
||||
|
||||
if (isRealMode) {
|
||||
Future<UmsCallResult> future = executor.submit(() -> {
|
||||
return httpClient.execute(httpPost, res -> {
|
||||
try {
|
||||
UmsCallResult result;
|
||||
String body = EntityUtils.toString(res.getEntity());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Response - {}", body);
|
||||
}
|
||||
result = gson.fromJson(body, UmsCallResult.class);
|
||||
result.setUmsMessageId(requestPayload.getMessageIdentityNo());
|
||||
result.setSuccess(true);
|
||||
return result;
|
||||
} catch (JsonSyntaxException e) {
|
||||
log.error("UMS Call error(JSON Syntax)", e);
|
||||
return UmsCallResult.builder()
|
||||
.umsMessageId(requestPayload.getMessageIdentityNo())
|
||||
.isSuccess(false)
|
||||
.throwable(e)
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
log.error("UMS Call error", e);
|
||||
return UmsCallResult.builder()
|
||||
.umsMessageId(requestPayload.getMessageIdentityNo())
|
||||
.isSuccess(false)
|
||||
.throwable(e)
|
||||
.build();
|
||||
} finally {
|
||||
log.debug("Response status - {}", res.getCode());
|
||||
if (isRealMode()) {
|
||||
try (CloseableHttpClient httpClient = createHttpClient()) {
|
||||
Future<UmsCallResult> future = executor.submit(() -> {
|
||||
return httpClient.execute(httpPost, res -> {
|
||||
try {
|
||||
UmsCallResult result;
|
||||
String body = EntityUtils.toString(res.getEntity());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Response - {}", body);
|
||||
}
|
||||
result = gson.fromJson(body, UmsCallResult.class);
|
||||
result.setUmsMessageId(requestPayload.getMessageIdentityNo());
|
||||
result.setSuccess(true);
|
||||
return result;
|
||||
} catch (JsonSyntaxException e) {
|
||||
log.error("UMS Call error(JSON Syntax)", e);
|
||||
return UmsCallResult.builder()
|
||||
.umsMessageId(requestPayload.getMessageIdentityNo())
|
||||
.isSuccess(false)
|
||||
.throwable(e)
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
log.error("UMS Call error", e);
|
||||
return UmsCallResult.builder()
|
||||
.umsMessageId(requestPayload.getMessageIdentityNo())
|
||||
.isSuccess(false)
|
||||
.throwable(e)
|
||||
.build();
|
||||
} finally {
|
||||
log.debug("Response status - {}", res.getCode());
|
||||
|
||||
if (res.getCode() != 200) {
|
||||
Arrays.asList(res.getHeaders()).forEach(o -> {
|
||||
log.warn("[Header] {}: {}", o.getName(), o.getValue());
|
||||
});
|
||||
if (res.getCode() != 200) {
|
||||
Arrays.asList(res.getHeaders()).forEach(o -> {
|
||||
log.warn("[Header] {}: {}", o.getName(), o.getValue());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
return future.get(property.getUmsTimeout(), TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
log.error("EAI Batch call exception", e);
|
||||
throw new KjbUmsException("EAI Ums call failed", e);
|
||||
return future.get(prop.getUmsTimeout(), TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException | IOException e) {
|
||||
log.error("UMS call exception", e);
|
||||
throw new KjbUmsException("UMS call failed", e);
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
} else {
|
||||
log.warn("UMS URL 미지정으로 실제 호출을 진행하지 않음.");
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.eactive.ext.kjb.ums.gson;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
public class GsonUtil {
|
||||
/** 한 번만 생성해 두고 재사용 */
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting() // 필요 시 포맷 옵션
|
||||
.create();
|
||||
|
||||
private GsonUtil() {
|
||||
/* 인스턴스 생성 금지 */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* 1. 객체 ↔ JSON 문자열
|
||||
* ------------------------------------------------------------------ */
|
||||
/** 객체 → JSON 문자열 */
|
||||
public static String toJson(Object src) {
|
||||
return GSON.toJson(src);
|
||||
}
|
||||
|
||||
/** JSON 문자열 → 객체 */
|
||||
public static <T> T fromJson(String json, Class<T> clazz) {
|
||||
return GSON.fromJson(json, clazz);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* 2. 객체 ↔ JsonElement
|
||||
* ------------------------------------------------------------------ */
|
||||
/** 객체 → JsonElement (Gson 내부 표현) */
|
||||
public static JsonElement toJsonElement(Object src) {
|
||||
return GSON.toJsonTree(src);
|
||||
}
|
||||
|
||||
/** JsonElement → 객체 */
|
||||
public static <T> T fromJsonElement(JsonElement json, Class<T> clazz) {
|
||||
return GSON.fromJson(json, clazz);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* 3. JSON 문자열 ↔ JsonObject
|
||||
* ------------------------------------------------------------------ */
|
||||
/** JSON 문자열 → JsonObject (정상적인 객체만 허용) */
|
||||
public static JsonObject fromJsonObject(String json) {
|
||||
JsonElement elem = GSON.fromJson(json, JsonElement.class);
|
||||
if (!elem.isJsonObject()) {
|
||||
throw new IllegalArgumentException("JSON 문자열이 JsonObject 가 아닙니다: " + json);
|
||||
}
|
||||
return elem.getAsJsonObject();
|
||||
}
|
||||
|
||||
/** JsonObject → JSON 문자열 (정렬 옵션 없이) */
|
||||
public static String toJsonString(JsonObject jsonObj) {
|
||||
return GSON.toJson(jsonObj);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* 4. JSON 문자열 ↔ List<T>
|
||||
* ------------------------------------------------------------------ */
|
||||
/** JSON 문자열 → List<T> */
|
||||
public static <T> List<T> fromJsonList(String json, Class<T> clazz) {
|
||||
// ParameterizedType 으로 List<T> 를 명시
|
||||
Type listType = new ParameterizedType() {
|
||||
@Override public Type[] getActualTypeArguments() { return new Type[]{clazz}; }
|
||||
@Override public Type getRawType() { return List.class; }
|
||||
@Override public Type getOwnerType() { return null; }
|
||||
};
|
||||
return GSON.fromJson(json, listType);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* 5. 기타 (예시: JsonArray ↔ List<T>)
|
||||
* ------------------------------------------------------------------ */
|
||||
/** JsonArray → List<T> */
|
||||
public static <T> List<T> fromJsonArray(JsonArray array, Class<T> clazz) {
|
||||
return GSON.fromJson(array, new TypeToken<List<T>>(){}.getType());
|
||||
}
|
||||
|
||||
/** List<T> → JsonArray */
|
||||
public static <T> JsonArray toJsonArray(List<T> list) {
|
||||
return GSON.toJsonTree(list).getAsJsonArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 문자열을 JsonObject 로 변환
|
||||
*
|
||||
* @param json 유효한 JSON 객체 문자열 (예: {"name":"John","age":30})
|
||||
* @return JsonObject 인스턴스
|
||||
* @throws IllegalArgumentException JSON 문자열이 객체가 아닐 경우
|
||||
*/
|
||||
public static JsonObject toJsonObject(String json) {
|
||||
// 먼저 JsonElement 로 파싱
|
||||
JsonElement element = GSON.fromJson(json, JsonElement.class);
|
||||
|
||||
// 객체인지 검사
|
||||
if (!element.isJsonObject()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Provided JSON string is not a JsonObject: " + json);
|
||||
}
|
||||
|
||||
// JsonObject 로 캐스팅 후 반환
|
||||
return element.getAsJsonObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 일반 Java 객체 → JsonObject
|
||||
*
|
||||
* @param src 변환할 객체 (Map, POJO 등)
|
||||
* @return JsonObject 인스턴스
|
||||
* @throws IllegalArgumentException 객체가 JsonObject 로 변환될 수 없을 때
|
||||
*/
|
||||
public static JsonObject toJsonObject(Object src) {
|
||||
// 객체를 JsonElement 로 변환
|
||||
JsonElement element = GSON.toJsonTree(src);
|
||||
|
||||
// 객체인지 검사 (Map, POJO 등은 JsonObject 가 됨)
|
||||
if (!element.isJsonObject()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Provided object cannot be represented as a JsonObject: "
|
||||
+ src.getClass().getName());
|
||||
}
|
||||
|
||||
return element.getAsJsonObject();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.eactive.ext.kjb.ums.gson;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class ObpMonitoringUmsTemplate implements IUmsGsonObject {
|
||||
@SerializedName("AUTH_NO")
|
||||
private String authNumber;
|
||||
@SerializedName("MOTR_EVAL_CNTN")
|
||||
private String message;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.eactive.ext.kjb.ums.gson;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -34,7 +36,7 @@ public class UmsRequestPayload {
|
||||
// MSG_BZWK_PARAM_CTNT object 메시지업무파라미터내용 4000 메시지업무코드의 템플릿에서 사용하는 변수와 변수값
|
||||
@NotNull
|
||||
@SerializedName("MSG_BZWK_PARAM_CTNT")
|
||||
private IUmsGsonObject content;
|
||||
private JsonObject content;
|
||||
|
||||
// 발송예약일시 / 14 / 실 발송 일자(yyyyMMddHHmmss)
|
||||
// SND_RESR_DTTM string 발송예약일시 14 20240418111500 O 실 발송 일자(현재시간)
|
||||
|
||||
@@ -11,11 +11,16 @@ public class KjbPropertyUtil {
|
||||
Class<?> clazz = KjbProperty.class;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sbDelete = new StringBuilder();
|
||||
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
KjbPropertyValue anno = field.getAnnotation(KjbPropertyValue.class);
|
||||
|
||||
if (anno != null) {
|
||||
sbDelete.append("DELETE FROM EMSADM.TSEAIRM24 WHERE PRPTYGROUPNAME = 'Monitoring' AND PRPTYNAME = '");
|
||||
sbDelete.append(anno.key());
|
||||
sbDelete.append("';\n");
|
||||
|
||||
sb.append("insert into EMSADM.TSEAIRM24 (PRPTYGROUPNAME, PRPTYNAME, PRPTY2VAL) values ('Monitoring', ");
|
||||
|
||||
String key = anno.key();
|
||||
@@ -27,6 +32,9 @@ public class KjbPropertyUtil {
|
||||
}
|
||||
|
||||
System.out.println(sb);
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println(sbDelete);
|
||||
}
|
||||
|
||||
private static String addQuote(String str) {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.eactive.ext.kjb.ums.test;
|
||||
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.utils.ValidationUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Slf4j
|
||||
public class KjbPropertyTest {
|
||||
|
||||
@Test
|
||||
void testKjbProperty() {
|
||||
Assumptions.assumeTrue(
|
||||
"true".equalsIgnoreCase(System.getenv("KJB_EAPIM_TEST_ENABLED")),
|
||||
"OS 환경변수 내 KJB_EAPIM_TEST_ENABLED=TRUE 설정되어 있어야 동작함");
|
||||
|
||||
|
||||
log.info("KjbProperty 테스트 시작");
|
||||
|
||||
|
||||
log.info("기본값 Validation 테스트");
|
||||
KjbProperty prop = new KjbProperty();
|
||||
ValidationUtil.validateOrThrow(prop);
|
||||
|
||||
log.info("KjbProperty 테스트 완료");
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import com.eactive.apim.portal.template.entity.MessageRequest;
|
||||
import com.eactive.ext.kjb.common.KjbEaiBatchException;
|
||||
import com.eactive.ext.kjb.common.KjbProperty;
|
||||
import com.eactive.ext.kjb.common.KjbPropertyHolder;
|
||||
import com.eactive.ext.kjb.common.KjbUmsException;
|
||||
import com.eactive.ext.kjb.ums.KjbEmailSendModule;
|
||||
import com.eactive.ext.kjb.ums.KjbUmsService;
|
||||
@@ -14,6 +15,8 @@ import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@@ -23,14 +26,16 @@ public class UmsTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
prop = new KjbProperty();
|
||||
prop = new KjbProperty();
|
||||
prop.setEaiBatchUrl("http://172.31.32.111:10230/BATAppWeb/EaiBatCall");
|
||||
prop.setUmsEaiBatchInterfaceId("UAGFF00001UIE");
|
||||
prop.setUmsEaiBatchInterfaceId("UIEFF00001UAG");
|
||||
|
||||
prop.setUmsHostUrl("http://172.31.35.144:9021");
|
||||
prop.setUmsApiKey("7cca6d58-e4f7-474d-9edd-525806bc99ff");
|
||||
|
||||
if (OsUtil.isWindows()) {
|
||||
prop.setEaiBatchUrl("");
|
||||
prop.setUmsHostUrl("");
|
||||
prop.setUmsEaiBatchSendDir("c:\\kjb-logs\\sendmail\\snd");
|
||||
prop.setUmsEaiBatchBackupDir("c:\\kjb-logs\\sendmail\\bak");
|
||||
prop.setUmsEaiBatchErrorDir("c:\\kjb-logs\\sendmail\\error");
|
||||
@@ -41,6 +46,8 @@ public class UmsTest {
|
||||
prop.setUmsEaiBatchBackupDir("/Data/eapim/portal/sendmail/bak");
|
||||
prop.setUmsEaiBatchErrorDir("/Data/eapim/portal/sendmail/error");
|
||||
}
|
||||
|
||||
KjbPropertyHolder.setForTest(prop);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -58,7 +65,7 @@ public class UmsTest {
|
||||
messageRequest.setSubject("제목 - test");
|
||||
messageRequest.setMessage("{\"ATHN_NO\"; \"369369\"}");
|
||||
|
||||
KjbUmsService umsService = new KjbUmsService(prop);
|
||||
KjbUmsService umsService = KjbUmsService.getInstance();
|
||||
try {
|
||||
boolean result = umsService.send(messageRequest);
|
||||
|
||||
@@ -71,6 +78,9 @@ public class UmsTest {
|
||||
log.info("done");
|
||||
}
|
||||
|
||||
/**
|
||||
* :eapim-admin-kjb:test --tests "com.eactive.ext.kjb.ums.test.UmsTest.testEmail"
|
||||
*/
|
||||
@Test
|
||||
public void testEmail() {
|
||||
Assumptions.assumeTrue(
|
||||
@@ -82,25 +92,71 @@ public class UmsTest {
|
||||
log.info("{}: {}", key, System.getProperty((String) key));
|
||||
});
|
||||
|
||||
KjbEmailSendModule service = KjbEmailSendModule.getInstance(prop, null);
|
||||
MessageRequest messageRequest = new MessageRequest();
|
||||
messageRequest.setId(UUID.randomUUID().toString());
|
||||
messageRequest.setMessageCode(MessageCode.USER_VERIFICATION_EMAIL);
|
||||
messageRequest.setEmail("dearmai@dearmai.net");
|
||||
messageRequest.setUmsUid(UUID.randomUUID().toString());
|
||||
messageRequest.setUsername("김광은");
|
||||
messageRequest.setSubject("제목 - test");
|
||||
messageRequest.setMessage("{\"ATHN_NO\": \"543216\"}");
|
||||
messageRequest.setServiceId("FM_APIM001");
|
||||
KjbEmailSendModule service = KjbEmailSendModule.getInstance();
|
||||
|
||||
List<MessageRequest> requestList = new ArrayList<>();
|
||||
|
||||
|
||||
log.info("#1 요청 생성 - 이메일 인증");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_VERIFICATION_EMAIL, "{\"ATHN_NO\": \"543216\"}"));
|
||||
|
||||
log.info("#2 요청 생성 - 비밀번호 초기화");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_PASSWORD_RESET, "{\"ATHN_NO\": \"new-password\"}"));
|
||||
|
||||
log.info("#3 요청 생성 - 비밀번호 변경 완료");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_PASSWORD_CHANGED, ""));
|
||||
|
||||
log.info("#4 요청 생성 - 로그인 제한");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_ACCOUNT_LOCKED, "{\"RJCT_RSN\": \"reason\"}"));
|
||||
|
||||
log.info("#5 요청 생성 - 이메일 초대");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_INVITATION,
|
||||
"{\"CRPT_NM\":\"corpName\",\"MNGR_NM\":\"managerName\",\"CUST_ID\":\"loginId\",\"RCMD_CD\":\"321654\",\"URL_ADDR\":\"https://www.naver.com/\"}"));
|
||||
|
||||
log.info("#6 요청 생성 - 이메일 초대 취소");
|
||||
requestList.add(createMessageRequest(MessageCode.USER_INVITATION_CANCELED,
|
||||
"{\"CRPT_NM\":\"corpName\",\"MNGR_NM\":\"managerName\"}"));
|
||||
|
||||
log.info("#7 요청 생성 - 법인관리자 및 법인 등록 승인");
|
||||
requestList.add(createMessageRequest(MessageCode.MANAGER_WITH_ORG_REGISTER_APPROVED, ""));
|
||||
|
||||
log.info("#8 요청 생성 - 법인관리자 및 법인 등록 거절");
|
||||
requestList.add(createMessageRequest(MessageCode.MANAGER_WITH_ORG_REGISTER_REJECTED, "{\"RJCT_RSN\": \"reason\"}"));
|
||||
|
||||
log.info("#9 요청 생성 - 앱 승인");
|
||||
requestList.add(createMessageRequest(MessageCode.APP_REGISTER_APPROVED, "{\"APP_IDNT_NM\": \"appName\"}"));
|
||||
|
||||
log.info("#10 요청 생성 - 앱 승인 거절");
|
||||
requestList.add(createMessageRequest(MessageCode.APP_REGISTER_REJECTED, "{\"RJCT_RSN\": \"reason\"}"));
|
||||
|
||||
|
||||
log.info("MessageRequest - {}", messageRequest);
|
||||
|
||||
try {
|
||||
service.sendEmail(messageRequest);
|
||||
for (int i = 0; i < requestList.size(); i++) {
|
||||
MessageRequest request = requestList.get(i);
|
||||
log.info("#{} - 메일 전송 시도 - {}", i + 1, request.getServiceId());
|
||||
service.sendEmail(request);
|
||||
}
|
||||
} catch (KjbEaiBatchException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
log.info("done");
|
||||
}
|
||||
|
||||
private MessageRequest createMessageRequest(MessageCode messageCode, String message) {
|
||||
MessageRequest messageRequest = new MessageRequest();
|
||||
messageRequest.setId(UUID.randomUUID().toString());
|
||||
messageRequest.setMessageCode(messageCode);
|
||||
messageRequest.setEmail(System.getenv().getOrDefault("KJB_TEST_EMAIL", "25W0064@kjbank.com"));
|
||||
messageRequest.setUmsUid(UUID.randomUUID().toString());
|
||||
messageRequest.setUsername("김광은");
|
||||
messageRequest.setSubject("제목 - test");
|
||||
messageRequest.setMessage(message);
|
||||
// messageRequest.setServiceId(serviceId);
|
||||
|
||||
log.info("MessageRequest - {}", messageRequest);
|
||||
|
||||
return messageRequest;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user