Stripe Billing - 定期支払いにおける比例配分の考え方


## この記事のカバー範囲
Stripe Billing における定期支払いの基本的な考え方はこちらの記事をご覧ください。 
 https://qiita.com/y_toku/items/235b5e7ee00792edcbbf

本記事では下記をカバーします。
 
- プラン変更に伴う差額の比例配分（Proration）の考え方
- Subscription のキャンセル方法

##プラン変更に伴う差額の比例配分（Proration）の考え方
異なる料率のプランを複数用意している場合、プラン変更が考えられます。こちらは、考え方によっては、プラン変更時の差額調整は行わないということも考えられます。
 
1. アップグレード: **低い料金プランから、高い料金プランへ**変更する場合
2. ダウングレード: **高い料金プランから、低い料金プランへ**変更する場合
 
###前提となるプランの変更
プランを変更するには、 既存の Subscription のプランを変更する処理をします。
 
前提として、以下とします。
 
- 変更前のプラン: 毎月 1000円, `Plan id`: `standard-monthly`
- これから適応するプラン: 毎月 3000円, `Plan id`: `pro-monthly`
 
```rb:プランの変更
subscription = Stripe::Subscription.retrieve("sub_xxxx") #既存の Subscription ID を指定
subscription.plan = "pro-monthly" #変更後の Plan ID を指定（Planは作成済みのもの）
subscription.save
```
 
これで終わりです。
 
プラン変更時に、Invoice の請求サイクルが変わるか変わらないかもポイントです。
以下の条件だと、請求サイクルは変わりません。
 
- `interval`、`interval_count`が同じである
- 新しいプランに変更した際に、トライアルやクーポンがない
 
参考ドキュメント: https://stripe.com/docs/subscriptions/upgrading-downgrading#switching
 
 
###1. アップグレードする場合
具体的なケースで考えていきます。
現在のプランは毎月1000円の Standard プランで、毎月1日に Invoice が発行されます。より充実したサービスへアップグレードするため、毎月3000円の Pro プランへ変更するとします。
 
Subscription の途中でプランを変更すると、当月分がすでに請求されているため、実際に利用した部分と利用していない部分が出てきます。この調整を自動で行います。重要なことは、**実際に金額に反映されるのは、次回の Invoice から** です。これを覚えておきましょう。
 
実際に簡単な例で、金額を計算してみます。
例えば、4/15 日に変更し、ちょうど 50% (4/1 に開始、4/15 に変更) の時間を利用しているケースを考えてみます。
 
**既存プラン（毎月1000円）**の調整金額の計算は、以下のようになります。
 
- 実際に利用した金額: 500円 = 1000円 × 50% 
- 未使用分の金額: 500円 = 1000円 × 50% <== 次回の Invoice から引きます(ドキュメントでは、credit と表現されています)
 
**新プラン（毎月3000円）**の調整金額の計算
 
- 4月に利用する金額: 1500円 = 3000円 × 50% <== 次回の Invoice に加算します
 
5/1 の次回の Invoice の金額は 4000円 となります。内訳は以下です。
 
- 新プランの料金: 3000円
- 旧プランの4月未使用料金: -500円
- 新プランの4月未払い料金: 1500円
 
**請求サイクルが変わらない場合は、翌月の Invoice で調整される**というのを今一度覚えておいてください。
 
もし、**毎月**1000円のプランから、**毎年**10000円のプランへと変更した場合は、Interval が代わりますので、プラン変更時点で新しい Invoice が作成され、その時点で請求します。つまり、4/15 に上記のように（50%の経過時点で）変更した場合の請求金額は 9500円(10000円 - 500円)となります。 
 
 
###2. ダウングレードする場合
今度は、逆のケースを考えてみたいと思います。
現在のプランは毎月3000円の Pro プランで、毎月1日に Invoice が発行されます。サービスへ満足しなかったので、毎月1000円の Standard プランへ変更する、とします。
 
既存プランの調整金額の計算
 
- 実際に利用した分: 1500円 = 3000円 × 50% 
- 未使用分: 1500円 = 3000円 × 50% <== 次回の Invoice から引きます(ドキュメントでは、credit と表現されています)
 
新プランの調整金額の計算
 
- 4月に利用する金額: 500円 = 1000円 × 50% <== 次回の Invoice に加算します
 
**5/1 の Invoice の金額は 0円**となります。内訳は以下です。
 
- 新プランの料金: 1000円
- 旧プランの4月未使用料金: -1500円
- 新プランの4月未払い料金: 500円
 
このケースだと5月に支払いは発生しません。もし、調整後の金額がマイナスになった場合は、翌々月の Invoice で調整されます。
 
###比例配分のコストを把握する方法
```rb:現時点でプランを変更し比例配分のコストを把握する
 # 現時点の時間を取得します:
proration_date = Time.now.to_i
 
# 次回の Invoice がどうなるかを確認します
# proration date をセットします:
invoice = Stripe::Invoice.upcoming(
    customer: "cus_xxxx",  #該当する Customer ID
    subscription: "sub_xxxx", #既存の Subscription ID
    subscription_plan: "pro-monthly", #変更予定の新しい Plan ID
    subscription_proration_date: proration_date,)  #上で取得したProration をする日
 
# 比例配分の費用を取得します:
current_prorations = invoice.lines.data.select { |ii| ii.period.start == proration_date }
cost = 0
current_prorations.each do |p|
  cost += p.amount
end
```
`cost` で、把握できます。
 
###比例配分する日を決める
よくあるお問い合わせですが、*日割りにしたい*、*変更日を指定したい*　というお問い合わせをいただきます。
その場合は、`proration_date`を指定します。タイムスタンプを利用すれば秒割り、日割りも可能です。
 
```rb:比例配分の日付指定
subscription = Stripe::Subscription.retrieve("sub_xxxx")
subscription.plan = "pro-monthly"
subscription.proration_date = {unix timestamp}
subscription.save
```
 
 
https://stripe.com/docs/api#update_subscription-proration_date
 
 
###比例配分をしない場合
比例配分をしない場合は、プランの変更時に`subscription.prorate`を`false`として渡すだけです。
 
```rb:差額の比例配分をしない
subscription = Stripe::Subscription.retrieve("sub_xxxx") #既存の Subscription ID を指定
subscription.plan = "pro-monthly" #新しい Plan ID を指定
subscription.prorate = false
subscription.save
```
 
##Subscription のキャンセル
最後に、残念ながら Subscription をキャンセルする場合を考えます。
 
```rb:Subscriptionのキャンセル
subscription = Stripe::Subscription.retrieve("sub_xxxx")
Subscription.delete
```
 
該当の Subscription を指定して、`delete` します。そうすると、ただちにキャンセルされます。
Subscription のキャンセル時には事前にいただいた期間分、すべてを使い切らずにキャンセルした場合、返金すべきかどうか、考慮する必要がある場合があります。
 
例えば、支払い済みの年間 Subscription を途中でキャンセルする場合などは、キャンセル時にどこまで利用したかを計算して計算する必要などがあります。その場合は、今辞めたらいくら分かかるかなどを確認できる [Preview](http://qiita.com/y_toku/private/7ccbccd5b6170b24d47a#%E6%AF%94%E4%BE%8B%E9%85%8D%E5%88%86%E3%81%AE%E3%82%B3%E3%82%B9%E3%83%88%E3%82%92%E6%8A%8A%E6%8F%A1%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95) を利用すると良いと思います。
 
一方で毎月の Subscription などある程度期間が短い場合は、返金はせずに、該当の期間終了をもってキャンセルする、というサービスがかなり多いかと思います。その場合は、`at_priod_end`が利用できます。
 
```rb:Subscriptionを期間終了時にキャンセル
subscription = Stripe::Subscription.retrieve("sub_xxxx")
subscription.delete(:at_period_end => true)
```

参考ドキュメント: https://stripe.com/docs/subscriptions/canceling-pausing 

こんな感じです。
お役に立てれば幸いです。

もし、何かご質問などござましたら、support-jp@stripe.com までお問い合わせください！
日本語でサポートしております。