商品バージョン、価格、通貨を固定するチェックアウトセッションを作成します。これは単発商品とサブスクリプション商品の両方のチェックアウトフローの最初のステップです。
一般的なフローは以下の通りです。
- マーチャントがチェックアウトセッションを作成(サーバーサイド)
- フロントエンドに
checkoutUrl を返す
- 消費者がリンクをクリックしてホスティングされたチェックアウトページに移動
- 消費者が請求情報を入力し、税額をプレビューし、注文を完了
POST /v1/actions/checkout/create-session
認証: API Key または Store Slug
リクエストボディ(API Key)
| フィールド | 型 | 必須 | 説明 |
|---|
productId | string | Yes | 商品 ID(Short ID フォーマット PROD_xxx) |
currency | string | Yes | ISO 4217 通貨コード(例:USD、EUR、JPY) |
priceSnapshot | object | No | セッション作成時に価格を上書き(API Key のみ、以下参照) |
withTrial | boolean | No | トライアル期間を有効にする(サブスクリプション商品のみ) |
buyerEmail | string | No | チェックアウトページで消費者のメールを事前入力 |
billingDetail | object | No | 請求情報を事前入力(以下参照) |
successUrl | string | No | 決済成功後のリダイレクト URL を上書き |
expiresInSeconds | number | No | セッション TTL(秒単位、デフォルト:2700 = 45 分、API Key のみ) |
darkMode | boolean | No | チェックアウトページのダークモードを有効にする |
metadata | object | No | セッションに添付するカスタムキー値ペア |
orderMerchantExternalId | string | No | マーチャント業務側の注文識別子(最大 128 文字) |
リクエストボディ(Store Slug)
| フィールド | 型 | 必須 | 説明 |
|---|
productId | string | Yes | 商品 ID(Short ID フォーマット PROD_xxx) |
currency | string | Yes | ISO 4217 通貨コード |
buyerEmail | string | No | 消費者のメールを事前入力 |
billingDetail | object | No | 請求情報を事前入力(以下参照) |
successUrl | string | No | 決済成功後のリダイレクト URL を上書き |
darkMode | boolean | No | チェックアウトページのダークモードを有効にする |
Store Slug 認証では、クライアントサイドからの価格改ざんやセッション操作を防止するため、priceSnapshot、expiresInSeconds、metadata、orderMerchantExternalId、withTrial はサポートされません(黙って無視されます)。
ID 命名規約:同じフラット双キー名(checkout 側の orderMerchantExternalId、返金チケット側の refundTicketMerchantExternalId)が、リクエストボディ、webhook ペイロード、そしてその値を保持する全ての GraphQL 型を通じて使用されます — checkout 作成時に書き込んだ値は Order、Payment、Refund、webhook ペイロードのいずれからも同じフィールド名で読み戻せます。
Price Snapshot オブジェクト
| フィールド | 型 | 必須 | 説明 |
|---|
amount | string | Yes | 表示フォーマット文字列としての価格(例:"29.00" = $29.00) |
taxIncluded | boolean | Yes | 金額に税が含まれているかどうか |
taxCategory | string | Yes | 税計算用のカテゴリ(例:saas、digital_goods) |
Billing Detail オブジェクト
| フィールド | 型 | 必須 | 説明 |
|---|
country | string | Yes | ISO 3166-1 alpha-2 国コード(例:US、JP、DE) |
isBusiness | boolean | Yes | 法人購入かどうか |
postcode | string | No | 郵便番号 |
state | string | 条件付き | US と CA で必須(例:CA、NY、ON) |
businessName | string | 条件付き | isBusiness が true の場合に必須 |
taxId | string | 条件付き | EU 諸国で isBusiness が true の場合に必須(VAT 番号) |
セッションロック
チェックアウトセッション作成時に以下の値がロックされ、セッションの有効期間中は変更できません。
productVersionId、productName、priceInfo、storeName、billingPeriod、withTrial、theme、buyerEmail、billingDetail
メールアドレスの正規化:すべてのメールフィールド(email / buyerEmail / contactEmail)はサーバー側で trim().toLowerCase() により正規化されてから保存・キャッシュ・下流呼び出しに使用されます。Foo@Bar.COM と foo@bar.com は同一アカウントとして扱われます。
リクエスト例
import { WaffoPancake, CheckoutSessionProductType } 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({
storeId: "STO_2D5F8G3H1K4M6N9P",
productId: "PROD_7J3K5L8M2N4P6Q9R",
productType: CheckoutSessionProductType.Onetime,
currency: "USD",
buyerEmail: "customer@example.com",
successUrl: "https://example.com/thank-you",
});
console.log(session.sessionId); // "cs_550e8400-e29b-41d4-a716-446655440000"
console.log(session.checkoutUrl); // "https://checkout.waffo.ai/..."
console.log(session.expiresAt); // "2026-01-22T10:30:00.000Z"
成功レスポンス (200)
{
"data": {
"sessionId": "cs_550e8400-e29b-41d4-a716-446655440000",
"checkoutUrl": "https://checkout.waffo.ai/my-store-abc123/checkout/cs_550e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-01-22T10:30:00.000Z"
}
}
レスポンスフィールド
| フィールド | 型 | 説明 |
|---|
sessionId | string | Checkout Session ID(cs_ + UUID フォーマット、Short ID ではない) |
checkoutUrl | string | 消費者をホスティングされたチェックアウトページにリダイレクトするための完全な URL |
expiresAt | string | セッションが期限切れになる ISO 8601 タイムスタンプ |
エラー
リトライポリシー:4xx は一切リトライしない — リクエストを修正してから再送信。5xx は指数バックオフでリトライ(5s 開始、最大 3 回)。
| ステータス | errors[0].message | 意味 | 推奨処理 |
|---|
| 400 | Missing or invalid header: x-context-environment | environment ヘッダーが欠落、または test / prod 以外 | ヘッダーを修正して再送信 |
| 400 | Invalid JSON body | リクエストボディが有効な JSON ではない | ボディを修正して再送信 |
| 400 | Missing required fields: productId, currency | productId または currency が欠落 | ボディを修正して再送信 |
| 400 | Invalid currency format: "X". Must be 3 uppercase letters (e.g., "USD", "EUR", "JPY") | 通貨コードが 3 文字の大文字ではない(ISO 4217) | 有効な ISO 4217 コードを使用して再送信 |
| 400 | Invalid billingDetail | 請求情報のバリデーションに失敗(例:US で state が欠落) | billingDetail を修正して再送信 |
| 400 | Expected format: PROD_xxx, got "..." | productId Short ID のデコード失敗 | productId のフォーマットを修正して再送信 |
| 400 | orderMerchantExternalId must not be empty | 指定後 trim で空になる | フィールドを省略するか、空でない値を指定 |
| 400 | orderMerchantExternalId must be at most 128 characters | 値が 128 文字を超過 | 128 文字以内に短縮 |
| 400 | Currency X is not supported for this product | 商品が要求された通貨の price snapshot を持たない | 商品がサポートする通貨を使用 |
| 401 | Unauthorized | API Key 署名が無効、または Store Slug が認識されない | 認証ヘッダーを確認 |
| 403 | Store is not active | ストアステータスが active でない | 先にストアを有効化 |
| 403 | Store is not approved for production payments | ストアが prod 環境承認を得ていない | test 環境を使用するか、ストア承認を取得 |
| 403 | Product does not belong to this store | 商品が訪問中のストアに属していない | 商品/ストアの組み合わせを確認 |
| 404 | Store not found | スラッグに一致するストアがない | スラッグと environment を確認 |
| 404 | Product not found | 商品が存在しない | productId を確認 |
| 404 | Product not found or not active for this environment | 該当 environment で商品の active バージョンがない | この environment 用に商品バージョンを有効化 |
| 500 | Internal server error | サーバ側の予期しない障害 | 指数バックオフでリトライ(5s 開始、最大 3 回) |
デフォルトのセッション TTL は 45 分(2700 秒)です。API Key 認証を使用する場合、expiresInSeconds でカスタマイズできます。セッションは作成時に商品バージョンと価格をロックするため、価格変更は既存のセッションに影響しません。