Skip to Content
개념세션
View as Markdown

세션

CheckoutSession은 구매자가 상호작용하는 대상입니다 — 시간 제한이 있는 일회용 객체이며 호스팅 결제 페이지 URL을 소유합니다. 세 가지 핵심 엔티티 중 가장 가벼운 편이며, 대부분의 로직은 Order와 PaymentIntent(아래 참조)가 담당합니다.

세 엔티티 데이터 모델

CheckoutSession ← 1:1 → Order ← 1:N → PaymentIntent (구매자 영역) (카탈로그) (결제 시도별)
엔티티용도수명
CheckoutSession구매자 영역 — session_key, checkout_url, TTL 보유분 단위(기본값 30)
Order가맹점의 카탈로그 상태 — 라인 아이템, 합계, 환불영구 기록
PaymentIntent하나의 체인/자산에서 한 번의 결제 시도시간 단위. 정산되거나 만료

세션과 주문은 함께 생성됩니다(POST /b2b/v1/checkout-sessions/quick 사용). 구매자가 체크아웃 페이지에서 자산을 선택할 때마다 해당 체인에 대해 새로운 PaymentIntent가 열립니다. 체크아웃 진행 중에 자산을 변경하면 이전 인텐트는 EXPIRED로 이동하고 새 인텐트가 시작됩니다.

식별자

세션은 session_key로 식별됩니다.

cst_G-SO92J7HNWkwMHEHjD4oO1Z

URL-safe하며 프리픽스 뒤에 약 24자입니다. 호스팅 결제 페이지 페이지는 https://checkout.infraio.xyz/<session_key>이며 — 세션 키는 해당 단일 체크아웃에 대한 베어러 자격 증명으로 취급해야 합니다.

라이프사이클 — CheckoutSession

상태의미
ACTIVE세션이 생성되어 열려 있는 상태. 체크아웃 URL을 사용할 수 있습니다.
COMPLETED이 세션의 PaymentIntent가 정산됨. Order는 이제 PAID(또는 과소 결제 시 PARTIAL_PAID)가 됩니다.
EXPIRED정산 없이 expires_at이 경과함. 열려 있던 Order는 취소됩니다.
CANCELED명시적 취소 — 구매자가 “취소”를 눌렀거나 가맹점이 취소 엔드포인트를 호출한 경우입니다.

세 가지 종료 상태는 상호 배타적이며 최종 상태입니다. 동일한 Order에 대해 재시도가 필요한 경우(예: 과소 결제 후) 새 CheckoutSession을 생성할 수 있습니다.

TTL

  • 기본값: 30분(생성 시 expires_in 필드로 초 단위 설정 가능).
  • 범위: 강제되는 최소/최대값은 없습니다. 구매자의 예상 결정 시간에 맞는 값을 선택하세요. 60초 미만은 정상적인 구매자도 시간 초과될 위험이 있고, 7일 넘게 열려 있는 세션은 거의 확실히 포기된 것입니다.
  • 가맹점별 기본값: 대시보드에서 설정할 수 있지만, POST /b2b/v1/checkout-sessions(2단계)만 이를 따릅니다. POST /b2b/v1/checkout-sessions/quick은 expires_in이 생략된 경우 대시보드 설정에 관계없이 30분을 사용합니다. /quick에서 다른 기본값을 사용하려면 매번 expires_in을 전송하세요.
  • 적용 방식: expires_at이 지난 세션은 상태가 아직 업데이트되지 않았더라도 EXPIRED로 취급되므로 만료 시점의 상태 값에 의존하지 마세요.

과소 결제

구매자가 세션 금액보다 적게 송금하면, PaymentIntent는 부분 금액에 대해 여전히 정산되고 Order는 PARTIAL_PAID로 전이합니다. CheckoutSession은 COMPLETED로 이동하므로(PaymentIntent 하나가 정산됨) 더 이상 재사용할 수 없습니다.

부족분을 전체 결제로 수용하려면 주문을 PAID로 해결할 수 있습니다 — 개념 → Order 참조(resolve는 API로 제공되지 않으므로 셀프 서비스를 유지하려면 부족분을 대신 수집하세요). 부족분을 수집하려면 동일한 Order에 대해 잔여 금액으로 새 CheckoutSession을 생성하세요.

초과 결제

구매자가 세션 금액보다 많이 송금하는 경우(수동 송금에서 드물게 발생), InfraIO Pay가 24시간 이내에 초과 결제를 감지하고 알림을 보냅니다. 자동으로 환불되지 않습니다. 환불 API 또는 대시보드를 통해 환불을 발행하세요.

잘못된 자산 결제

입금 주소는 하나의 세션, 네트워크, 자산에 대해 생성됩니다. 구매자가 다른 자산을 해당 주소로 송금하면 결제가 매칭되지 않고 PaymentIntent는 세션이 만료될 때까지 열린 상태로 유지됩니다. 지원팀이 자금 복구를 도울 수 있지만 자동이 아닙니다. 구매자에게 체크아웃 페이지에 표시된 정확한 자산을 송금하도록 안내하세요.

TRON, Solana, TON에는 주문별 입금 주소가 없으므로 이 내용은 EVM 네트워크에만 해당합니다. 구매자가 가맹점의 지갑으로 직접 결제합니다. 지갑 직접 결제 네트워크를 참조하세요.

생성 시 멱등성

POST /b2b/v1/checkout-sessions/quick는 요청 본문에 idempotency_key 필드를 허용합니다(주의: HTTP 헤더가 아닌 본문 필드). 자연스러운 키가 없다면 UUID를 생성하세요.

이 키는 CheckoutSession이 아닌 Order에 대해 중복을 제거합니다. 동일한 키로 재시도하면 /quick은 원래 주문(order_id는 안정적)을 반환하지만 새로운 CheckoutSession을 발급합니다 — 매번 새 session_key와 checkout_url이 생성됩니다. 이는 의도된 동작입니다. 하나의 Order가 여러 체크아웃 시도를 지원할 수 있으므로(Order 참조), 재시도된 /quick은 주문을 중복 생성하지 않고 구매자에게 깨끗한 세션을 제공합니다.

알아 두어야 할 두 가지 동작이 있습니다.

  • 본문은 해시되거나 비교되지 않습니다. 동일한 키를 다른 본문과 함께 재사용해도 409를 반환하지 않습니다 — 서버는 해당 키에 저장된 주문을 조용히 반환하고 새 본문을 무시합니다. 따라서 idempotency_key는 단일 논리적 주문에 대한 일회성 토큰으로 다루고, 서로 다른 장바구니에 절대 재사용하지 마세요.
  • Order만 중복 제거되며, 세션은 그렇지 않습니다. 동일한 체크아웃 URL을 다시 받으려면 첫 응답의 session_key / checkout_url을 영구 저장하세요 — /quick을 다시 호출해도 이전 URL이 반환되지 않습니다. 하나의 주문에 대해 발급된 모든 세션을 열거하려면 GET /b2b/v1/checkout-sessions/by-order/:order_id를 사용하세요.

API 엔드포인트

메서드경로비고
POST/b2b/v1/checkout-sessions/quick한 번의 호출로 주문 + 세션 생성
POST/b2b/v1/checkout-sessions기존 주문에 대해 세션 생성
GET/b2b/v1/checkout-sessions/by-order/:order_id한 주문의 모든 세션 목록(재시도 이력)

전체 생성 요청 본문과 서명은 빠른 시작을 참조하세요.

다음 단계

  • 개념 → Order — Order 엔티티(이행의 그라운드 트루스로 다루는 엔티티)를 다룹니다.
  • 개념 → 체인 및 자산 — 지원되는 네트워크와 체인별 파이널리티 가정을 다룹니다.
  • 웹훅 → 개요 — 각 세션 상태 전이에서 발생하는 이벤트를 다룹니다.