> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# チェックアウトセッションの作成

> カスタムパラメータで支払いリンクをプログラム的に生成

<Accordion title="✨ AIでインストール" icon="sparkles">
  このプロンプトをAIコードエディタ（Cursor、Copilotなど）にコピーして、チェックアウト統合を作成：

  ```text theme={"system"}
  Add Waffo Pancake checkout to my project using the official TypeScript SDK.

  npm install @waffo/pancake-ts

  Create a WaffoPancake client with WAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY.
  Use client.checkout.createSession({ productId, currency: "USD" })
  to get a checkoutUrl, then redirect the user with res.redirect(checkoutUrl).

  For webhooks, use verifyWebhook(rawBody, signature) from the SDK — it has embedded public keys,
  no secret needed. Handle events: order.completed, subscription.activated, subscription.canceled.

  Read https://waffo.mintlify.app/llms-full.txt for full API reference.
  ```
</Accordion>

***

## 構築するもの

チェックアウトセッションは動的に生成される支払いページです。静的な製品リンクを共有する代わりに、以下が可能です：

* 顧客メールの事前入力
* カスタムmetadataでの注文追跡
* カスタム成功URLの設定
* サブスクリプションのトライアル期間の有効化

***

## 前提条件

* Waffo Pancakeアカウント
* APIキー（Dashboard → API と開発）
* 少なくとも1つの製品が作成済み

***

## 基本的なチェックアウトセッション

最もシンプルなチェックアウトセッションには製品IDと通貨が必要です。

### TypeScript SDK を使用（推奨）

```bash theme={"system"}
npm install @waffo/pancake-ts
```

```typescript theme={"system"}
import { WaffoPancake } from "@waffo/pancake-ts";

const client = new WaffoPancake({
  merchantId: process.env.WAFFO_MERCHANT_ID!,
  privateKey: process.env.WAFFO_PRIVATE_KEY!,
});

const session = await client.checkout.createSession({
  productId: "prod_xxx",
  currency: "USD",
});

// ユーザーをチェックアウトページにリダイレクト
res.redirect(session.checkoutUrl);
```

### REST APIを直接使用

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -X POST https://api.waffo.ai/v1/actions/checkout/create-session \
    -H "Content-Type: application/json" \
    -H "X-Store-Slug: your-store-slug" \
    -H "X-Environment: test" \
    -d '{
      "productId": "your-product-uuid",
      "currency": "USD"
    }'
  ```

  ```python Python theme={"system"}
  import requests

  response = requests.post(
      'https://api.waffo.ai/v1/actions/checkout/create-session',
      headers={
          'Content-Type': 'application/json',
          'X-Store-Slug': 'your-store-slug',
          'X-Environment': 'test',
      },
      json={
          'productId': 'your-product-uuid',
          'currency': 'USD',
      }
  )

  checkout_url = response.json()['data']['checkoutUrl']
  # 顧客をcheckout_urlにリダイレクト
  ```
</CodeGroup>

**レスポンス：**

```json theme={"system"}
{
  "data": {
    "sessionId": "cs_xxx",
    "checkoutUrl": "https://checkout.waffo.ai/your-store/checkout/cs_xxx",
    "expiresAt": "2024-01-22T12:00:00Z"
  }
}
```

顧客を`checkoutUrl`にリダイレクトして支払いを完了します。

***

## リダイレクトのベストプラクティス

<Warning>
  **チェックアウトページを開くために`window.open()`を使用しないでください。** Safariや多くのモバイルブラウザは、非同期コールバック（例：API呼び出しの後）から開かれるポップアップウィンドウをブロックします。これにより、顧客のチェックアウトが警告なしに失敗します。
</Warning>

**推奨アプローチ：**

| 方法              | 使用するタイミング          | 例                                    |
| --------------- | ------------------ | ------------------------------------ |
| サーバーサイドリダイレクト   | APIルート / サーバーアクション | `res.redirect(checkoutUrl)`          |
| クライアントサイドリダイレクト | SPA / React        | `window.location.href = checkoutUrl` |
| リンク要素           | 静的リンク              | `<a href={checkoutUrl}>`             |

```typescript theme={"system"}
// ✅ 推奨：サーバーサイドリダイレクト
export async function POST(req: NextRequest) {
  const session = await client.checkout.createSession({ ... });
  return NextResponse.redirect(session.checkoutUrl);
}

// ✅ これも可：クライアントサイドリダイレクト
const { checkoutUrl } = await res.json();
window.location.href = checkoutUrl;

// ❌ 避けるべき：window.open — Safariとモバイルブラウザにブロックされる
window.open(checkoutUrl, "_blank"); // ブロックされます！
```

支払い後、顧客はあなたの`successUrl`にリダイレクトされます。成功ページで支払いを検証するには、`{SESSION_ID}`プレースホルダーを使用してください。

***

## 顧客メールの事前入力

事前入力してメール入力ステップをスキップ：

```typescript theme={"system"}
const session = await client.checkout.createSession({
  productId: "prod_xxx",
  currency: "USD",
  buyerEmail: "user@example.com",
});
```

**ユースケース：** ユーザーが既にアプリにログインしているため、メールがわかっている場合。

***

## metadataでの追跡

チェックアウトセッションを内部システムに関連付け：

```typescript theme={"system"}
const session = await client.checkout.createSession({
  productId: "prod_xxx",
  currency: "USD",
  metadata: {
    user_id: "usr_abc123",
    campaign: "black_friday_2024",
    referrer: "twitter",
  },
  successUrl: "https://yoursite.com/success",
});
```

Metadata はチェックアウトセッションに保存され、`checkoutSession` GraphQL クエリで取得できます。Webhook への metadata 転送は近日対応予定です。

***

## トライアル付きサブスクリプション

サブスクリプション製品のトライアル期間を有効化：

```typescript theme={"system"}
const session = await client.checkout.createSession({
  productId: "prod_subscription",
  currency: "USD",
  withTrial: true,
  successUrl: "https://yoursite.com/welcome",
});
```

<Note>
  割引コードとシート数量はまだAPI経由でサポートされていません。割引はDashboardで管理してください。
</Note>

***

## 請求先情報付きサブスクリプション

税金計算のために消費者の請求先情報を事前入力：

```typescript theme={"system"}
const session = await client.checkout.createSession({
  productId: "prod_xxx",
  currency: "USD",
  billingDetail: {
    country: "US",
    isBusiness: false,
    state: "CA",
    postcode: "94105",
  },
});
```

***

## 動的成功URL

成功ページにデータを渡す：

```typescript theme={"system"}
const session = await client.checkout.createSession({
  productId: "prod_xxx",
  currency: "USD",
  successUrl: "https://yoursite.com/success?session_id={SESSION_ID}",
});
```

`{SESSION_ID}`は実際のセッションIDに置き換えられ、成功ページで支払いを検証できます。

***

## 完全な例：SaaSアップグレードフロー

SDKを使用してユーザーのサブスクリプションをアップグレードする実際の例：

```typescript theme={"system"}
// app/api/upgrade/route.ts (Next.js App Router)
import { NextRequest, NextResponse } from "next/server";
import { WaffoPancake } from "@waffo/pancake-ts";

const client = new WaffoPancake({
  merchantId: process.env.WAFFO_MERCHANT_ID!,
  privateKey: process.env.WAFFO_PRIVATE_KEY!,
});

export async function POST(req: NextRequest) {
  const { userId, planId, email } = await req.json();

  const session = await client.checkout.createSession({
    productId: planId,
    currency: "USD",
    buyerEmail: email,
    metadata: { user_id: userId, action: "upgrade" },
    successUrl: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?upgraded=true`,
  });

  // サーバーサイドリダイレクト — すべてのブラウザで動作
  return NextResponse.redirect(session.checkoutUrl);
}
```

クライアントサイドでチェックアウトを処理する必要がある場合（例：SPA）：

```typescript theme={"system"}
async function handleUpgrade(planId: string) {
  const res = await fetch("/api/upgrade", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ userId: currentUser.id, planId, email: currentUser.email }),
  });
  const { checkoutUrl } = await res.json();

  // 同じタブでリダイレクト — Safariでも安全
  window.location.href = checkoutUrl;
}
```

***

## パラメータリファレンス

| パラメータ        | 型       | 必須  | 説明                                         |
| ------------ | ------- | --- | ------------------------------------------ |
| `productId`  | string  | はい  | Dashboardからの製品UUID                         |
| `currency`   | string  | はい  | ISO 4217通貨コード（例：`"USD"`）                   |
| `buyerEmail` | string  | いいえ | 消費者メールの事前入力                                |
| `successUrl` | string  | いいえ | カスタム成功リダイレクトURL                            |
| `metadata`   | object  | いいえ | セッションに保存されるカスタムキーバリューデータ（Webhook転送は近日対応予定） |
| `withTrial`  | boolean | いいえ | サブスクリプション製品のトライアル期間を有効化                    |

***

## 次のステップ

<CardGroup cols={2}>
  <Card title="Webhookの処理" icon="webhook" href="/ja/guides/webhooks">
    支払い完了時に通知を受ける
  </Card>

  <Card title="支払いの検証" icon="shield-check" href="/ja/api-reference/webhooks">
    Webhook署名を安全に検証
  </Card>
</CardGroup>
