はじめに
今回の記事は、Stripe Connectを使ってCheckoutを利用した継続課金を実装の続きとなります。
前回に引き続き、継続課金の実装について紹介していきます。今回は、実際のサービスでの利用を意識して、複数の継続課金を併用した場合について見ていきます。
想定する継続課金
企業向けの架空のファイルアップロードサービスを例にした継続課金になります。はじめに、ユーザ企業はプラン(定額)を契約し、その後、サービスを利用するユーザ数分のID(従量課金)を購入します。
プランは3種類あり、金額に応じて一人あたりのアップロード可能数が増加します。
- プランA 1,000円/月 1GB/人まで
- プランB 2,000円/月 5GB/人まで
- プランC 3,000円/月 無制限
ID数の方は、一人あたり一律100円かかります。例えば、プランAを選択し、30人のユーザが利用する場合、毎月の費用は4,000円になります。
想定するシチュエーション
今回の記事では、以下のようなシチュエーションを想定しています。
- プランAとID数を30契約
- ID数をさらに20購入
- プランAからプランBにアップグレード
- ID数を10解約
- プランBからプランAにダウングレード
継続課金商品の作成
プランの継続課金商品の作成
Stripeの管理画面の商品からプランとID数の継続課金商品を作成します。
プランの継続課金商品は、料金体系モデルで標準の料金体系を選択し、料金設定を行います。
更に料金を2つ追加すると、以下のようになります。
ID数の継続課金商品の作成
次にID数の継続課金商品を作成します。
ID数の継続課金商品は、数量ベースの料金体系を選択します。
この設定では、一人あたり毎月一律100円かかります。
実装
前回の記事では、継続課金商品の契約はCheckout画面で行いましたが、今回は請求タイミングを月末に固定したいので、コード上から契約を行います。
プランAとID数を30契約する
Subscription::create()
メソッドで継続課金商品を契約します。このメソッドでは、以下のように一度に複数の継続課金商品を契約することができます。
billing_cycle_anchor
で指定した日付に次回の請求が行われます。また、当月の請求は日割り計算となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function subscribe() { Stripe::setApiKey(env('STRIPE_SECRET')); $subscription = Subscription::create([ 'customer' => 'your_customer_id', 'items' => [ [ // プランA 'price' => 'planA_price_id', ], [ // ID数を30 'price' => 'id_set_price_id', 'quantity' => 30, ], ], 'billing_cycle_anchor' => 1622473199, // 次回の請求日 ]); } |
ID数をさらに20購入
継続課金商品の契約個数を更新する前に、追加の月額を計算することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function calculate() { Stripe::setApiKey(env('STRIPE_SECRET')); $proration_date = time(); // 継続課金の変更日時 $subscription = \Stripe\Subscription::retrieve('sub_JZGRs56J8bebKP'); $items = [ [ // ID数を30から50へ変更する 'id' => $subscription->items->data[1]->id, 'quantity' => 50, ], ]; $invoice = \Stripe\Invoice::upcoming([ 'customer' => 'cus_JZGRPAUzlFmazf', 'subscription' => 'sub_JZGRs56J8bebKP', 'subscription_items' => $items, 'subscription_proration_date' => $proration_date, 'subscription_proration_behavior' => 'always_invoice', ]); } |
$invoice
の内容を抜粋すると以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | { "object": "invoice", "account_country": "JP", "account_name": "hoge-test", "account_tax_ids": null, "amount_due": 149, "amount_paid": 0, "amount_remaining": 149, // ... "subtotal": 149, "tax": null, "total": 149, "total_discount_amounts": [], "total_tax_amounts": [], "transfer_data": null, "webhooks_delivered_at": null } |
proration_behavior
に
always_invoice
を指定すると、変更にかかる金額が即時決済されます。
total
の金額が追加の決済金額です。
その後、実際にID数を50に変更する処理がこちらです。
Subscription::update()
メソッドで、IDの数量を変更しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | function update(int $subscriptionId) { Stripe::setApiKey(env('STRIPE_SECRET')); $proration_date = time(); $subscription = \Stripe\Subscription::retrieve('sub_JZGRs56J8bebKP'); $items = [ [ 'id' => $subscription->items->data[1]->id, 'quantity' => 50, ], ]; $subscription = Subscription::update( 'sub_JZGRs56J8bebKP', [ 'items' => $items, // Invoice::upcomingで渡した subscription_proration_date と同じ値にする 'proration_date' => $proration_date, 'proration_behavior' => 'always_invoice', ], ); } |
このように、追加分が即時決済されます。
プランAからプランBにアップグレード
プランの変更もID数の変更と同様に
Subscription::update()
メソッドで行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | function update(int $subscriptionId) { Stripe::setApiKey(env('STRIPE_SECRET')); $proration_date = time(); $subscription = \Stripe\Subscription::retrieve('sub_JZGRs56J8bebKP'); $items = [ [ 'id' => $subscription->items->data[0]->id, 'price' => 'pran_B_price_id', ], ]; $subscription = Subscription::update( 'sub_JZGRs56J8bebKP', [ 'items' => $items, // Invoice::upcomingで渡した subscription_proration_date と同じ値にする 'proration_date' => $proration_date, 'proration_behavior' => 'always_invoice', ], ); } |
こちらも、ID数を変更する場合と同様に、プランを変更する前に追加の金額を表示する必要があるでしょう。
ID数を10解約
プランのダウングレードやID数を減らす場合、日割り計算はせず、次月の請求から変更が反映されるものとします。ID数を増やす場合と殆ど変わりませんが、
Subscription::update()
メソッドのパラメータの
proration_
を
none
で指定します(
proration_date
は不要)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function update(int $subscriptionId) { Stripe::setApiKey(env('STRIPE_SECRET')); $proration_date = time(); $subscription = \Stripe\Subscription::retrieve('sub_JZGRs56J8bebKP'); $items = [ [ 'id' => $subscription->items->data[1]->id, 'quantity' => 40, ], ]; $subscription = Subscription::update( 'sub_JZGRs56J8bebKP', [ 'items' => $items, 'proration_behavior' => 'none', ], ); } |
この場合の
Invoce::upcoming()
メソッドのレスポンスは以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { "object": "invoice", "account_country": "JP", "account_name": "hoge-test", "account_tax_ids": null, "amount_due": 6000, "amount_paid": 0, "amount_remaining": 6000, // ... "total": 6000, "total_discount_amounts": [], "total_tax_amounts": [], "transfer_data": null, "webhooks_delivered_at": null } |
total
の値は、次回の請求金額になります。
ちなみに、ID数を減らした後、次の請求より前にID数を増やす場合、日割り金額は減らした後のID数をもとに計算されます。
プランBからプランAにダウングレード
最後に、プランBからプランAにダウングレードする場合です。こちらもID数を減らす場合とほとんど変わりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function update(int $subscriptionId) { Stripe::setApiKey(env('STRIPE_SECRET')); $proration_date = time(); $subscription = \Stripe\Subscription::retrieve('sub_JZGRs56J8bebKP'); $items = [ [ 'id' => $subscription->items->data[0]->id, 'price' => 'pran_A_price_id', ], ]; $subscription = Subscription::update( 'sub_JZGRs56J8bebKP', [ 'items' => $items, 'proration_behavior' => 'none', ], ); } |
さいごに
前回に引き続き、継続課金について、複数の継続課金を併用し、途中で内容を変更する方法を紹介しました。