こんにちは、サイオステクノロジーの佐藤 陽です。
今回はStripeのBillingを使って、Subscriptionの無償期間を実現する方法をご紹介します。
- サブスクリプションの契約から一定期間を無償としたい
- 申し込みから一定期間経ってから金額の請求を開始したい
という実装を行いたい方は是非ご覧ください。
はじめに
Stripe Billing は、サブスクリプションなどの定期的な課金や請求書の発行を簡単に実現するためのツールです。
Billingを利用すると、月次や年次などの継続支払いののロジックを簡単に実装することができます。
日割り計算など、細かい部分までStripe側で全部やってくれるので非常に便利なツールですね。
今回は、このBillingを利用し、申し込み後一定期間を無償とする方法をご紹介します。
サンプルのリクエストコードも併せて紹介するので、是非ご活用ください。
無償期間を扱うユースケース
無償期間を扱う事により、以下の事が実現できるようになります。
- トライアルとして、ユーザーに一定期間無償で使ってもらう
- サービス提供側で、申し込みからサービス提供まで時間を要するため、その期間を無償とする
etc.
割と想定されるようなユースケースなのではないでしょうか?
今回は
申し込みから1週間を無償期間とし、1週間経過後に請求を開始する
という要件を満たす実装を考えてみたいと思います。
実装方法
これを実現する方法としてはいくつか考えられます。
今回は以下の4つを挙げました。
もっといい方法もあるかとも思うので、おすすめの方法があれば是非コメントに書いていってください!
- トライアル機能
- Billing Cycle Anchor & ProrationBehavior=None
- Subscription Schedule
- そもそもSubscriptionを作成しない
案1 : トライアル機能
次はStripeが提供するトライアル機能を使う例です。
これが一番スタンダードな方法なのではないでしょうか?
Subscription作成時にtrial_endを設定することで、トライアルの期間を設定することができます。
APIのリクエストとしては以下のような形となります。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscriptions' \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'customer=cus_OfJPPQQ76K59G5' \ # 対象Customer
-d 'items[0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ # 申し込みを行うPrice
-d 'trial_end={現在時刻+1週間後のunixtimestamp}''
なおこの場合、以下のタイミングで請求書が発行されます
- 申し込み時(0円の請求書)
- トライアル終了時(有償の請求書)
また、最初に発行される0円請求書の品目のところには「Trial」という記載がされます。
またCustomer Portalを利用する場合、顧客に対して「トライアルはmm/ddに終了します」という表記が表示されることも注意です。
無償期間は作りたいけど、顧客に「無償トライアル」というニュアンスでは提供したくない
という要求がある場合、適切な選択肢ではないかもしれません。
ちなみに、トライアル期間は最大2年間設定可能です。
(2年間無償期間を続けることは要件はあまり無いかと思いますが…)
案2 : BillingCycleAnchor+ProrationBehavior=None
次にBillingCycleAnchorとProrationBehaviorを組み合わせて利用するパターンです。
SubscriptionのオブジェクトのパラメータにはBillingCycleAnchorというものがあります。
これは支払日を固定できるパラメータであり、例えば「毎月1日に支払いを行う」といったような設定することができます。
例えば
申し込み日 | 9月15日 |
BillingCycleAnchor(支払日) | 10月1日(毎月1日) |
とした場合を考えます。
まず、Stripeでは先払いがデフォルトなので10月1日に徴収されるのは10月分の料金です。
それでは、この9月15日から10月1日までの利用料金はどのように設定するのでしょうか?
ここで活きてくるのが、Proration Behaviorというパラメータです。
これは日割り計算に関する設定が行えるパラメータで
create_prorations | 日割り計算を行う |
none | 日割り計算を行わない(料金を請求しない) |
のいずれかを設定できます。
create_prorationsを設定すれば、9月15日から10月1日までの約半月分の料金が、申し込み日の9月15日に請求されます。
一方、noneを設定することで、9月15日から10月1日までは料金が請求されず、10月1日に初めて請求されるようになります。
つまり、9月15日から10月1日までは無償となります。
これをうまく利用すると
以下の内容のサブスクリプションを作成することで、1週間の無償期間を実現することができます。
- Create Subscription
- BillingCycleAnchor:申し込み日の1週間後
- ProrationBehavior:none
APIのリクエストとしては以下のような形となります。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscriptions' \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'customer=cus_OfJH6z4pFoq16M' \ # 対象Customer
-d 'items[0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ # 申し込みを行うPrice
-d 'billing_cycle_anchor={現在時刻+1週間後のunixtimestamp}'
-d 'proration_behavior=none'
なおこの場合の注意点として、9月15日において請求書は発行されません。
また、一つ制限がある点としてBillingCycleAnchorが1ヵ月以上先に設定できない事があります。
あくまで支払いのサイクル日を固定するパラメータなので、たしかに1ヵ月以上先に設定するのは想定されませんよね。
そのため、例えば
2ヵ月の無償期間を実現したい
という要件に対しては、この方法は利用することができません。
案3 : Subscription Schedule
次に、Subscription Scheduleを利用する方法です。
「サブスクリプションの作成を1週間後に行う」というスケジュールを立てることで、1週間の無償期間を実現することができます。
Create Scheduleのパラメータとして用意されているstart_dateの値に1週間後の日時を設定します。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules' \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'customer=cus_OfZSLdkwhPxJz7' \ # 対象Customer
-d 'start_date={現在時刻+1週間後のunixtimestamp}' \
-d 'end_behavior=release' \
-d 'phases[0][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ # 申し込みを行うPrice
-d 'phases[0][items][0][quantity]=1' #個数
以下のようにDashboardに表示されました。
なお、このAPIコール時にはSubscriptionScheduleのオブジェクトが生成されるだけであり、Subscriptionオブジェクトは生成されません。
start_dateのタイミングになって初めてSubscriptionオブジェクトが生成されます。
そのためSubscriptionIdを使って内部業務を回したい、という場合にはあまり適していないかもしれません。
また、今回のstart_dateのパラメータに関してですが、以下の説明があります。
When the subscription schedule starts. We recommend using now so that it starts the subscription immediately. You can also use a Unix timestamp to backdate the subscription so that it starts on a past date, or set a future date for the subscription to start on.
start_dateにはnowを使うことを推奨している、という記載があります。
ScheduleとSubscriptionの作成タイミングがずれることによって色々複雑さが増すからでしょうか?
この案3については、Stripeの推奨しない方法なのかもしれません。
案3・改 : 0円Priceを利用する
案3において
- Subscriptionのオブジェクトが生成されない
- start_dateの値がStripeの推奨するnowではない
という2点を懸念挙げましたが、これを解消する方法もあります。
それが価格が0円のPriceを作成し、それを無償期間として扱う方法です。
つまり
- 0円のPriceを作成する(同Productでも別Productでも可)
- 申し込み時に、0円のPriceを元にSubscription&SubscriptionScheduleを作成する
- 1週間後に0円のPriceから有償のPriceへUpdateするようにScheduleを組む
という流れです。
これにより、最初に挙げた2つの懸念点を解消することができます。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules' \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'customer=cus_OfZxIGN1gGlycW' \ # 対象Customer
-d 'start_date=now' \ # 今すぐ開始
-d 'end_behavior=release' \
-d 'phases[0][items][0][price]=price_1NryeRE7qHO17eJUJjAlaPcK' \ # 0円Price
-d 'phases[0][items][0][quantity]=1' \ #個数
-d 'phases[0][end_date]={現在時刻+1週間後のunixtimestamp}' \
-d 'phases[1][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ # 申し込みを行うPrice
-d 'phases[1][items][0][quantity]=1' \
-d 'phases[1][iterations]=1'
ただこれはコードの複雑度も増しますし、0円Priceという「実装のためだけのPriceオブジェクト」を生成することになるため、あまりお勧めは出来ません。
要件的に「どうしてもこれが必要だ!」という場合に採用を検討してみてください。
案4 : 金額を徴収するまでSubscriptionを作成しない
案3に近いですが「そもそもサブスクリプションを作成しない」という方法です。
Subscriptionを作成するということは、Customerが存在しているはずです。
この時、
と内部的に定義します。
そして内部処理や無償期間が終わったタイミングで、初めて通常通りSubscriptionを新規作成します。
この時注意するのが、
- 実際にサービス提供開始する時に、サブスクリプションの作成を忘れないようにする必要がある
- 複数Subscriptionを契約するようなケースの場合の判定に注意する
といった所だと思います。
1 Customerに対して1 Subscriptionしか存在していない場合は
シンプルな形で実現できるため、選択肢として挙がってくるかと思います。
支払い方法
支払い方法に関する注意点を述べます。
今回は、クレジットカードの支払いを想定して実装しています。
通常、有償のサブスクリプションを作成する場合は有効なカードが紐づいている必要があります。
ただし、今回挙げた方法を用いて無償期間を実現することによって
カードの紐づけ無しでもサブスクリプションを作成することが可能です。
無償期間が終わるとどうなるかというと、カードが紐づいていないため支払いが失敗します。
支払い失敗時の挙動に関しては、Billingの設定項目で設定が可能ですが
そもそも予期せぬ失敗は防ぎたいところですね。
対応としては
- SetupIntentを使って支払い方法を登録してもらう
- Customer Portalを利用して支払い方法を登録してもらう
などが考えられます。
事前に対応して、予期せぬ支払いエラーを防ぐようにしましょう。
またトライアルに関しては、この辺りの情報がドキュメントにまとまっていたのでこちらもご覧ください。
どう選択していくか
いずれの方法でも無償期間の実現は可能かと思うので、あとは要件に合わせて選択してみてください。
判断基準としては、以下のような項目かと思います
- 無償期間の期間はどれくらいか
- 無償期間の請求書が必要か
- Trial期間であることを意識させてもよいか
- SubscriptionのObjectを作成したいか
- 1人のCustomerに対して複数のSubscriptionが紐づくことがあるか
- その他、ビジネス要件や内部処理の事情
コンプライアンス
今回例に挙げたような無償期間に対しては、コンプライアンス要件が存在しています。
Stripeのドキュメントにもまとまっているので、ご一読ください。
まとめ
今回はStripeのBillingを利用し、Subscriptionの無償期間を実装してみました。
方法としてはいくつかあり、それぞれ一長一短があるため要件に適したものを選んでみてください。
また、おそらく今回紹介した方法以外にも無償期間を実現する方法はあると思うので、
おススメの方法があれば是非コメントに書いてください!
ではまた!