<!-- Source: https://docs.infraio.xyz/ja/concepts/sessions -->
<!-- Last updated: 2026-10-04 -->

# セッション

**CheckoutSession** はバイヤーが操作するもので、時間制限付きで 1 回限りの、
ホスト型チェックアウト URL を所有するオブジェクトです。3 つのコア
エンティティの中で最も軽量で、ほとんどのロジックは [Orders](https://docs.infraio.xyz/ja/concepts/orders)
と **Payment Intents** (下記) を扱います。

## 3 エンティティのデータモデル

```
CheckoutSession  ←  1:1  →  Order  ←  1:N  →  PaymentIntent
   (buyer)                  (catalog)         (each pay attempt)
```

| エンティティ | 目的 | 寿命 |
| --- | --- | --- |
| **CheckoutSession** | バイヤー向け — `session_key`、`checkout_url`、TTL を持つ | 分単位 (デフォルト 30) |
| **Order** | あなたのカタログ状態 — 行明細、合計、返金 | 永続レコード |
| **PaymentIntent** | 1 つのチェーン / アセットでの 1 回の支払い試行 | 時間単位; 精算または期限切れ |

セッションと注文は (`POST /b2b/v1/checkout-sessions/quick` 経由で)
一緒に作成します。チェックアウトページでバイヤーがアセットを選ぶたびに、
新しい PaymentIntent が該当チェーンに対して開かれます。途中で
アセットを切り替えると、前のインテントは `EXPIRED` に移り、新しい
ものが始まります。

## 識別子

セッションは `session_key` で識別されます:

```
cst_G-SO92J7HNWkwMHEHjD4oO1Z
```

URL セーフで、プレフィックス後は約 24 文字。ホスト型チェックアウトページは
`https://checkout.infraio.xyz/<session_key>` です — セッションキーを
そのチェックアウト用のベアラ資格情報として扱ってください。

## ライフサイクル — CheckoutSession

```mermaid
stateDiagram-v2
    [*] --> ACTIVE
    ACTIVE --> COMPLETED: a PaymentIntent settles
    ACTIVE --> EXPIRED:   expires_at elapsed
    ACTIVE --> CANCELED:  buyer or merchant cancels
    COMPLETED --> [*]
    EXPIRED --> [*]
    CANCELED --> [*]
```

| 状態 | 意味 |
| --- | --- |
| `ACTIVE` | セッションが作成されオープン。チェックアウト URL は使用可能。 |
| `COMPLETED` | このセッション上の PaymentIntent が精算。Order は `PAID` (または過少支払いなら `PARTIAL_PAID`)。 |
| `EXPIRED` | 精算なしに `expires_at` が経過。オープンな Order はキャンセルされる。 |
| `CANCELED` | 明示的キャンセル — バイヤーが "cancel" を押したか、キャンセルエンドポイントを呼び出した。 |

3 つの終端状態は相互排他的かつ最終的です。同じ 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 が 1 つ精算した) ので、もはや
再利用できません。

不足分を全額支払いとして受け入れて Order を `PAID` に解決することもできます。
[コンセプト → 注文](https://docs.infraio.xyz/ja/concepts/orders) を参照 (解決は API では利用できません;
セルフサーブのままにするには、代わりに残額を回収してください)。
残額を回収するには、同じ Order に対して残額の **新しい** CheckoutSession
を作成してください。

## 過剰支払い

バイヤーがセッション額より多く送ると (レアですが、手動送金で発生)、
InfraIO Pay が 24 時間以内に過剰支払いを検出し、通知します。
自動では返金されません。返金 API または
ダッシュボードから返金してください。

## 誤アセット支払い

入金先アドレスは 1 つのセッション・ネットワーク・アセットに対して生成
されます。バイヤーがそのアドレスに別のアセットを送ると、支払いは
照合されず、PaymentIntent はセッションが期限切れになるまでオープンの
ままです。サポートが資金の回収をお手伝いできますが、自動ではありません。
バイヤーにはチェックアウトページに表示されている正確なアセットを
送るよう案内してください。

TRON、Solana、TON には入金先アドレスがないため、これは EVM ネットワークのみに当てはまります。バイヤーはマーチャントのトレジャリーウォレットへ直接支払います。[ウォレット直接決済ネットワーク](https://docs.infraio.xyz/ja/concepts/chains#ウォレット直接決済ネットワーク) を参照してください。

## 作成時の冪等性

`POST /b2b/v1/checkout-sessions/quick` はリクエストボディに
`idempotency_key` フィールドを受け付けます (注意: **ボディフィールドで、
HTTP ヘッダーではありません**)。自然キーがない場合は UUID を生成してください。

このキーは CheckoutSession ではなく **Order** を重複排除します。同じ
キーでリトライすると、`/quick` は *元の Order* を返し (`order_id` は
安定)、**新しい CheckoutSession** を発行します — 毎回新しい
`session_key` と `checkout_url` です。これは意図的です:1 つの Order は
複数のチェックアウト試行を背負えるため ([Orders](https://docs.infraio.xyz/ja/concepts/orders)
を参照)、リトライされた `/quick` は Order を重複させずにバイヤーへ
クリーンなセッションを渡します。

2 つの挙動にご注意ください:

- **ボディはハッシュも比較もされません。** *異なる* ボディでキーを
  再利用しても `409` は **返りません** — サーバーはそのキーで既に
  保存された Order を黙って返し、新しいボディを無視します。したがって
  `idempotency_key` は 1 つの論理的な Order に対する使い切りトークン
  として扱い、異なるカートをまたいで使い回さないでください。
- **重複排除されるのは Order だけで、セッションではありません。**
  *同じ* チェックアウト URL が必要な場合は、最初のレスポンスから
  `session_key` / `checkout_url` を永続化してください — `/quick` を
  再度呼んでも古いものは返りません。ある Order に対して発行された全
  セッションを列挙するには、`GET /b2b/v1/checkout-sessions/by-order/:order_id`
  を使ってください。

## API エンドポイント

| メソッド | パス | 備考 |
| --- | --- | --- |
| `POST` | `/b2b/v1/checkout-sessions/quick` | 1 回の呼び出しで Order + セッションを作成 |
| `POST` | `/b2b/v1/checkout-sessions` | 既存の注文に対してセッションを作成 |
| `GET` | `/b2b/v1/checkout-sessions/by-order/:order_id` | 注文に対する全セッションを一覧表示 (リトライ履歴用) |

作成リクエストの完全なボディと署名は [クイックスタート](https://docs.infraio.xyz/ja/get-started/quickstart)
を参照してください。

## 次に

- [コンセプト → 注文](https://docs.infraio.xyz/ja/concepts/orders) — Order エンティティ
  (フルフィルメントの真実のソースとして扱うもの)。
- [コンセプト → チェーン & アセット](https://docs.infraio.xyz/ja/concepts/chains) — サポート
  ネットワークとチェーンごとのファイナリティ仮定。
- [Webhook → 概要](https://docs.infraio.xyz/ja/webhooks/overview) — 各セッション状態遷移で
  発火するイベント。
