Stripeで従量課金、かつ最初の数人は無料というサービスの設計

# はじめに
Stripeで下記のような従量課金の仕様で設計する方法をまとめました。Githubのようにチームメンバーが増えると共に使用量が増える料金モデルです。
もっと良い方法があったら教えて欲しいです。（最後の問題点というところにまとめました）

- 人数に応じて月額課金
- 最初の3人は無料
- 集計月の最大登録人数で課金

# 商品の追加
Stripeのコンソールで商品の追加->新しい料金の追加で下記のように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/f3575f95-3634-72fd-b46c-a9b8fc398d73.png)



これで最初の3人は無料、その後1人増えるごとに500円月額課金する料金体系ができました。
また、課金数量は集計月の最大数量で計算されます。（つまり課金の対象となる人数が増えたり減ったりしても、集計月の中で最大になった時の数が使われます）

似たようなもので数量ベースの料金体系がありますが、この場合数量が増えると最初の3人の無料というのが無視されます。

たとえば、最初の3人を無料にし、5人登録があった場合、
**段階的な料金体系**：最初の3人無料、残りの2人に課金 => **1000円**
**数量ベースの料金体系**：3人までは無料だが、それより多い場合はユニットあたり全て課金 => **2500円**
となるので、注意して下さい。


# 課金処理
### 初期化
実際に課金されるまでの処理を説明します。
その前にRailsの場合はinitializerでStripeオブジェクトを初期化して下さい。

```ruby
Stripe.api_version = "2020-08-27"

# 実際はsecretはcredentialとかに入れて下さい。
Stripe.api_key = "stripe secret"
```

### Stripeの処理
ここからStripeの処理を並べていきます。

1. Customerの作成
2. Payment Methodの作成
3. Subscriptionの作成
4. Usage Recordの作成


Ruby以外の場合は[Stripe API](https://stripe.com/docs/api)で他の言語も確認できます。

### Customer作成
まずはStripe上にCustomerを作成します。


```ruby
Stripe::Customer.create({
  name: 'name',
  email: 'email@example.com'
})
```

createの引数はなくても大丈夫だと思いますが、Stripe上でも分かるように自分のアプリで管理してる情報と紐付けた方が良いかと思います。

また、customer_idが返ってきますのでこちらをDBに残しておきます。


### Payment Methodの作成
StripeにはPayment MethodとCardとという2つの支払い情報登録できるオブジェクトがありますが、Payment Methodはより新しく、Cardを含めて色々な支払情報を抽象化したものらしいのでPayment Methodを使います。

フロントでカード情報を取得してバックエンド側で登録することも可能ですが、なるべくバックエンド側に情報を流したくないので、フロントでカード登録できるように実装します。

reactの場合の実装は[react-stripe-js](https://github.com/stripe/react-stripe-js)を確認してください。

こちらを使うとフロントでカードを登録できます。ただ、この際に前段で作成したcustomer_idを引数に含めてpayment_methodと紐付けておいてください。
payment_method_idやカードの期限等返ってきますので、必要なものはバックエンド側でDBに残しておきます。

### Subscriptionの作成
料金を支払うためのSubscriptionを作成します。


```ruby
subscription = Stripe::Subscription.create({
  customer: 'customer_id', # subscriptionを紐付けたいcustomer_idを入力
  items: [
     { 
       price: 'price_id', # 商品の追加のところで作った料金のidを入力
     }
  ]
})
subscription_id = subscription['id']
```

この時点ではまだ料金は発生しません。
また、subscription_idは残しておきます。

### Usage Recordの作成
数量を設定していきます。

```ruby
subscription_items = Stripe::SubscriptionItem.list(
      subscription: subscription_id # 前段で保存したsubscription_id
    )

Stripe::SubscriptionItem.create_usage_record(
      subscription_items.data.first.id,
      {quantity: quantity}, # 必要な数量
)
```

subscription_itemは最初にsubscriptionを作成した時点で1つ作られます。
他の料金体系を同じsubscriptionに紐付けた場合2つ以上になりますが、今回は1つしか作らないのでfirstで1つ取得して、そのsubscription_itemに使用量を紐付けます。

このAPIを叩く度にquantityで設定されます。元々quantityが5で次にもう1回このAPIをquantity:1で叩いたらStripe上ではquantity:1になります（5+1=6とかにはなりません）

例として、課金対象人数を図で表すと下図のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/a309813e-9f29-28df-ca3f-d45d69cc58bd.png)

1/6以降もずっと1だとすると、1月分の課金額は最大の8人に課金されます。最初の3人は無料なので、今回の場合5×500円で2500円となります。

### 問題点
実装していて、結構面倒だなぁと思ったのは**課金基準日**です。
課金の基準日はSubscriptionの作成日です。
今回の仕様では最初の3人無料なので、Subscriptionを作成しても課金はされません。ですが月初に登録してずっと2人で運用し、月末に例えば5人に増やした場合でもその月の使用量は5人対して行われます。

実際に課金対象人数になった日を基準日としたい場合（下図）はアプリ側で制御するしかなさそうな感じがします。
下図の場合でいうと、課金対象期間を1/31~2/28にしたいです。

![Screen Shot 2021-11-16 at 16.31.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/504490b0-6ddb-9c59-e7a6-bf985ef2a2f5.png)


アプリ側で制御する場合は、1/30まではsubscriptionを作成せずに、1/31に無料枠である3人を超えた時に初めてsubscriptionを作成するようにすれば1/31が課金基準日になるかと思います。

ただ、例えば次の課金対象月で3人以内に戻して、またどこかのタイミングで4人以上になったときにそこを課金基準日にするにはsubscriptionをまた作り直したりしないといけないので結構面倒かなって思います。
Stripeの仕様を完璧把握してるわけでないので、良い方法がある場合は教えて下さい。