本文へ

ガイド

レシピ:SaaS サブスク

暗号資産での月額・年額プラン。期間ごとにリマインダー付きの請求書。アプリは誰にアクセス権があるかを Perly Pay に尋ねます。

Markdown で開く

暗号資産はウォレットから引き落とせないため、サブスクリプションは請求書で更新します:期間の終わる前に購入者は次の請求書を受け取り、支払われるまでリマインダーが届きます。自動引き落としはありません。アプリは日数を自分で数えず、entitlements.check に尋ねます。

アシスタントと一緒に:このレシピは、Perly Pay プラグインの sell-subscription スキルがあなたのプロジェクトで実行します。動くサンプルは、プラグインのリポジトリの examples/saas-subscription(MIT)です。

仕組み

  1. 1

    プラン

    model: "subscription" と recurring.interval(month、year…)を持つ商品と価格。任意でトライアルと猶予日。

  2. 2

    サブスクリプション

    ユーザーを顧客にしたその価格の請求書が、サブスクリプションと最初の請求書を作ります。その支払いでプランが有効になります。

  3. 3

    機能へのアクセス

    entitlements.check({ customer_external_id, product }) → has_access と ends_at。サーバーで、訪問ごとに、または短いキャッシュ付きで。

  4. 4

    受け取る

    invoice.fulfilled は最初の支払いと毎回の更新。subscription.past_due、subscription.unpaid、subscription.ended で警告し、閉じます。

  5. 5

    購入者による管理

    購入者ポータルへのリンク(portalSessions.create):未払いの更新の支払い、前払い、解約。

Subscribe, then gate
const invoice = await pay.invoices.create(
  { line_items: [{ price: PRO_MONTHLY }], customer: customer.id, metadata: { user: userId }, return_url },
  { idempotencyKey: `subscribe-${userId}-${today}` },
);
redirect(invoice.url); // invoice.subscription is the new subscription

const { has_access } = await pay.entitlements.check({ customer_external_id: userId, product: PRO });

猶予日、プランの変更、ステータスは Subscriptions and reminders に。

サンプルを動かす

  1. 1

    インストール

    examples/saas-subscription で npm install(Node 20.12+)。

  2. 2

    キー

    .env.example を .env にコピーし、PERLY_PAY_SECRET_KEY にテストキー(sk_test_…)を書きます。

  3. 3

    準備

    npm run setup があなたのキーで商品と価格を作成し、.env 用にその ID を表示します。

  4. 4

    起動

    README のとおり npm start(または npm run dev)。

  5. 5

    ウォレットなしで支払う

    トップページで申し込み、請求書で Simulate payment を押し、/pro?user=you@example.com を開きます:期間の終わりまで Pro が開きます。

落とし穴

  • 「ウォレットから自動で引き落とします」と約束すること。何も引き落とされません。「請求書で更新」と伝えてください。
  • 顧客のメールがない、または架空のもの:更新の請求書とリマインダーはそこに届きます。
  • 1 分遅れただけでアクセスを閉じること。past_due(猶予日の範囲内)をどう扱うか決めてください。
  • 購入者が支払いから戻ってきた時点でアクセスを開くこと。「支払い済み」を意味するのは、検証済みの Webhook invoice.fulfilled か、サーバーからの entitlements.check だけです。