Booking / Payment · Consistency
Stripe 선결제부터 Webhook·취소·환불까지 결제 상태 흐름을 구축했습니다.
외부 결제와 DB를 하나의 transaction처럼 포장하지 않고, 예약 실패의 보상 흐름과 환불 완료 시점을 분리해 상태 정합성을 보완했습니다.
- Role
- Stripe 선결제 구축 주도 · 결제 도메인 기여
- Scope
- Prepayment · Refund
- Stack
- FastAPI · PostgreSQL · Stripe
- Period
- 2024.11 — 2025.01
외부 provider의 접수·완료 상태가 확인되기 전에 로컬 업무 상태를 성공으로 앞서 보내지 않습니다.
Problem & constraints
왜 이 문제를 풀어야 했는가
선결제는 예약 생성 전에 시작되므로 PaymentIntent와 로컬 결제 이력을 아직 없는 예약 객체 없이 연결해야 했습니다.
환불은 provider에서 비동기로 완료됩니다. 요청 시점에 mileage와 ticket을 먼저 바꾸면 provider 실패 때 로컬 상태만 앞서갈 수 있었습니다.
Failure boundary
실패하면 어디에서 멈추고, 어떻게 복구하는가
Decisions
핵심 기술 판단
Correlation
local transaction ID와 payment type을 Checkout·Webhook metadata에 넣어 외부 event를 로컬 이력과 연결했습니다.
Compensation
manual capture 전후 상태에 따라 cancel/refund를 선택하는 provider-side 보상 경계를 뒀습니다.
Completion State
mileage 복원과 ticket 삭제를 환불 요청이 아니라 완료 transition 뒤로 이동했습니다.
System flow
판단을 실제 시스템으로 옮긴 구조
Payment history
예약 전 local transaction과 payment method 생성
Checkout · PaymentIntent
metadata로 correlation하고 manual capture 대기
예약 처리
성공 시 capture, 실패 시 상태별 cancel/refund
Webhook completion
완료 확인 뒤 payment·mileage·ticket 상태 전이
Evidence
운영에서 확인한 결과
Checkout·manual capture·provider compensation
refund·mileage·ticket transition