クレジット決済ゲートウェイのStripeを用いたサブスクリプション課金の実装について、プランの組み合わせなどを中心に、できる事とできない事をリスト化します。
決済の登録から実際のInvoice生成までの挙動と、マッチする利用方法なども合わせて書きたいと思います。
また、Stripe APIのバージョンも新しくなり、古いバージョンとの差異についても軽く触れたいと思います。
1つのサブスクリプションの中に、月次と年次、などの期間の異なるアイテムを持たせることはできない。
Stripeでは、例えば年間ライセンスの基本料金と、月額のオプション料金を合わせて一つのサブスクリプション内で登録することはできません。言い換えると、年間ライセンスの支払い時に、月額オプションを12ヶ月分をあわせて決済するということはできません。
prorate 周りの追加と削除時の決済について
最新のバージョン(2020-08-27系 stripe-phpライブラリではv7系)では、prorateパラメータは、proration_behaviorというパラメータになっている。(ただし、prorateパラメータも引き続き使える。)
◯キャンセルまたは、個数マイナス変更時に、prorateが有効になっていると、前払いで確定したサブスクリプション期間の金額から、変更時の残りの日数日割り差額が「繰り越し」状態として残る。これは、次回請求確定時に相殺されるので、意図しない割引となってしまう場合がある。
キャンセルまたは個数マイナス変更については日割りを按分しない、要は「途中キャンセルの返金は無し」を実現するには、proration_behaviorを'none'にする必要がある。
◯年次プランなどの中長期プランにおいて、追加分を即時決済したい場合は、updateで送るパラメータのproration_behaviorを"always_invoice"とすると、残りの日数の日割りのInvoiceが作成される。
ここで注意すべきポイントは、同一期間内で、個数を削減→追加、と変更を繰り返した場合のケース。
仮に従業員が一人辞めて新たに一人増えるケースにおいて、続いて1ユーザー削除、さらに1ユーザー追加した場合、トータルユーザー数は変わらないけれど、追加したユーザー分の日数日割り分が、即時決済されてしまう。
- 削除はprorate:falseで上記追加分の引き継ぎは無し
- 次に1ユーザー追加時には"proration_behavior:always_inovice"で即時決済
これでは、期間の最初に削除したユーザー分の料金は支払い済みにも関わらず、さらに追加料金が発生してしまい、お客様は納得しない。
追加時に、同一期間内に削除があるかどうか判定して、それによって追加決済するかどうか、という計算はできない。
期間内の最終的なユーザーライセンス数によって決済するには、proration_behaviorの値はデフォルトの「create_prorations」とすると、次の期間が始まるタイミングで、今の期間内の「最終的な」追加分をキチンと計算してくれる。
年間ライセンスなどの場合、料金の上乗せが来年になってしまうが、Stripe標準の計算機能を使う場合はどうしようもない。
【期間の途中で、create_prorationsからalways_invoiceに切り替えた場合】
create_prorations設定で、期間内にライセンス追加し、翌期に日割り分が持ち越されている状態で、新たにalways_inoviceでライセンス追加した場合、今回変更のあった部分のみ、即時請求が確定し、過去にcreate_proratsionsで登録された繰越分については、そのまま繰越状態となっており、次の期間の開始時の請求に合算されていた。
商品タイプの「計測された使用量に基づく請求」について
Usage APIを利用し、使用した数量を登録していくタイプの商品になり、当然後払いとなります。年間ライセンスとなると、実際のキャッシュインが一年後とかになるので、注意が必要です。
また、数量は整数となるので、仮にディスク容量などの使用量を販売したい場合は、MB単価などの設定が必要です。
例えば、「1GB当たり〇〇円」などの料金設計は向きません。1.3GBの場合は2GB分の料金(◯◯円×2)といった計算はできません。
そういった商品設計の場合は、使用量に基づく請求ではなく、普通の商品として登録し、自社側で数値計算するのが良さそうです。
バージョンが上がって、plan_idは無くなってprice_idになった
以前はPlanという商品の中にネストされたアイテムがベースになっていたが、最新のバージョン(2020-08-27系 stripe-phpライブラリではv7系)では、名前が変わってPriceという概念になっている。公式のAPIリファレンスでも、全てPriceやprice_idとなっているが、以前のplan_idと互換性があり、現時点ではどちらもAPIは受け入れてくれる。
古いstripe-phpライブラリで、plan_idを指定するパラメータに、price_id(price_xxxxx)を入れたり、新しいライブラリでprice_idパラメータにplan_id(plan_xxxxx)を入れても問題はない。古い商品IDはplan_xxxxxのままですが、そのままprice_idとして運用できます。