---
title: Checkout Sessions API
description: 建立與查詢 Hosted Checkout 結帳 Session
---

# Checkout Sessions API

Checkout Session 是 [Hosted Checkout](/guides/checkout/hosted-checkout) 的核心資源。在後端建立 Session 後,將用戶導向回傳的 `url`,即可在 Recur 託管的結帳頁面完成付款。

  **欄位命名**:回應一律使用 `snake_case`(如 `external_customer_id`)。請求本文接受 `snake_case`(建議)與 legacy `camelCase` 兩種寫法。

## 認證

兩個端點都支援 Secret Key(`Authorization: Bearer sk_xxx`)與 Publishable Key(`X-Recur-Publishable-Key: pk_xxx`)。差異:

- **Publishable Key** 不可設定 `metadata`(server-only 欄位)
- 建議在後端以 Secret Key 建立 Session

## 建立 Checkout Session

```
POST https://api.recur.tw/v1/checkout/sessions
```

### 請求參數

| 參數 | 必填 | 說明 |
|------|------|------|
| `product_id` | ✅* | 商品 ID(與 `product_slug` 二擇一) |
| `product_slug` | ✅* | 商品 Slug(與 `product_id` 二擇一) |
| `success_url` | ✅ | 成功後的重新導向 URL(HTTPS,支援 `{CHECKOUT_SESSION_ID}` 佔位符) |
| `cancel_url` | ✅ | 取消時的重新導向 URL(HTTPS) |
| `mode` | ❌ | `PAYMENT`、`SUBSCRIPTION`、`SETUP`;未指定時依商品類型自動判斷 |
| `customer_email` | ❌ | 預填客戶 Email(未提供時由結帳頁向付款者收集) |
| `customer_name` | ❌ | 預填客戶姓名 |
| `external_customer_id` | ❌ | 您系統中的用戶 ID。無論 email 是在建立時提供或結帳頁才收集,都會套用到該 Session 建立/連結的客戶,詳見[客戶身份綁定](/guides/checkout/hosted-checkout#客戶身份綁定externalid) |
| `promotion_code` | ❌ | 預先套用的優惠碼(建立時即驗證與計算折扣) |
| `collect_payment_method` | ❌ | `always`(預設)或 `if_required`(零元結帳免綁卡) |
| `metadata` | ❌ | 自訂 metadata(僅 Secret Key 可用) |
| `einvoice` | ❌ | 買家電子發票選擇(Publishable Key 也可用),用於預填結帳頁的發票資訊區塊。格式錯誤(如統編檢查碼不符)回 `422`,詳見[電子發票](/guides/checkout/einvoice) |

### 範例

```bash
curl -X POST https://api.recur.tw/v1/checkout/sessions \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prod_abc123",
    "mode": "SUBSCRIPTION",
    "success_url": "https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
    "cancel_url": "https://example.com/pricing",
    "external_customer_id": "user_123"
  }'
```

**回應(201)**:

```json
{
  "id": "cs_abc123xyz",
  "url": "https://checkout.recur.tw/cs_abc123xyz",
  "expires_at": "2025-01-01T00:30:00Z",
  "amount": 29900,
  "requires_payment_method": true,
  "livemode": true
}
```

| 欄位 | 說明 |
|------|------|
| `id` | Session ID |
| `url` | 導向用戶的結帳頁 URL |
| `expires_at` | Session 到期時間(建立後 30 分鐘) |
| `amount` | 折扣後實際金額 |
| `requires_payment_method` | 是否需要收集信用卡(零元結帳時可能為 `false`) |
| `client_secret` | (選)PaymentIntent client secret,供前端 SDK 輪詢狀態 |
| `discount` | (選)套用優惠碼時的折扣明細 |
| `einvoice_enabled` | 組織是否已啟用電子發票自動開立(可據此決定是否收集發票資訊) |
| `livemode` | 是否為正式環境 |

## 查詢 Checkout Session

```
GET https://api.recur.tw/v1/checkout/sessions/{id}
```

用於付款完成重新導向後確認 Session 狀態,或稽核 Session 上儲存的值。

**回應(200)**:

```json
{
  "id": "cs_abc123xyz",
  "status": "COMPLETE",
  "mode": "SUBSCRIPTION",
  "customer_email": "user@example.com",
  "external_customer_id": "user_123",
  "order_id": "ord_xyz789",
  "subscription_id": "sub_def456",
  "payment_intent_id": "pi_ghi012",
  "setup_intent_id": null,
  "amount_total": 29900,
  "currency": "TWD",
  "product": { "id": "prod_monthly", "name": "Monthly Plan" },
  "expires_at": "2025-01-01T00:30:00Z",
  "created_at": "2025-01-01T00:00:00Z",
  "completed_at": "2025-01-01T00:05:00Z",
  "livemode": true
}
```

| 欄位 | 說明 |
|------|------|
| `status` | `OPEN`(等待付款)、`COMPLETE`(付款完成)、`EXPIRED`(已過期) |
| `customer_email` | 建立時預填或結帳頁收集到的 Email |
| `external_customer_id` | 建立 Session 時帶入的外部客戶 ID(可用於稽核綁定值) |
| `subscription_id` | 訂閱建立後回填(SUBSCRIPTION mode) |

  付款完成後,建議以 `checkout.completed` webhook 為準進行開通;此端點適合重新導向頁的即時確認與除錯。

## 錯誤

| HTTP | code | 情境 |
|------|------|------|
| 400 | `bad_request` | JSON 格式錯誤、Publishable Key 帶 `metadata` |
| 401 | `unauthorized` | API Key 無效 |
| 404 | `not_found` | 商品不存在或未上架(含存取其他組織的商品) |
| 409 | `conflict` | 客戶已有該商品的有效訂閱,詳見[錯誤代碼](/api-reference/error-codes#conflict-409) |
| 422 | `validation_error` | 請求本文驗證失敗(含 `einvoice` 格式錯誤,如統編檢查碼不符、手機條碼格式錯誤) |

完整錯誤格式請見[錯誤代碼](/api-reference/error-codes)。
