Payment ‐ 세부기능 - nhnacademy-aiot3-4iren/4iren-wiki GitHub Wiki
Payment (구독 결제)
repo:
4iren-payment-api
0. 무엇을 판매하는가
- 팀/워크스페이스의 Owner 등급을 월간(
MONTHLY)/연간(YEARLY) 구독 상품으로 판매한다. - 등급 승격은 빌링키 등록 자체가 아니라 최초 결제가 성공한 시점에 이루어진다.
- 승격/강등은 RabbitMQ 이벤트로
account-api에 전달된다.account-api가 소유한UserRole.OWNER와core-api의 팀별TeamRole.OWNER는 서로 다른 개념이다.
1. 요금제 조회
GET /api/payment/plans— 판매 중인 요금제와 가격 조회 (역할 검증 없음)
2. 구독 관리
GET /api/payment/subscriptions— 현재 구독 상태 조회 (OWNER)DELETE /api/payment/subscriptions— 구독 취소 (OWNER)- 취소해도 즉시 강등되지 않고 현재 결제 주기 종료일(
currentPeriodEnd)까지 OWNER 등급이 유지된다.
- 취소해도 즉시 강등되지 않고 현재 결제 주기 종료일(
3. 결제 이력
GET /api/payment/payments— 결제 이력 조회 (OWNER)
4. 빌링키(자동결제) 등록
| 기능 | Toss Pay | Kakao Pay | 권한 |
|---|---|---|---|
| 등록 시작 | POST /api/payment/billing-keys/toss/registrations |
POST /api/payment/billing-keys/kakao/registrations |
NORMAL |
| 결제수단 변경 | POST .../toss/registrations/change |
POST .../kakao/registrations/change |
OWNER |
| 콜백 | POST .../toss/callback |
GET .../kakao/callback |
검증 없음 |
- 콜백은 PG사가 호출하므로 역할 검증을 적용하지 않는다.
- 결제수단 변경 시 새 빌링키는
PENDING상태로 저장되었다가 다음 청구 시점에 교체된다. - 등록 진행 상태는 Redis에 TTL 캐시로 보관한다.
- 빌링키 자격증명은 컨버터로 암호화하여 저장한다.
5. PG(결제대행사) 연동 현황
| PG사 | 상태 |
|---|---|
| Toss Pay | 구현 완료 (등록 콜백에서 REMOVED 처리 포함) |
| Kakao Pay | 구현 완료 |
| Naver Pay | 미구현 — Provider.NAVER_PAY enum 값만 존재하며, 선택 시 게이트웨이 조회에서 예외가 발생한다 |
6. 자동결제 및 배치
| 스케줄러 | 주기 | 역할 |
|---|---|---|
| 구독 정기 결제 | 매일 01:00 | 갱신 대상 구독 청구 (가상 스레드, 동시 실행 수 제한) |
| 취소 구독 만료 처리 | 매일 01:30 | 주기 종료된 취소 구독을 만료 처리하고 강등 이벤트 발행 |
| 미완료 결제 복구 | 10분마다 | READY 상태로 멈춘 결제 복구 |
- 다중 인스턴스 중복 실행은 Redis 기반 ShedLock으로 방지한다.
- 결제 실패 시 즉시 강등하지 않고
PAST_DUE상태로 두며, 최대 3회까지 재청구(dunning)한다. 재시도 횟수와 크론 주기는 코드 기본값이며 config-repo에서 별도로 재정의하지 않는다.
7. 등급 이벤트
- 승격: 최초 결제 성공 시
OWNER승격 이벤트 발행 (갱신 결제 시에는 재발행하지 않음) - 강등: 구독 만료(
EXPIRED) 또는 취소 후 주기 종료 시NORMAL강등 이벤트 발행
8. 도메인 엔티티 및 상태
Subscriptions—ACTIVE/PAST_DUE/EXPIRED/CANCELEDPayments—READY/DONE/FAILEDBillingKeys—ACTIVE/PENDING/DELETEDPlanPrices— 가격 변경 후에도 기존 구독자는 가입 시점 가격을 유지한다.- 물리 삭제를 사용하지 않고 모두 상태 전이로 관리한다. (빌링키 삭제도
DELETED전이)
9. 알림 및 실패 로깅
- 결제·구독 관련 메일 5종을 이벤트 기반으로 발송한다.
- 메일 발송 실패와 역할 변경 이벤트 발행 실패는 Elasticsearch에 별도 로그로 적재한다.
- RabbitMQ publisher confirms/returns를 사용해 발행 실패를 감지한다.
10. 외부 연동
- Eureka 서비스 디스커버리 기반 Feign 클라이언트로
4IREN-ACCOUNT,4IREN-CORE호출. 두 클라이언트 모두 fallback을 두지만 예외를 던지는 fail-closed 방식이며, 기능을 축소해 계속 동작하지는 않는다. - Config Server에서
4iren-payment.properties(-dev/-prod) 프로파일별 설정 로드 - MySQL 사용, Flyway로 마이그레이션 관리 — 이미 적용된 마이그레이션 파일은 수정하지 않는 것이 원칙. ⚠️ dev 프로파일은 로컬 전용 스키마(
payment_db)를 쓰지만, prod는 다른 서비스들과 동일한 공유 스키마(aiot03_team4)를 사용한다 — Database-per-Service 원칙이 prod에서는 지켜지지 않고 있다(4iren-config-repo/4iren-payment-prod.properties확인, 2026-09-09).
11. 현재 제공하지 않는 것
- 환불 API
- PG 결제 웹훅 수신 (콜백은 빌링키 등록 흐름에만 존재)
- 명시적 멱등성 키 — Toss는 등록 대기 캐시 소비와 활성 키 존재 여부로, Kakao는 404 응답으로 중복을 방어한다.