Commit Graph

414 Commits

Author SHA1 Message Date
curry772 1bf2c78f03 NON_DELIVERY_GROUP 기능 추가 2026-09-07 14:27:20 +09:00
curry772 1941292079 Merge branch 'feature/hsm-config-failover'
- HSM 설정 이중화(PRIMARY/SECONDARY) 및 상태 조회 API 추가
- isNotBlank -> StringUtils.isNotBlank 로 변경

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ
2026-09-03 09:03:33 +09:00
curry772 abf0de7757 Merge branch 'feature/msg-block-parse-skip'
- JsonReader: 수신 전문에 존재하는 블록을 ref 조건으로 버리지 않도록 수정
- 표준 오류응답 메시지 형식을 PropManager 에서 조회하도록 변경

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ
2026-09-03 08:58:24 +09:00
curry772 a7fde3f81e 표준 오류응답 메시지 형식을 PropManager 에서 조회하도록 변경
DefaultProcess.setResMsg() 두 곳(표준/준표준 오류응답)에 하드코딩돼 있던
String.format("[%s] %s (%s)", ...) 를 프로퍼티 기반으로 바꾼다.

- 그룹/키: DefaultProcess / std.error.msg.format
- 인자 순서: 1=오류코드, 2=오류메시지, 3=오류상세
- 기본형식: "[%s] %s"

프로퍼티는 에이전트의 ReloadPropertyCommand 로 무중단 갱신될 수 있으므로
캐시하지 않고 호출할 때마다 조회한다.

방어 두 가지를 함께 넣는다.
 - 그룹/키가 없거나 값이 공백이면 기본형식을 쓴다. 설정을 넣지 않아도 동작한다.
 - 형식이 잘못되면(%s 개수 불일치 등) String.format 이 IllegalFormatException 을
   던지는데, 하필 오류응답 경로라 여기서 예외가 나면 오류 자체를 못 내려보낸다.
   조립 실패 시 경고만 남기고 기본형식으로 되돌린다.

특정 사이트 전용이 아닌 공통 기능이다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ
2026-09-03 08:57:17 +09:00
curry772 bfec1edea2 JsonReader: 수신 전문에 존재하는 블록을 ref 조건으로 버리지 않도록 수정
상대가 오류응답을 procs_rslt_dvcd=F 로 보내면서 요청응답구분 dman_rspn_dvcd 는
요청값 S 를 그대로 에코백했다(표준은 응답 시 R). 레이아웃의 MSG 블록 조건이 !S 라
MSG 이하가 통째로 버려졌고, 그 결과

 - MAIN_MSG 가 레이아웃 기본값으로 남아 오류가 "정상처리되었습니다." 로 보고되고
 - 거래로그는 StandardMessage 재직렬화본(EAILogDAO)이라 MSG 부 이후가 통째로 누락됐다

refPath/refValue 는 "이 블록이 전문에 들어있는가" 를 판단하는 조건인데, 고정길이와
달리 JSON 은 키의 존재 자체가 답이다. OBJECT 분기에 도달했다는 것은 수신 전문에
해당 블록이 실제로 들어있다는 뜻이므로 조건으로 다시 거르지 않고, 불일치는 상대
헤더의 오류로 보고 경고만 남긴 뒤 파싱을 계속한다.

기존에 한쪽 분기의 스킵 경고가 isDebugEnabled 가드에 가려 운영 로그에 남지 않던
문제도 함께 해소된다. FlatReader 는 조건이 블록 존재 판단에 반드시 필요하므로
그대로 둔다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ
2026-09-02 17:24:59 +09:00
curry772 3c6c8d181d isNotBlank -> StringUtils.isNotBlank로 변경 2026-09-01 11:26:11 +09:00
curry772 2240a0d604 HSM 설정 이중화(PRIMARY/SECONDARY) 및 상태 조회 API 추가
HsmManager
- PKCS11_CONFIG_SECONDARY / PIN_SECONDARY 프로퍼티 추가.
  PIN_SECONDARY 미설정 시 PIN 재사용, PKCS11_CONFIG_SECONDARY 미설정 시
  후보가 1건이므로 기존과 동일하게 동작한다.
- 기동/재연결 모두 PRIMARY -> SECONDARY 순으로 시도해 최초 성공분을 사용한다.
  연결 성공 판정은 Provider 생성 + KeyStore.load + alias/getKey probe까지 포함하며,
  Security 등록 전에 검증하므로 실패해도 사용 중인 Provider/keyStore는 영향이 없다.
- 주기적 재로드에서 SECONDARY로 동작 중이면 PRIMARY 재연결을 먼저 시도해
  PRIMARY 복구 시 자동 복귀한다. PRIMARY 정상 동작 중에는 기존 keyStore 인스턴스에
  다시 load() 하여 PKCS11 세션 누적 방지 로직을 유지한다.
- PropertyChangeListener로 등록하여 HSM 프로퍼티 변경 시 다음 스케줄을 기다리지 않고
  즉시 재적용한다. HSM 통신이 호출 스레드를 막지 않도록 스케줄러 스레드에 위임하며,
  RELOAD_INTERVAL_MINUTES 변경 시 스케줄을 재등록한다.
- activeConfigName, failoverCount, lastReloadResult 등 모니터링 상태값을 노출한다.

HsmCryptoService
- 캐시 진단용 getCachedKeyInfos() / getCacheTtlMs() 추가. 키 원본은 노출하지 않는다.

/manage/hsm
- status(연결 설정/프로퍼티/alias/캐시 키), properties, keystore/aliases, cache/keys 조회와
  reload, cache/clear 실행 API 추가. PIN 류 프로퍼티는 마스킹한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013ZMr6y9kc6Y6TWN3x4gpYg
2026-09-01 10:08:02 +09:00
curry772 78606514ad newNumberSafeMapper 에 선행 0 숫자 허용 옵션 추가
상대 시스템이 0 패딩된 코드값을 따옴표 없이(=JSON 숫자로) 보내면 표준 파서가
"Invalid numeric value: Leading zeroes not allowed" 로 전문 전체를 거부한다.
전문을 못 읽고 실패하는 것보다 값을 받아들이는 쪽이 낫다고 판단해
ALLOW_LEADING_ZEROS_FOR_NUMBERS 를 켠다.

newNumberSafeMapper() 한 곳에 넣어 이를 쓰는 전 경로(JsonReader 표준전문,
JacksonUtil.OBJECT_MAPPER 를 타는 어댑터/필터)를 함께 덮는다.
WRITE_BIGDECIMAL_AS_PLAIN 을 여기 넣었던 것과 같은 이유다.

주의: 이 옵션은 00001 을 숫자 1 로 만든다(선행 0 미보존).
항목이 NUMBER/LL_NUMBER 로 선언돼 있으면 StandardItem.toTypeValue() 가
어차피 선행 0 을 깎으므로 결과가 같고, STRING/ZZ_STRING 선언이면 자릿수가
사라진다. 후자는 상대에게 따옴표를 붙여 보내달라고 요청하는 것이 정답이다.

Jackson 2.12.7 실측: 선행 0 파싱 8종, 숫자 정밀도 왕복 5종, 제어문자 정규화
조합, 과허용 여부(+1 / .5 / 무따옴표키 / 홑따옴표는 여전히 거부) 19건 PASS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Phh6MSGvgHM3rPgGUU3dzR
2026-08-28 16:41:21 +09:00
curry772 6dee34e085 제어문자 섞인 전문 대응: 수신은 정규화, 송신은 정제
수신측 - JacksonUtil.escapeControlChars() 적용 범위 확대
  JsonReader 에만 걸려 있어 TemplateCodeConvertAdapterErrorMsgHandler 등
  직접 readTree() 하는 경로가 "Illegal unquoted character ((CTRL-CHAR, code 10))"
  로 실패했다. JacksonUtil.readTree() 공용 진입점과 payload 를 파싱하는
  핸들러/필터에 적용한다.

송신측 - MessageUtil.stripControlChars() 신규
  TemplateAdapterErrorMsgHandler.render() 가 Matcher.quoteReplacement() 로만
  치환하고 있었다. 이것은 정규식 치환용이라 JSON/XML 이스케이프가 아니어서,
  값에 개행이 있으면 깨진 JSON 을 만들어 응답으로 내보냈다. 실제로 위 파싱
  오류의 원문도 상대 전문이 아니라 이 렌더 결과였다.

  템플릿이 JSON/XML 어느 쪽인지 알 수 없어 포맷별 이스케이프가 불가능하므로
  제어문자를 걸러낸다. 탭/개행/CR 은 공백으로, 나머지 제어문자와 DEL 은 제거.
  render() 의 스칼라 치환과 renderRow() 의 행 필드 치환에만 적용해
  템플릿 서식(들여쓰기/개행)은 보존한다.

검증: gradlew compileJava BUILD SUCCESSFUL.
      databind 2.12.7 런타임에서 0x00~0x1F 전수 + 로그 재현 케이스 통과.
2026-08-28 14:28:01 +09:00
curry772 f1b67df867 JsonReader: 이스케이프되지 않은 제어문자를 정규화 후 파싱
상대 시스템이 개행을 이스케이프하지 않고 그대로 보내는 경우
"Illegal unquoted character ((CTRL-CHAR, code 10))" 로 파싱이 실패했다.
파서 옵션(ALLOW_UNESCAPED_CONTROL_CHARS)으로 푸는 대신, 입력을 표준 JSON 으로
정규화하는 JacksonUtil.escapeControlChars() 를 추가하고 파서는 strict 로 유지한다.

문자열 리터럴 "안" 의 제어문자만 바꾼다. JSON 은 토큰 사이의 개행/탭을 공백으로
허용하므로 구조적 공백까지 치환하면 pretty-print 된 JSON 이 오히려 깨진다.
2026-08-28 13:17:34 +09:00
curry772 7677f23767 모니터링 타임아웃 분류 및 응답에러코드 널 안전성 수정
- EAIServiceMonitor: timeOutCodes.indexOf 판정을 '> 0' -> '>= 0' 으로 수정
  (목록 첫 번째 코드가 타임아웃이 아닌 시스템에러로 분류되던 문제)
- EAIServiceMonitor: getLogRspErrCd() null 대비 defaultString 적용, 리터럴 비교 순서 변경
- EAILogDAO, EAIFileLogger: 응답에러코드 substring(1,2) 를 널 안전한 StringUtils.substring 으로 교체
2026-08-28 10:43:54 +09:00
curry772 dd7c8a29bf newNumberSafeMapper 출력측 옵션 추가 및 ArrayNode.set 버전 호환 수정
JacksonUtil.newNumberSafeMapper() 는 USE_BIG_DECIMAL_FOR_FLOATS +
withExactBigDecimals 로 입력(파싱)측만 막고 있었다. DecimalNode 직렬화는
BigDecimal.toString() 이라 scale 이 음수이거나 adjusted exponent < -6 일 때
지수 표기가 나온다. 즉 파싱을 제대로 해도 내보낼 때 작은 소수가 깨졌다.
  0.00000012 -> 1.2E-7 , -0.0000005 -> -5E-7
WRITE_BIGDECIMAL_AS_PLAIN 을 추가해 출력측까지 보존한다.
(금액처럼 scale >= 0 인 큰 값은 원래 영향 없음. 이율/환율이 대상)

또한 JacksonUtil.setValue() 가 ArrayNode.set(int, String) 을 쓰고 있었다.
이 오버로드는 jackson-databind 2.13 부터이고, 실제 런타임은 2.12.7 이다
(2.12.7 은 set(int, JsonNode) 하나뿐). jackson-dataformat-xml:2.13.1 이
compileOnly 로 컴파일 클래스패스에만 2.13.1 을 올려 컴파일만 통과하던
상태였고, 배열 경로에 setText() 하면 운영에서 NoSuchMethodError 가 났다.
TextNode.valueOf() 로 감싸 set(int, JsonNode) 에 바인딩한다.

그 외
- TemplateCodeConvertAdapterErrorMsgHandler: 응답 JSON 왕복 지점 전환
- HttpAdapterServiceSupport, HttpClient5AdapterServiceRestAddFilter: 직렬화 지점 전환
- JsonReader: parse() 호출마다 ObjectMapper 를 새로 만들던 것을 static 싱글턴으로
  바꾸고 중복 설정 코드를 JacksonUtil 에 위임
- MessageKeyExtractor: 선언만 하고 쓰지 않는 ObjectMapper 필드 제거
- build.gradle: 미사용 jackson-dataformat-xml 제거 (common 은 Ignite 경유로 jackson 확보)

검증: gradlew compileJava BUILD SUCCESSFUL, databind 2.12.7 런타임에서
숫자 왕복 4건 + setText 배열/객체/미존재 경로 5건 전부 통과.
2026-08-28 09:26:32 +09:00
curry772 bb8a91f5f2 Merge branch 'master' of https://git.eactive.synology.me:8090/eapim/djbank/elink-online-common.git 2026-08-27 16:56:29 +09:00
curry772 0f02f4d261 Jackson Mapper 생성을 newNumberSafeMapper 이용으로 통일 2026-08-27 16:56:08 +09:00
Rinjae bc9a4caf4a generatedJavaDir 중복 등록 방지 코드 추가 - APT 재생성 오류 해결 2026-08-27 16:32:41 +09:00
curry772 82b7c779f1 feat : template 기반 AdapterErrorMessageHandler 내부오류코드별 템플릿 지정 추가
- {in 어댑터그룹명}.sys.{rspErrCd}.template 키 사용
2026-08-26 13:48:05 +09:00
curry772 65bd1ff005 거래로그의 오류 출력 부분 수정
- 수신시스템 오류응답 수신 시(RECEAIINA001) 성공건으로 변경
- 유량제어(RECEAIIRP072), 거래차단(RECEAIIRP070) 건은 오류건으로 변경
2026-08-26 11:04:33 +09:00
curry772 e9fbffa87e 거래로그의 오류 출력 부분 수정
- 오류 발생 시 AdapterErrorMessageHandler가 처리하여도 400 오류로 출력되도록 수정
- 업무 오류 발생 시 AdapterErrorMessageHandler가 처리하여도 에러 RECEAIINA001 출력
2026-08-26 09:47:02 +09:00
curry772 585a9e4520 응답 변환 시 한글 깨지는 문제
- 원인은 HTTPProcess에서 어댑터 문자셋에 따라 무조건 charset 마추어 bytes로 변경하는 문제
2026-08-18 15:36:22 +09:00
curry772 e3419e4d43 가변 url 표준전문헤더값 추출 기능 추가
- stdHeaderGroup. prefix 사용
2026-08-18 10:06:55 +09:00
curry772 f11d27e05e damo-manager.jar 배포본 내 WEB-INF/lib로 이동 2026-08-15 11:17:10 +09:00
curry772 2865c6bd03 헤더내 환경구분코드 운영 system mode 시 'P' 설정하도록 수정 2026-08-14 15:20:26 +09:00
curry772 cc016d9d81 ReflectHeaderFilter 필터 추가 2026-08-14 15:19:46 +09:00
curry772 23bdca4777 printStackTrace() 주석 처리 2026-08-13 15:07:21 +09:00
curry772 398c26537f 비동기 로그 배치 커밋 적용 2026-08-12 13:15:58 +09:00
curry772 3f75bd9b49 QueryString(parameter, formdata) 관련 Util 클래스 추가 2026-08-10 15:25:30 +09:00
curry772 51d95d8824 QueryString(parameter, formdata) 관련 Util 클래스 추가 2026-08-10 15:25:30 +09:00
curry772 5c3de18cc9 HttpAdapterServiceVirtualAccount online -> common 이동 2026-08-06 14:23:09 +09:00
curry772 a5a072fef4 Merge branch 'master' of https://git.eactive.synology.me:8090/eapim/djbank/elink-online-common.git 2026-08-06 09:30:17 +09:00
curry772 078331b3b8 In 필터 개발 : 데이터부에 상태코드 값을 응답 HTTP 상태코드에 설정하는 필터 2026-08-06 09:29:54 +09:00
Rinjae 428ab1103a damo-manager.jar 라이브러리 업데이트
- eapim-admin, eapim-online, elink-portal 공통 반영
2026-08-05 17:46:54 +09:00
curry772 4813a2ef0e 거래고유번호 맨앞에 instid 추가 2026-08-03 13:29:17 +09:00
curry772 752156b86f 거래고유번호 맨앞에 instid 추가 2026-08-03 11:38:21 +09:00
curry772 5732ddf962 checkTokenRetry 메소드 refactoring 2026-07-31 14:26:45 +09:00
curry772 5ffc48c039 REST 전송 body log의 길이를 줄이는 문제 처리 2026-07-31 13:48:39 +09:00
curry772 cbb6f33ce5 HttpClient5AdapterServiceRest.checkTokenRetry private -> protected 2026-07-31 13:48:08 +09:00
curry772 44093681b7 AdapterErrorMessageHandler 프러퍼티 그룹에 default template 기능 추가
- default.template
- default.in.template
- default.sys.template
20260731_개발배포
2026-07-31 09:35:48 +09:00
curry772 a24b437f5c 수신에서 표준오류응답을 수신하였는데 Inbound 어댑터에 AdapterErrorHandler 설정하였으나, 처리 후 null를
리턴하는 경우, 처리 로직 추가
2026-07-30 14:08:25 +09:00
curry772 67dba6ca4a R(응답)거래가 없어져서 소스 원복 2026-07-30 11:25:44 +09:00
curry772 f4d7ac2fad 타발응답거래(R2) 거래시 로그 출력 및 응답 안주는 문제 처리
- R2거래이어도 동기 거래이기 때문에 응답을 전달해야 함.
- 로그도 100 ~ 400을 출력해야 함.
2026-07-30 08:57:09 +09:00
curry772 6ca653aa1e oauth token scope 검증 중 통과 시킬 scope 배열 리스트 설정으로 변경
- oAuthServer pass.scope.list에 ',' 구분자로 통과시킬 scope 리스트
  설정(ex:public,oob)
2026-07-27 14:56:20 +09:00
curry772 90941bff54 DAMO 암호화 복호화 실패 시 원본 리턴되도록 수정 2026-07-27 10:43:33 +09:00
curry772 9e1f7391a0 ToolsController 개발
- base64 인코딩, damo 암복호화, version 정보
20260724_개발배포
2026-07-23 11:43:59 +09:00
curry772 cb0a588a9c ToolsController(/manage/tools) Postman 컬렉션 추가
base64/hex 변환, DAMO 및 EncryptionManager 암복호화, 배포 버전 조회 API를
기존 CryptoModuleManage/SessionCacheManage 컬렉션과 동일한 스타일로 샘플링.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 09:10:27 +09:00
curry772 afe2040b6e SessionManager 캐시 조회 관리 API 추가 (/manage/session)
SessionManagerForIgnite/SessionManagerForEhcache가 관리하는 login,
http-login, evict-master, terminal, convert-user-id, socket,
outbound-access-token 캐시를 조회할 수 있는 관리용 API를 추가한다.
outbound-access-token 캐시는 Ignite 백엔드에서만 지원하며, Ehcache
백엔드에서는 success=false로 응답하고 500을 반환하지 않는다.
20260722_개발배포
2026-07-21 15:25:27 +09:00
curry772 d13278c374 OAuth2 토큰 타입이 없을 때 Authorization 헤더에 Bearer 접두어 미부착
accessToken.getTokenType()이 비어있으면 Bearer 접두어 없이 토큰 값만
헤더에 설정하도록 setAuthHeaders를 수정하고, OAuth2AccessTokenVO의
tokenType은 BEARER_TYPE과 대소문자 무관하게 일치할 때만 상수로 정규화한다.
2026-07-21 15:01:54 +09:00
curry772 98d815e659 CryptoModuleManager 기반 암호화모듈 진단/암복호화 테스트 관리 API 추가
/manage/crypto 하위에 등록된 암호화모듈 목록/단건 조회, DYNAMIC 키
전략(KeyDerivationStrategy) 로드 상태 확인, 동적 키 캐시 키 목록 조회,
Base64 기반 암복호화 라운드트립 테스트 엔드포인트를 제공한다.
원본 암호키(encKeyHex/decKeyHex/ivHex)는 응답에 포함하지 않는다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 14:59:09 +09:00
curry772 c118c88dce 어댑터별 apikey 헤더명 동적 적용 2026-07-20 11:12:13 +09:00
curry772 28a4becf1c threshhold 및 threshholdpersecond 값 null 체크 추가 2026-07-20 11:10:56 +09:00
curry772 8339efc752 상태코드 출력포맷 변경 2026-07-20 11:10:21 +09:00