Skill をコピー
Skill ファイルを開き、全内容をクリップボードにコピーします。
Skill をダウンロード (.md)
Skill ファイルをダウンロードして、AI コーディングエージェントや IDE に追加します。
@waffo/pancake-ts は Waffo Pancake 決済 API のサーバーサイド TypeScript クライアントです。リクエスト署名、チェックアウトセッション作成、Webhook 検証、GraphQL クエリを処理します。
よくある落とし穴 — 最初にお読みください
統合を壊すミスをまとめています。コードを書く前に必ず目を通してください。| 落とし穴 | なぜ壊れるか | 修正方法 |
|---|---|---|
| Webhook ボディを JSON として読み取る | request.json() はボディを再シリアライズし、空白が変わります。署名検証は元の生バイト列と比較します。 | 常に request.text()(App Router / Hono)または express.raw()(Express)を使用してください。 |
| localtunnel を Webhook に使用する | localtunnel はカスタム HTTP ヘッダーを削除します。X-Waffo-Signature がハンドラーに届きません。 | 代わりに cloudflared tunnel --url http://localhost:3000 を使用してください。 |
.publish() を忘れる | 商品はデフォルトで test 環境に作成されます。未公開商品の本番チェックアウトセッションはサイレントに失敗します。 | 本番稼働前に client.onetimeProducts.publish({ id }) または client.subscriptionProducts.publish({ id }) を呼び出してください。 |
GraphQL で result.data ではなく result にアクセスする | GraphQL クライアントは { data: T | null, errors?: [...] } を返します。フィールドは .data の下にネストされています。 | 常に分割代入してください:const stores = result.data?.stores ?? []。 |
| セントではなくドル金額を渡す | すべての金額は最小通貨単位を使用します。$29.00 = 2900、¥1000 = 1000(JPY は小数なし)。 | 再確認:$9.99 の商品を作成する場合、9.99 ではなく 999 を渡してください。 |
GraphQL 変数で $id: ID! を使用する | バックエンドは $id: String! を使用し、$id: ID! ではありません。間違った型を使うとサイレントに null が返されます。 | ID 変数は常に String! として宣言してください。 |
グループ更新の productIds は完全置換 | subscriptionProductGroups.update({ productIds: [...] }) はリスト全体を置換します — 追加ではありません。 | 新規追加分だけでなく、常に完全な希望リストを渡してください。 |
ユースケース
Waffo Pancake は merchant-of-record 決済プラットフォームです。SDK は以下のようなプロジェクトに適しています:- SaaS サブスクリプション課金 — 月額/年額プラン、アップグレード/ダウングレード(例:Free/Pro/Team ティア)
- デジタル商品販売 — 電子書籍、テンプレート、コース、ライセンスの単発購入
- 従量課金 — ダウンロード、API コール、レポート生成ごとに課金
- ハイブリッドモデル — サブスクリプション+単発購入の組み合わせ
- マルチ通貨対応 — 通貨ごとの価格設定と自動税務処理
| プロジェクトタイプ | 課金モデル | 作成する商品 |
|---|---|---|
| AI Skills マーケットプレイス | 都度ダウンロード + Pro サブスク | 単発商品1個($0.99/ダウンロード)+ サブスク商品2個(月額/年額) |
| オンラインコースプラットフォーム | コース単位の単発購入 | コースごとに単発商品1個(199) |
| SaaS(Starter/Pro/Enterprise) | サブスクティア | サブスク商品3個 + プラン切替用の商品グループ1個 |
| デザインテンプレートショップ | テンプレート単位の単発購入 | テンプレートごとに単発商品1個、または priceSnapshot で価格を上書きする共有商品1個 |
| API クレジットサービス | クレジットパック + サブスク | パックごとに単発商品1個 + 月間クォータ用サブスク |
インストールとセットアップ
PEM 鍵の取り扱い
エスケープ改行(最もシンプル):クイックスタート:ゼロから作成
クイックスタート:既存商品を使用
ダッシュボードですでに商品を作成済みの場合、Product ID をコピーしてそのままチェックアウトへ:API リファレンス
ストア
単発商品
digital_goods | saas | software | ebook | online_course | consulting | professional_service
サブスクリプション商品
サブスクリプション商品グループ
グループは共有トライアルとサブスクリプション商品間のプラン切替を可能にします。チェックアウトセッション
サブスクリプションのキャンセル
GraphQL クエリ
読み取り専用。ID 変数にはString! を使用してください(ID! ではありません)。
Webhook 検証
SDK には両環境の公開鍵が埋め込まれています。検証は関数呼び出し一回で完了します。Next.js App Router
Express
Hono
検証オプション
イベントタイプ
| イベント | トリガー |
|---|---|
order.completed | 単発決済成功 |
subscription.activated | 初回サブスク決済成功 |
subscription.payment_succeeded | 更新決済成功 |
subscription.canceling | キャンセル開始(期間終了まで有効) |
subscription.uncanceled | キャンセル撤回 |
subscription.updated | プラン変更(アップグレード/ダウングレード) |
subscription.canceled | サブスクリプション完全終了 |
subscription.past_due | 更新決済失敗 |
refund.succeeded | 返金完了 |
refund.failed | 返金失敗 |
イベント構造
Webhook URL の設定
エラーハンドリング
errors[0] が根本原因(最深層)、errors[n] が最も外側の呼び出し元です。
開発のヒント
- Webhook トンネリング — localtunnel ではなく
cloudflaredを使用してください(落とし穴の表を参照)。
-
冪等性は自動 — SDK は
merchantId + path + bodyから決定論的なキーを生成します。リトライは安全です。 -
Test → Prod ワークフロー — 商品はデフォルトで test 環境に作成されます。
.publish()で本番環境にプロモートします。Webhook イベントにはmode: "test" | "prod"が含まれるため、ハンドラーで区別できます。
クイックスタートチェックリスト
npm install @waffo/pancake-tsWAFFO_MERCHANT_IDとWAFFO_PRIVATE_KEY環境変数を設定new WaffoPancake({ merchantId, privateKey })でクライアントを初期化- ストアを作成または参照
- 商品を作成または参照
- チェックアウトを作成:
client.checkout.createSession(...)→checkoutUrlにリダイレクト - Webhook を処理:
verifyWebhook(rawBody, sig)— 必ずrequest.text()を使用 - Webhook URL を設定:
client.stores.update({ webhookSettings: ... })