Skip to Content
概念工作階段
View as Markdown

工作階段

CheckoutSession 是買家互動的對象 — 一個有時效、單次使用的物件, 擁有託管結帳頁 URL。它是三個核心實體中最輕量的一層;你的多數邏輯會處理 訂單與 Payment Intent(見下方)上。

三實體資料模型

CheckoutSession ← 1:1 → Order ← 1:N → PaymentIntent (買家) (目錄) (每次付款嘗試)
實體用途生命週期
CheckoutSession買家面向 — 有 session_key、checkout_url、TTL分鐘級(預設 30 分鐘)
Order你的目錄狀態 — 商品項目、總額、退款永久紀錄
PaymentIntent在某條鏈 / 資產上的一次付款嘗試小時級;結算或過期

你會一起建立 session 與 order(透過 POST /b2b/v1/checkout-sessions/quick)。 每次買家在結帳頁選擇資產,系統會在對應的鏈上開啟新的 PaymentIntent。 若買家在結帳中途切換資產,先前的 intent 會進入 EXPIRED,新的會 開始。

識別碼

Session 以其 session_key 識別:

cst_G-SO92J7HNWkwMHEHjD4oO1Z

URL-safe,在前綴 cst_ 之後約 24 個字元。託管結帳頁是 https://checkout.infraio.xyz/<session_key> — 請把 session key 當作該一筆結帳的 bearer 憑證對待。

生命週期 — CheckoutSession

狀態意義
ACTIVESession 已建立並開啟。結帳 URL 可用。
COMPLETED此 session 上的某個 PaymentIntent 結算。Order 此時為 PAID(或若短付則為 PARTIAL_PAID)。
EXPIREDexpires_at 在未結算下過去。任何開啟的 Order 會被取消。
CANCELED明確取消 — 買家按下「取消」或你呼叫了 cancel endpoint。

三個終態互斥且最終。如果想要重試(例如短付後),可以對同一個 Order 建立新的 CheckoutSession。

TTL

  • 預設: 30 分鐘(可透過 create 時的 expires_in 欄位設定, 單位為秒)。
  • 範圍: 不強制任何最小/最大上下限。請選擇符合買家預期決策視窗的 值:低於 60 秒可能讓合法買家逾時,而開啟超過 7 天的 session 幾乎肯定 已被放棄。
  • 每商家預設: 你可以在儀表板設定預設值,但只有 POST /b2b/v1/checkout-sessions(兩步驟)會遵循它。 POST /b2b/v1/checkout-sessions/quick 在 expires_in 省略時使用 30 分鐘,無論儀表板設定為何。若要在 /quick 使用不同預設, 請在每次呼叫都帶 expires_in。
  • 強制執行: 一個 expires_at 已過的 session 即使狀態尚未更新, 也會被視為 EXPIRED,所以別在恰好過期的時刻倚賴狀態值。

短付

若買家送出少於 session 金額,PaymentIntent 仍會以該部分金額結算, Order 轉為 PARTIAL_PAID。CheckoutSession 移到 COMPLETED (一個 PaymentIntent 已結算),不再可重複使用。

要接受短缺作為全額付款,訂單可被 resolve 為 PAID。見 概念 → 訂單(無法透過 API resolve; 若要維持自助流程,請改為收集差額)。要收集差額,請對同一個 Order 建立新的 CheckoutSession,以剩餘金額計算。

超付

若買家送出超過 session 金額(罕見,但手動轉帳時會發生),InfraIO Pay 會在 24 小時內偵測到超付並通知你。超付不會自動退款, 請透過退款 API 或儀表板發起退款。

錯誤資產付款

每筆訂單獨立收款位址(CREATE2)是為單一 session、網路與資產產生的。 如果買家把不同的資產送到該位址,該筆付款不會被比對,PaymentIntent 會保持開啟直到 session 過期。Support 可以協助救回資金,但不會自動進行 — 請告知買家送出結帳頁顯示的確切資產。

TRON、Solana 與 TON 沒有獨立收款位址,因此這僅適用於 EVM 網路:買家直接付款到你的資金庫錢包。請見直達錢包的網路。

建立時的冪等性

POST /b2b/v1/checkout-sessions/quick 在請求 body 中接受 idempotency_key 欄位(注意:body 欄位,不是 HTTP header)。若你的 client 沒有自然 key,請產生一個 UUID。

這個 key 去重的是 Order,而不是 CheckoutSession。以相同 key 重試時, /quick 會回傳 原始 order(order_id 穩定),但每次都鑄造一個 全新的 CheckoutSession — 每次都是新的 session_key 與 checkout_url。這是 刻意設計:一個 Order 可以背負多次結帳嘗試(見 訂單),所以重試的 /quick 會在不重複 order 的前提下給買家一個乾淨的 session。

有兩點行為需要注意:

  • body 不會被雜湊或比較。 以 不同 的 body 重用一個 key 不會 回傳 409 — 伺服器會靜默回傳該 key 名下已存的 order,並忽略新的 body。所以請把 idempotency_key 當作單一邏輯 order 的一次性 token; 絕不要跨不同購物車回收使用。
  • 只有 Order 被去重,session 不會。 若你需要拿回 同一個 結帳 URL, 請把第一次回應裡的 session_key / checkout_url 持久化下來 — 再次 呼叫 /quick 不會回傳舊的。要列舉某個 order 名下鑄造過的每一個 session, 請用 GET /b2b/v1/checkout-sessions/by-order/:order_id。

API endpoints

MethodPath備註
POST/b2b/v1/checkout-sessions/quick一次呼叫建立 order + session
POST/b2b/v1/checkout-sessions對既有訂單建立 session
GET/b2b/v1/checkout-sessions/by-order/:order_id列出某訂單的所有 session(重試歷史)

完整 create 請求 body 與簽章請見快速入門。

下一步