한화리조트 PMS API 연동 개발 가이드
- 한화리조트 PMS API 연동 개발 가이드
- 시스템 개요
- 서비스 인터페이스 목록
- 공통 요청/응답 구조
- API 목록
- API별 처리 프로세스
- 1. 패키지 동기화
POST /v1/contents/sync-package - 2. 패키지 목록 조회
GET /v1/contents/search-package - 3. 케파(재고) 동기화
POST /v1/contents/sync-block - 4. 일별 객실료 동기화
POST /v1/contents/sync-rate - 5. 예약 생성
POST /v1/realtime/reservation - 6. 예약 취소
PUT /v1/realtime/reservation - 7. 예약 조회
GET /v1/realtime/reservation/{internalOrderNumber} - 8. 예약 복구
POST /v1/realtime/reservation/{internalOrderNumber}
- 1. 패키지 동기화
- 스케줄러
- 관련 DB 테이블
- 기술 스택
- 주요 참고사항
한화리조트 PMS API 연동 개발 가이드
자사 플랫폼과 한화리조트 PMS(iGate LCB) 간의 외부 API 연동 개발 내용을 정리한 문서입니다.
Spring Boot + WebClient(Reactor) 기반으로 구현되었으며, 모든 API는 JSON 형식으로 통신합니다.
시스템 개요
| 항목 | 내용 |
|---|---|
| 연동 대상 | 한화리조트 PMS (iGate LCB 게이트웨이) |
| PMS API Endpoint | application properties에 설정 (비공개) |
| 통신 방식 | HTTPS POST (단일 엔드포인트, serviceId로 API 구분) |
| 데이터 형식 | JSON |
| 인증 방식 | 요청 Body 내 CUST_NO, CONT_NO 포함 + 헤더 Uuid (UUID v4) |
| 인증 정보 | 설정 파일 또는 환경 변수에서 관리 (비공개) |
| HTTP Client | Spring WebClient (Project Reactor) |
| 타임아웃 | 60초 |
| DB | MariaDB |
| 스케줄러 | 재고 동기화 매일 01:00, 요금 동기화 매일 05:00 |
연동 API는 단일 엔드포인트에 대해 요청 Body의
SystemHeader.INTFC_ID값으로 서비스를 구분합니다.
서비스 인터페이스 목록
| 서비스명 | INTFC_ID | SERVICE_ID | 설명 |
|---|---|---|---|
| PACKAGELIST | LCB00HBSREMPRR9906 |
HBSREMPRR9906 |
패키지 목록 조회 |
| PACKAGEDETAIL | LCB00HBSREMPRR9931 |
HBSREMPRR9931 |
패키지 구성(상세) 조회 |
| BLOCK | LCB00HBSREMPRR9905 |
HBSREMPRR9905 |
케파(가용 객실 재고) 조회 |
| RATE | LCB00HBSREMPRR9907 |
HBSREMPRR9907 |
일별 객실 요금 조회 |
| RESERVATION | LCB00HBSREMPRR9901 |
HBSREMPRR9901 |
예약 생성 |
| CANCEL | LCB00HBSREMPRR9902 |
HBSREMPRR9902 |
예약 취소 |
| RETRIEVE | LCB00HBSREMPRR9903 |
HBSREMPRR9903 |
예약 조회 |
| MODIFY | LCB00HBSREMPRR9904 |
HBSREMPRR9904 |
예약 수정 (예비) |
공통 요청/응답 구조
요청 (CommonRequest)
모든 한화 API 요청은 아래 공통 헤더 구조를 사용합니다.
{
"systemHeader": {
"INTFC_ID": "LCB00HBSREMPRR9906",
"SERVICE_ID": "HBSREMPRR9906"
},
"transactionHeader": {
"TRANS_DT": "20251126",
"TRANS_TM": "120000",
"TRANS_SEQ_NO": "..."
},
"messageHeader": {
"MSG_PRCS_RSLT_CD": null,
"MSG_DATA_SUB_RPTT_CNT": null,
"MSG_ETC": null
},
"data": { ... }
}
응답 성공 판별
// messageHeader.MSG_PRCS_RSLT_CD == "0" AND
// messageHeader.MSG_DATA_SUB[0].MSG_CD == "SCMI000001"
MSG_PRCS_RSLT_CD가"0"이고MSG_CD가"SCMI000001"이면 정상 처리- 그 외는
HanwhaReservationException발생
HTTP 요청 헤더
Content-Type: application/json
Uuid: {UUID v4 랜덤 생성}
API 목록
Contents Controller (/v1/contents)
| Method | Endpoint | 설명 | 호출 방향 |
|---|---|---|---|
| POST | /v1/contents/sync-package |
패키지 동기화 | 내부 호출 → 한화 PMS |
| GET | /v1/contents/search-package |
패키지 목록 조회 (DB) | 내부 조회 |
| POST | /v1/contents/sync-block |
케파(재고) 동기화 | 내부 호출 → 한화 PMS |
| POST | /v1/contents/sync-rate |
일별 객실료 동기화 | 내부 호출 → 한화 PMS |
Realtime Controller (/v1/realtime)
| Method | Endpoint | 설명 | 호출 방향 |
|---|---|---|---|
| POST | /v1/realtime/reservation |
예약 생성 | 자사 → 한화 PMS |
| PUT | /v1/realtime/reservation |
예약 취소 | 자사 → 한화 PMS |
| GET | /v1/realtime/reservation/{orderNumber} |
예약 조회 | 자사 → 한화 PMS |
| POST | /v1/realtime/reservation/{orderNumber} |
예약 복구 | 자사 → 한화 PMS |
API별 처리 프로세스
1. 패키지 동기화 POST /v1/contents/sync-package
한화 PMS에서 영업장별 패키지 목록 및 구성 정보를 조회하여 DB에 동기화합니다.
처리 흐름
POST /v1/contents/sync-package
↓
[Step 1] 패키지 목록 조회 (PACKAGELIST - HBSREMPRR9906)
상품 매핑 테이블에서 한화 연동 숙소(LOC_CD) 목록 조회
→ 한화 PMS API 호출: 향후 12개월치 월별 1일 기준으로 패키지 목록 요청
→ PackageListResponse 수신 (패키지번호/명/유효기간/판매기간/연박수)
↓
[Step 2] 패키지 구성 조회 (PACKAGEDETAIL - HBSREMPRR9931)
패키지 번호 목록 추출 (distinct)
→ Flux 병렬 처리 (Schedulers.boundedElastic)로 패키지 상세 일괄 조회
→ PackageDetailResponse 수신 (영업장코드/룸타입코드/객실명)
↓
[Step 3] DB 저장
기 등록된 객실 정보와 매핑
→ (영업장코드 + 룸타입코드) 기준으로 product_idx, room_type_idx 매핑
→ HanwhaRatePlan 생성 후 DB upsert (패키지 요금제 테이블)
요청 파라미터
| 필드 | 설명 |
|---|---|
productIdxList |
동기화 대상 상품 Idx 목록 (비어있으면 전체) |
한화 패키지 목록 요청 주요 필드 (ds_search)
| 필드 | 설명 |
|---|---|
CUST_NO |
고객 번호 (설정값, 비공개) |
CONT_NO |
계약 번호 (설정값, 비공개) |
LOC_CD |
영업장 코드 |
ARRV_DATE |
도착일 (yyyyMMdd, 월 1일 기준 12개월) |
PAKG_NO |
패키지 번호 (전체 조회 시 null) |
2. 패키지 목록 조회 GET /v1/contents/search-package
DB에 저장된 한화 패키지 목록을 조회하는 내부 API입니다. (외부 API 미호출)
처리 흐름
GET /v1/contents/search-package
→ ContentsService.searchPackage(request)
→ DB 조회 (패키지 요금제 테이블)
→ List<PackageSearchList> 반환
3. 케파(재고) 동기화 POST /v1/contents/sync-block
한화 PMS에서 일별 객실 가용 재고를 조회하여 DB에 업데이트합니다.
스케줄러에 의해 매일 01:00 자동 실행됩니다.
처리 흐름
POST /v1/contents/sync-block (또는 스케줄러 자동 실행)
↓
매핑 정보 조회
→ 한화 매핑 테이블에서 대상 목록 조회
→ 룸온리 상품 / 패키지 상품으로 분류
↓
[룸온리 상품] 재고 업데이트
→ 케파 API 호출 (BLOCK - HBSREMPRR9905)
→ 0.5초 간격 직렬 처리 (한화 API 병렬 처리 시 오류 방지)
→ KepaResponse.DsRoomStatus (세션날짜, 예약가능수) 수신
→ 객실 재고 테이블 upsert (avail, stock, date)
↓
[패키지 상품] 요금제 가용 업데이트
→ 케파 API 호출 (BLOCK - HBSREMPRR9905, 패키지번호 포함)
→ 요금제 가용 테이블 upsert (avail, date)
케파 요청 주요 필드 (KepaRequest)
| 필드 | 설명 |
|---|---|
CUST_NO |
고객 번호 (설정값) |
CONT_NO |
계약 번호 (설정값) |
LOC_CD |
영업장 코드 |
ROOM_TYPE_CD |
룸타입 코드 |
PAKG_NO |
패키지 번호 (룸온리는 null) |
케파 응답 주요 필드 (DsRoomStatus)
| 필드 | 설명 |
|---|---|
LOC_CD |
영업장 코드 |
ROOM_TYPE_CD |
룸타입 코드 |
SESN_DATE |
세션 날짜 (yyyyMMdd) |
RSRV_POSBL_CNT |
예약 가능 수량 |
요청 파라미터
| 필드 | 설명 |
|---|---|
allSync |
전체 동기화 여부 (true: 전체) |
productIdxList |
특정 상품 Idx 목록 |
4. 일별 객실료 동기화 POST /v1/contents/sync-rate
한화 PMS에서 일별 객실 요금을 조회하여 DB에 업데이트합니다.
스케줄러에 의해 매일 05:00 자동 실행됩니다.
처리 흐름
POST /v1/contents/sync-rate (또는 스케줄러 자동 실행)
↓
매핑 정보 조회
→ 한화 매핑 테이블에서 대상 목록 조회
→ 룸온리 상품 / 패키지 상품으로 분류
↓
[룸온리 상품] 요금 업데이트
오늘 기준 2개월치, 1일 간격으로 요청 목록 생성
→ 요금 API 호출 (RATE - HBSREMPRR9907)
→ 0.5초 간격 직렬 처리
→ RateResponse.DsResult (영업일, 객실요금, 수수료율 등) 수신
→ 마진율 계산: otaPrice → duePrice, netPrice, price 순차 계산
→ 요금제 요금 테이블 upsert
↓
[패키지 상품] 요금 업데이트
패키지 유효기간(minDate ~ maxDate), ovntCnt 간격으로 요청 목록 생성
→ 요금 API 호출 (RATE - HBSREMPRR9907)
→ 동일 방식으로 요금 계산 및 DB upsert
요금 API 요청 주요 필드 (RateRequest)
| 필드 | 설명 |
|---|---|
LOC_CD |
영업장 코드 |
ROOM_TYPE_CD |
룸타입 코드 |
PAKG_NO |
패키지 번호 (룸온리는 null) |
ARRV_DATE |
도착일 (yyyyMMdd) |
OVNT_CNT |
연박 수 (룸온리: 1, 패키지: ovntCnt) |
요금 응답 주요 필드 (DsResult)
| 필드 | 설명 |
|---|---|
BSN_DATE |
영업일 (yyyyMMdd) |
ROOM_RATE |
객실 요금 |
ORIG_ROOM_RATE |
원래 객실 요금 |
CALC_ROOM_RATE |
계산된 객실 요금 (마진 계산 기준) |
FEE_RATE |
수수료율 |
UPGRD_YN |
업그레이드 여부 |
마진 계산 로직
// otaPrice = CALC_ROOM_RATE
// duePrice = otaPrice × inDuePriceRate (올림 없음)
// netPrice = otaPrice × inNetPriceRate
// price = netPrice × inPriceRate
// → 요금제 요금 테이블에 저장
5. 예약 생성 POST /v1/realtime/reservation
자사 플랫폼에서 한화 PMS로 실시간 예약을 전송합니다.
처리 흐름
자사 플랫폼 결제 완료
→ POST /v1/realtime/reservation (JSON)
↓
[1] 예약 요청 로그 저장 (reservation_log)
↓
[2] 한화 예약 사전 저장 (한화 예약 테이블)
rateplanIdx 기반으로 객실 정보 조회
→ 영업장코드(LOC_CD), 룸타입코드, 패키지번호 확인
↓
[3] 한화 PMS 예약 API 호출 (RESERVATION - HBSREMPRR9901)
WebClient POST → 한화 이게이트 단일 엔드포인트 (설정값)
↓
[4] 응답 검증
MSG_PRCS_RSLT_CD == "0" AND MSG_CD == "SCMI000001"
→ 성공: 한화 예약 테이블 업데이트 (bookingStatus=COMPLETE, hanwhaBookingId=rsrvNo)
→ 실패: HanwhaReservationException 발생
↓
[5] 예약 응답 로그 저장
→ externalBookingId (한화예약번호) 반환
요청 주요 필드 (ReservationRequest)
| 필드 | 설명 |
|---|---|
internalOrderNumber |
자사 주문번호 |
rateplanIdx |
요금제 Idx |
| 투숙자 정보 | 이름, 연락처 등 |
| 투숙 정보 | 도착일, 객실수, 연박수 등 |
한화 예약 요청 주요 필드 (HanwhaReservationRequest)
| 필드 | 설명 |
|---|---|
LOC_CD |
영업장 코드 |
ROOM_TYPE_CD |
룸타입 코드 |
PAKG_NO |
패키지 번호 |
ARRV_DATE |
도착일 (yyyyMMdd) |
OVNT_CNT |
연박 수 |
RSRV_ROOM_CNT |
예약 객실 수 |
INHS_CUST_NM |
투숙객명 |
INHS_CUST_TEL_NO |
투숙객 연락처 |
6. 예약 취소 PUT /v1/realtime/reservation
자사 플랫폼에서 한화 PMS로 예약 취소를 전송합니다.
처리 흐름
자사 플랫폼 취소 요청
→ PUT /v1/realtime/reservation (JSON)
↓
[1] internalOrderNumber로 한화 예약 테이블 조회 (한화예약번호 확인)
↓
[2] 예약 취소 요청 로그 저장 (reservation_log)
↓
[3] 한화 PMS 취소 API 호출 (CANCEL - HBSREMPRR9902)
→ 한화예약번호(externalBookingId) 기반으로 취소 요청
↓
[4] 응답 검증
MSG_PRCS_RSLT_CD == "0" AND MSG_CD == "SCMI000001"
→ 성공: 한화 예약 테이블 업데이트 (bookingStatus=CANCELED)
→ 실패: HanwhaReservationException 발생
↓
[5] 취소 응답 로그 저장
→ internalOrderNumber, externalBookingId 반환
요청 주요 필드 (ReservationCancelRequest)
| 필드 | 설명 |
|---|---|
internalOrderNumber |
자사 주문번호 |
externalBookingId |
한화 예약번호 (rsrvNo) |
7. 예약 조회 GET /v1/realtime/reservation/{internalOrderNumber}
자사 주문번호로 한화 PMS에서 예약 정보를 조회합니다.
처리 흐름
GET /v1/realtime/reservation/{internalOrderNumber}
↓
[1] DB에서 한화 예약 테이블 조회 → 한화예약번호(rsrvNo) 확인
↓
[2] 한화 PMS 조회 API 호출 (RETRIEVE - HBSREMPRR9903)
→ 한화예약번호 기준으로 예약 상세 조회
↓
[3] 응답 검증
MSG_PRCS_RSLT_CD == "0" AND MSG_CD == "SCMI000001"
→ 성공: ReservationSearchResponseInfo 반환
→ 실패: HanwhaReservationException 발생
조회 응답 주요 필드 (DsResult)
| 필드 | 설명 |
|---|---|
RSRV_NO |
한화 예약번호 |
LOC_CD |
영업장 코드 |
ROOM_TYPE_CD |
룸타입 코드 |
ARRV_DATE |
도착일 |
OVNT_CNT |
연박 수 |
RSRV_ROOM_CNT |
예약 객실 수 |
INHS_CUST_NM |
투숙객명 |
INHS_CUST_TEL_NO2~4 |
투숙객 연락처 |
8. 예약 복구 POST /v1/realtime/reservation/{internalOrderNumber}
예약 생성 중 장애 등으로 DB 저장 누락 시 한화 PMS 데이터 기준으로 예약 정보를 복구합니다.
처리 흐름
POST /v1/realtime/reservation/{internalOrderNumber}
↓
[1] DB에서 한화 예약 테이블 조회 → 한화예약번호 미존재 확인 (복구 대상 판별)
↓
[2] 한화 PMS 조회 API 호출 (RETRIEVE - HBSREMPRR9903)
→ 한화 PMS 실제 예약 정보 조회
↓
[3] 주문 상품 테이블 조회
→ 자사 주문 정보 확인 (productIdx, roomIdx, rateplanIdx, saleAmount)
↓
[4] DB 복구 저장
한화 PMS 조회 결과 + 주문 상품 정보 기반으로 한화 예약 테이블 INSERT
(bookingStatus=COMPLETE, hanwhaBookingId=rsrvNo)
↓
[5] externalBookingId 반환
스케줄러
| 스케줄 | Cron | 대상 | 설명 |
|---|---|---|---|
| 재고 동기화 | 0 0 1 * * * (매일 01:00) |
전체 매핑 상품 | 케파 API → 객실 재고 테이블 업데이트 |
| 요금 동기화 | 0 0 5 * * * (매일 05:00) |
전체 매핑 상품 | 요금 API → 요금제 요금 테이블 업데이트 |
스케줄러는
prod프로파일에서만 동작합니다.
관련 DB 테이블
| 구분 | 설명 |
|---|---|
| 한화 연동 원본 | 한화 영업장·객실·패키지(요금제) 원본 데이터 |
| 연동 매핑 | 자사 상품 ↔ 한화 상품 매핑 정보 |
| 예약 | 한화 예약 정보 및 송수신 로그 |
| 재고·요금 | 케파·요금 동기화 결과 (객실 재고, 요금제 요금, 가용 여부) |
| 주문 | 자사 주문 상품 정보 |
| 마진 설정 | 요금제별 마진율 설정 |
실제 테이블명 및 스키마는 내부 관리 문서를 참고합니다.
기술 스택
| 항목 | 기술 |
|---|---|
| Framework | Spring Boot |
| HTTP Client | WebClient (Project Reactor / Flux, Mono) |
| 직렬 처리 | delayElements(500ms) – 한화 API 병렬 호출 오류 방지 |
| 병렬 처리 | Flux.parallel() + Schedulers.boundedElastic() (패키지 상세 조회) |
| ORM | MyBatis |
| 인증 | JWT (Spring Security) |
| DB | MariaDB |
| 스케줄러 | Spring @Scheduled |
| 캐시 | Spring Cache (Caffeine) |
주요 참고사항
- 단일 엔드포인트: 모든 한화 API는 동일한 URL로 요청하며
SystemHeader.INTFC_ID로 서비스를 구분합니다. - 직렬 처리: 케파·요금 조회는 한화 API 측의 병렬 오류로 인해
delayElements(500ms)직렬 처리로 전환되었습니다. - 패키지 상세 조회: 패키지 목록에서 추출한 패키지번호를 기준으로 Flux 병렬 처리하여 성능을 확보합니다.
- 요금 계산: 한화에서 받은
CALC_ROOM_RATE기준으로 DB에 저장된 마진율을 적용해 duePrice/netPrice/price를 계산합니다. - 예약 복구: 예약 중 장애로 DB 저장 실패 시
/v1/realtime/reservation/{orderNumber}POST 호출로 한화 PMS 데이터 기준 복구가 가능합니다. - prod 환경 전용: 스케줄러는
spring.profiles.active=prod일 때만 동작합니다.