サブスクリプションの実装を構築する
Appearance API でカスタマイズします。
Stripe Billing の利用をご希望の場合
無料トライアル、請求サイクルの起点、比例配分などのサブスクリプション機能の管理を可能にする Payment Element のシステムを開発しています。詳細については、決済ページを構築する ガイドをご覧ください。
このガイドで、固定価格のサブスクリプションを販売する方法をご確認ください。Payment Element を使用して、アプリケーションに埋め込むカスタムの決済フォームを作成します。
カスタムの支払いフォームを作成しない場合は、Checkout に実装することもできます。一連の導入手順を説明している実践的なガイドについては、Billing のクイックスタートをご覧ください。
実装をコーディングする準備ができていなくても、基本的なサブスクリプションをダッシュボードから手動で設定できます。また、Payment Links を使用して、コードを一切記述せずにサブスクリプションを設定することもできます。何を決定する必要があり、どのようなリソースが必要なのかを把握するには、実装の設計方法をご覧ください。
構築する内容
このガイドでは以下の方法について説明します。
- 商品カタログを構築して、ビジネスをモデル化する。
- 顧客を作成する登録プロセスを構築します。
- サブスクリプションを作成して、支払い情報を収集します。
- 支払いとサブスクリプションのステータスをテストして、モニタリングします。
- 顧客がプランを変更したりサブスクリプションをキャンセルしたりできるようにします。
Stripe でモデル化する方法
サブスクリプションは、インボイスと PaymentIntents を自動的に作成することによって請求業務をシンプルにします。サブスクリプションを作成して有効化するには、まず販売対象をモデル化する商品と、請求する期間と金額を決定する価格を作成する必要があります。毎回の継続支払いの実行に使用される決済手段を格納する Customer (顧客) も必要です。
API オブジェクトの定義
Stripe を設定する
任意の Stripe クライアントをインストールします。
次に Stripe CLI をインストールします。CLI は Webhook のテストを提供します。これを実行すると Stripe への API コールを実行できます。このガイドの後続セクションでは、CLI を使った料金体系モデルの設定方法を紹介します。
その他のインストールオプションについては、Stripe CLI を使ってみるをご覧ください。
顧客を作成するクライアントおよびサーバー
Stripe では、各サブスクリプションに顧客が必要です。アプリケーションのフロントエンドでユーザーから必要な情報を収集し、それをバックエンドに渡します。
住所の詳細を収集する必要がある場合、住所 Element を使用すると顧客の配送先住所または請求先住所を収集できます。住所 Element の詳細については、住所 Element ページをご覧ください。
<form id="signup-form"> <label> Email <input id="email" type="email" placeholder="Email address" value="test@example.com" required /> </label> <button type="submit"> Register </button> </form>
const emailInput = document.querySelector('#email'); fetch('/create-customer', { method: 'post', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: emailInput.value, }), }).then(r => r.json());
サーバーで、Stripe の Customer オブジェクトを作成します。
サブスクリプションを作成するクライアントおよびサーバー
注
最初にサブスクリプションを作成せずに Payment Element をレンダリングする場合は、インテントを作成する前に支払いの詳細を収集するをご覧ください。
新しい顧客がプランを選択してからサブスクリプションを作成できるようにします。このガイドでは、顧客は基本またはプレミアムから選択します。
フロントエンドで、選択した価格 ID と顧客レコードの ID をバックエンドに渡します。
fetch('/create-subscription', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ priceId: priceId, customerId: customerId, }), })
バックエンドで、payment_behavior=default_incomplete
を使用して、ステータスが incomplete
のサブスクリプションを作成します。次に、サブスクリプションの最初の Payment Intent からの client_secret
をフロントエンドに返して、支払いを完了します。
支払いが成功したときに決済手段をデフォルトとして保存するには、save_default_payment_method を on_subscription
に設定します。デフォルトの決済手段を保存すると、その後のサブスクリプションの決済の成功率が高くなります。
注
多通貨の Price を使用している場合、currency パラメーターを使用して、サブスクリプションに使用する Price の通貨を指定します (currency
パラメーターを省略すると、サブスクリプションは Price のデフォルトの通貨を使用します)。
この時点でサブスクリプションは inactive
であり、支払いを待っています。次に示すのはレスポンスの例です。強調表示されているのは保存が必要な最小限のフィールドですが、アプリケーションが頻繁にアクセスするフィールドをすべて保存します。
{ "id": "sub_JgRjFjhKbtD2qz", "object": "subscription", "application_fee_percent": null, "automatic_tax": { "enabled": false }, "billing": "charge_automatically", "billing_cycle_anchor": 1623873347, "billing_thresholds": null,
支払い情報を収集するクライアント
Stripe Elements を使用して支払いの詳細を収集し、サブスクリプションを有効化します。Elements は、お使いのアプリケーションのデザインに合わせてカスタマイズできます。
注
Payment Element は、多様な決済手段で必要な決済の詳細をすべて安全に収集します。現在、Payment Element とサブスクリプションの両方でサポートされている決済手段は、クレジットカード、Link、SEPA ダイレクトデビット、BECS ダイレクトデビットです。
Stripe Elements を設定する
Payment Element は Stripe.js の機能として自動的に使用できるようになります。決済ページに Stripe.js スクリプトを含めるには、HTML ファイルの head
にスクリプトを追加します。常に js.stripe.com から Stripe.js を直接読み込むことにより、PCI 準拠が維持されます。スクリプトをバンドルに含めたり、そのコピーを自身でホストしたりしないでください。
<head> <title>Checkout</title> <script src="https://js.stripe.com/v3/"></script> </head> <body> <!-- content here --> </body>
決済ページで以下の JavaScript を使用して、Stripe のインスタンスを作成します。
// Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe(
);'pk_test_TYooMQauvdEDq54NiTphI7jx'
Payment Element をページに追加する
Payment Element を本番で使用するには、支払いページへの配置場所が必要です。支払いフォームで、一意の ID を持つ空の DOM ノード (コンテナー) を作成します。
<form id="payment-form"> <div id="payment-element"> <!-- Elements will create form elements here --> </div> <button id="submit">Subscribe</button> <div id="error-message"> <!-- Display error message to your customers here --> </div> </form>
上記のフォームが読み込まれたら、Payment Element のインスタンスを作成して、それをコンテナーの DOM ノードにマウントします。サブスクリプションの作成ステップで、フロントエンドに client_secret
を渡しています。この値を、Elements のインスタンスを作成する際にオプションとして渡します。
const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 5 const elements = stripe.elements(options); // Create and mount the Payment Element const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element');
Payment Element によって動的なフォームが表示され、顧客はここで決済手段を選択できます。このフォームでは、顧客が選択した決済手段で必要な決済の詳細のすべてが自動的に収集されます。
(オプション) Payment Element の設定
- 自社サイトのデザインに合わせて Payment Element をカスタマイズするには、Elements のインスタンスを作成する際に Appearance (デザイン) オブジェクトを
options
に渡します。 - 継続支払い、自動再読み込み、後払いに対応するために、マーチャントトークンを返すよう Apple Pay インターフェイスを設定します。
支払いを完了する
stripe.confirmPayment
を使用して、Payment Element からの詳細を指定した支払いを完了し、サブスクリプションを有効化します。これにより PaymentMethod が作成され、不完全なサブスクリプションの最初の PaymentIntent が確定され、その結果支払いが実行されます。支払いに強力な顧客認証 (SCA) が必要とされる場合は、PaymentIntent の確定前に Payment Element で認証プロセスが処理されます。
支払いの完了後に Stripe がユーザーをリダイレクトする場所を指定するには、この関数に return_url を指定します。ユーザーは、最初に銀行のオーソリページなどの中間サイトにリダイレクトされてから、return_url
にリダイレクトされる場合があります。カード支払いでは、支払いが正常に完了するとすぐに return_url
にリダイレクトされます。
const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: "https://example.com/order/123/complete", } }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } });
顧客が支払いを送信すると、Stripe は顧客を return_url
にリダイレクトし、以下の URL クエリーパラメーターを含めます。返品ページでは、これらを使用して PaymentIntent のステータスを取得し、顧客に支払いステータスを表示できます。
return_url
を指定する際に、返品ページで使用する独自のクエリパラメーターを追加することもできます。
パラメーター | 説明 |
---|---|
payment_intent | PaymentIntent の一意の識別子。 |
payment_intent_client_secret | PaymentIntent オブジェクトの client secret。 |
顧客が自社のサイトにリダイレクトされたら、payment_intent_client_secret
を使用して PaymentIntent をクエリし、顧客に取引ステータスを表示できます。
注意
顧客のブラウザーセッションを追跡するツールを利用している場合、リファラー除外リストに stripe.com
ドメインの追加が必要になる場合があります。リダイレクトを行うと、一部のツールでは新しいセッションが作成され、セッション全体の追跡ができなくなります。
クエリパラメーターのいずれか 1 つを使用して PaymentIntent を取得します。PaymentIntent のステータスを調べて、顧客に表示する内容を決定します。また、return_url
を指定するときに独自のクエリパラメーターを追加することもできます。このパラメーターはリダイレクトプロセスの間は維持されます。
// Initialize Stripe.js using your publishable key const stripe = Stripe(
); // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => { const message = document.querySelector('#message') // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': message.innerText = 'Success! Payment received.'; break; case 'processing': message.innerText = "Payment processing. We'll update you when payment is received."; break; case 'requires_payment_method': message.innerText = 'Payment failed. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; default: message.innerText = 'Something went wrong.'; break; } });'pk_test_TYooMQauvdEDq54NiTphI7jx'
Webhook をリッスンするサーバー
組み込みを完了するには、Stripe から送信される Webhook を処理する必要があります。Webhook は、サブスクリプションによって新しいインボイスが作成されるなど、Stripe 内の状態が変化するたびにトリガーされるイベントです。アプリケーションで、Webhook イベントを含む POST リクエストを受け取る HTTP ハンドラーを設定し、イベントの署名を検証します。
開発中は、Stripe CLI を使用して Webhook を監視し、アプリケーションに転送します。開発アプリの実行中に、新しい端末で以下を実行します。
stripe listen --forward-to localhost:4242/webhook
本番環境では、ダッシュボードで Webhook エンドポイント URLを設定するか、Webhook Endpoints API を使用します。
いくつかのイベントをリッスンして、このガイドの残りのステップを完了します。サブスクリプション固有の Webhook の詳細については、サブスクリプションのイベントをご覧ください。
サービスへのアクセスを提供するクライアントおよびサーバー
ここまででサブスクリプションが有効になりました。次は、ユーザーがサービスにアクセスできるようにします。これには、customer.subscription.created
、customer.subscription.updated
、customer.subscription.deleted
の各イベントをリッスンします。これらのイベントは、Subscription オブジェクトを渡し、このオブジェクトには、サブスクリプションが有効か、期日超過か、キャンセルされたかを示す status
フィールドが含まれます。ステータスの一覧については、サブスクリプションのライフサイクルをご覧ください。
Webhook ハンドラーで、以下を実行します。
- サブスクリプションのステータスを確認します。
active
の場合、ユーザーは商品の支払いを実行しています。 - 顧客が登録している商品を確認し、サービスへのアクセス権を付与します。価格ではなく商品を確認することにより、料金体系や請求間隔の変更が必要になった場合に、柔軟に対応できます。
product.id
、subscription.id
およびsubscription.status
を、すでに保存されているcustomer.id
とともにデータベースに保存します。アプリケーションでユーザーに対して有効にする機能を決定する際に、このレコードを確認します。
サブスクリプションの状態は、存続期間のどの時点でも変化する可能性があります。これは、アプリケーションが Stripe への直接の呼び出しを行っていない場合でも同様です。たとえば、クレジットカードの有効期限が切れて更新が失敗した場合、サブスクリプションは期日超過の状態になります。また、カスタマーポータルを実装している場合、ユーザーが直接アプリケーションを開かずにサブスクリプションをキャンセルすることがあります。ハンドラーを正しく実装することで、常にアプリケーションを Stripe と同期した状態に維持できます。
サブスクリプションをキャンセルするクライアントおよびサーバー
顧客にサブスクリプションのキャンセルを許可するのは一般的です。この例では、アカウントの設定ページにキャンセルオプションを追加します。
サブスクリプションのキャンセル機能が設定されたアカウント設定
function cancelSubscription(subscriptionId) { return fetch('/cancel-subscription', { method: 'post', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ subscriptionId: subscriptionId, }), }) .then(response => { return response.json(); }) .then(cancelSubscriptionResponse => { // Display to the user that the subscription has been canceled. }); }
バックエンドで、フロントエンドから呼び出すエンドポイントを定義します。
アプリケーションが customer.subscription.deleted
イベントを受信します。
サブスクリプションがキャンセルされたら、データベースを更新して以前に保存された Stripe サブスクリプション ID を削除し、サービスへのアクセスを制限します。
キャンセルされたサブスクリプションを、再びアクティブにすることはできません。代わりに、顧客から更新された請求情報を収集し、顧客のデフォルトの支払い方法を更新して、既存の顧客レコードから新しいサブスクリプションを作成します。
組み込みをテストする
決済手段をテストする
次の表を使用して、さまざまな決済手段とシナリオをテストします。
決済手段 | シナリオ | テスト方法 |
---|---|---|
BECS ダイレクトデビット | 顧客が BECS ダイレクトデビットによる支払いに成功します。 | 口座番号 900123456 と BSB 000-000 を使用して、フォームに入力します。確定された PaymentIntent のステータスは、まず processing に移行し、3 分後に succeeded ステータスに移行します。 |
BECS ダイレクトデビット | 顧客の支払いが account_closed エラーコードで失敗します。 | 口座番号 111111113 と BSB 000-000 を使用して、フォームに入力します。 |
クレジットカード | カード支払いは成功し、認証は要求されません。 | クレジットカード番号 4242 4242 4242 4242 と、任意の有効期限、セキュリティコード、郵便番号を使用してクレジットカードフォームに入力します。 |
クレジットカード | カード決済で認証が要求されます。 | クレジットカード番号 4000 0025 0000 3155 と、任意の有効期限、セキュリティコード、郵便番号を使用してクレジットカードフォームに入力します。 |
クレジットカード | カードが insufficient_funds などの拒否コードで支払い拒否されます。 | クレジットカード番号 4000 0000 0000 9995 と、任意の有効期限、セキュリティコード、郵便番号を使用してクレジットカードフォームに入力します。 |
SEPA ダイレクトデビット | 顧客が SEPA ダイレクトデビットによる支払いに成功します。 | 口座番号 AT321904300235473204 を使用して、フォームに入力します。確定された PaymentIntent のステータスはまず、processing に移行し、3 分後に succeeded ステータスに移行します。 |
SEPA ダイレクトデビット | 顧客の Payment Intent のステータスが、processing から requires_payment_method に移行します。 | 口座番号 AT861904300235473202 を使用して、フォームに入力します。 |
イベントをモニターする
Webhook を設定して、アップグレードとキャンセルなどのサブスクリプションの変更イベントをリッスンします。サブスクリプションの Webhook に関する詳細は、ガイドをご覧ください。イベントの表示は、ダッシュボード、または Stripe CLI を使用して行うことができます。
詳細については、Billing の実装のテストをご覧ください。
Stripe について顧客に開示する
Stripe は顧客の Elements とのやり取りに関する情報を収集して、サービスを提供し、不正利用を防止し、サービスを向上します。これには、Cookie と IP アドレスを使用して、1 つの決済フローセッションで顧客に表示する Elements を特定することが含まれます。Stripe がこのような方法でデータを使用するために必要なすべての権利と同意について開示し、これらを取得することはお客様の責任です。詳細については、プライバシーセンターをご覧ください。