【Rails 入門】Stripe API

# はじめに
### [stripe](https://stripe.com/jp) とは

**決済代行サービス**です（類似サービスとしては`PayPal`があります）。

具体的に説明すると、stripeのAPIを使う（stripeのサービスプラットフォームを使う）ことで、自身のサービスの決済処理を担ってくれます！

つまり、

- ユーザーにお金を請求してその支払を受け取りたい！
- 「買切り」や「定額プラン」を設定して請求したい！

といったことが可能になります。

私がstripeの特に良いと思ったところは、**ユーザーがstripeのアカウントがなくても支払ができる**ということです。

アカウント作成の手間を省けるのは、UXとして大事な要素だと思います！

また、[ドキュメント](https://stripe.com/docs/api)が読みやすいですね。
英語なので読めない人にとっては辛いかもしれないですが、よくまとまっていると思います（そういった方々のために少しでも記事が参考になれば幸いです）。

そこで今回は、**Railsで処理を行う`Stripe API`（バックエンド側）**を説明いたします！

（stripeの決済処理を実現するためには、フロントエンドとしてJavascript、Vueなどを使い、クレジットカード情報の入力を処理する [stripe checkout](https://stripe.com/jp/payments/checkout)、[stripe element](https://stripe.com/jp/payments/elements) などの実装や、バックエンド側に送信してあげる処理が必要となりますが、今回はバックエンド側の処理にフォーカスを当てています！）

# stripeで何をやりたい？

Railsでstripeを実装するとなると、

**顧客情報をstripeに登録し、その際に作られた顧客IDを中心にその他の課金等の処理を実行する**

というのが実装の方針になるかと考えています。

それはなぜかと言うと、この**顧客ID**（`cus_xxxxxxxxxxxxxx`）を取得してしまえば、**その顧客に対して**定期課金や登録しているクレジットカードの削除などの処理を行えば良いからです！

後で詳しく説明しますが、この**顧客IDをもとにstripe側からクレジットカードの情報や、課金の内容等を取得することができる**ようになります。

以下のように機能ごとにまとめましたので、**適宜やりたい内容の箇所に飛んで**確認して下さい！
（掲載しているものは特に使用頻度の高いAPIとなっていますが、その他にも沢山ありますので是非チャレンジしてみて下さい！）

### 顧客管理
- [顧客登録](#顧客登録)
- [顧客情報の取得](#顧客情報の取得)
- [顧客削除](#顧客削除)

### クレジットカード管理
- [クレジットカード登録](#クレジットカード登録)
- [クレジットカード削除](#クレジットカード削除)

### 課金
- [一回課金（売り切り）](#一回課金売り切り)
- [定期課金（月額契約など）](#定期課金月額契約など)
- [定期課金解除](#定期課金解除)

### サービスプラン
- [サービスプラン登録](#サービスプラン登録)

# Stripe APIを利用するための準備
stripeのサービス登録や、本番環境利用の申請等の準備は行っている前提でご説明しますね。
### [stripe gem](https://github.com/stripe/stripe-ruby)のインストール

Gemfileに以下を追加し、`bundle install`をして下さい。

```rb:Gemfile
gem "stripe"
```

### シークレットキーの設定

Rails（ruby）でstripeのAPIを利用するためには、アプリケーションに**シークレットキー**を設定する必要があります。

そのシークレットキーはstripeの`ダッシュボード`（開発者→APIキー）から確認することができます。

画面左側下あたりの`テストデータの表示中`トグルをONにするとテスト用のシークレットキー、OFFにすると本番環境用のシークレットキーを取得することができます

参考に、テスト用のシークレットキー記載箇所の画像を添付しますね。

![for_qiita.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/7a80bb9c-29b6-4827-bb46-fc0be4c50ca6.jpeg)

ここで**重要なポイント**があり、このシークレットキー（特に本番用）はセキュリティ上、直でアプリケーションに入力するのは望ましくありません。

Rails5.2から追加された`credentials.yml.enc`を使用したシークレットキーの参照をおすすめいたします。

今回の記事でシークレットキーを記述すべきところは、テスト用のシークレットキーを利用するという前提で、以下のように定数`STRIPE_TEST_SECRET_KEY`を使用して解説します。

```rb
Stripe.api_key = STRIPE_TEST_SECRET_KEY
```

シークレットキーは以下の場所に追加し、いつでもstripeのAPIにアクセスできる状態にしておきましょう！

```rb:config/initializers/stripe.rb
Stripe.api_key = STRIPE_TEST_SECRET_KEY
Stripe.api_version = "2020-03-02" # 最新のバージョンにしましょう
```

### stripe APIの実装場所

単体クラスとして`lib/autoloads/payment.rb`に私は実装しています。

`config/application.rb`に以下内容を追加すると、`lib/autoloads`配下のクラスを読むようになります。

```rb:config/application.rb
config.autoload_paths += %W[#{config.root}/lib/autoloads]
```

# 顧客管理
### 顧客登録

顧客登録のAPIである[**Stripe::Customer.create**](https://stripe.com/docs/api/customers/create)に実装方法が記載されていますが、私は以下のような実装を行っています。

```rb:lib/autoloads/payment.rb
class Payment
  def self.register_customer(card_token)
    Stripe::Customer.create({
      source: card_token,
    })
  end
end
```

この`Stripe::Customer.create`内にあるキー`source`は`card_token`（変数名は自由に定義できます）をペアの値として設定しています。

この`card_token`には、**ユーザーのクレジットカード情報をstripeが暗号化したもの（トークン）**がパラメータとして渡されなければなりません。

実際の流れで説明すると、

1. ユーザーがクレジットカードの登録フォームに自身のクレジットカード情報を入力
2. そのクレジットカード情報がフロントエンドを通してstripeで暗号化される
3. その暗号化されたものをトークンとしてバックエンド（今回使用するRails側）に渡す
4. そのトークン（`card_token`）をもとに`Stripe::Customer.create`（stripeの顧客登録API）を行うことで、stripe側へ顧客情報（クレジットカード情報）を登録する

のようになっています！

その結果として、

- ユーザーの顧客ID（`cus_xxxxxxxxxxxxxx`）
- 登録したクレジットカード情報（`card_xxxxxxxxxxxxxxxxxxxxxxxx`）

を含む以下のような様々な情報が登録されます！

```rb
customer = Payment.register_customer("tok_visa")
=> #<Stripe::Customer:0x3fd2df28f888 id=cus_xxxxxxxxxxxxxx> JSON: {
  "id": "cus_xxxxxxxxxxxxxx",
  "invoice_prefix": "xxxxxxxx",
  "invoice_settings": {"custom_fields":null,"default_payment_method":null,"footer":null},
  "livemode": false,
  # 略
  "sources": {"object":"list","data":[{"id":"card_xxxxxxxxxxxxxxxxxxxxxxxx","object":"card","address_city":null # 続く
  # 略
}

# 上記メソッドの返り値である customer の参照例（顧客ID、クレジットカードID）
customer.id => "cus_xxxxxxxxxxxxxx"
customer.sources["data"][0].id => "card_xxxxxxxxxxxxxxxxxxxxxxxx"
```
この`tok_visa`はテスト用にstripeが準備したトークンで、このトークン以外にもテスト用に必要となるパラメータは[こちら](https://stripe.com/docs/testing)で準備されています。

実際のトークンは`tok_xxxxxxxxxxxxxxxxxxxxxxxx`のような文字列になっています。


それでは、この`source`は顧客登録のAPIに本当に必要なのか？というと、**実はそうではありません。**

[公式リファレンス](https://stripe.com/docs/api/customers/create)では、

```rb
Stripe::Customer.create({
  description: 'My First Test Customer (created for API docs)',
})
```

となっており、この`description`（ダッシュボードで表示される`説明`欄の内容）のパラメータを渡すだけでも顧客登録ができます。

つまり、このAPIを使うにあたって**入力が必須なパラメーターはありません**
が、`source`、`description`、`email`など、自身が顧客登録に必要と考える**何らかのパラメーター**を渡してあげましょう！


それではなぜ私は`source`（クレジットカードのトークン情報）を採用しているのか？

通常のアプリの流れを考えると、ユーザーが**初めてサービスの支払（課金）を登録する際は、必ずクレジットカード情報を登録する**はずです。

ですので、**初回のクレジットカード登録時に一緒にstripeの顧客登録を行う**ことが望ましいと考えています！

### 顧客情報の取得

[**Stripe::Customer.retrieve**](https://stripe.com/docs/api/customers/retrieve)のAPIを使用します。

```rb:lib/autoloads/payment.rb
  def self.fetch_customer(customer_id)
    Stripe::Customer.retrieve(customer_id)
  end
```

```rb
customer = Payment.fetch_customer("cus_xxxxxxxxxxxxxx")
=> #<Stripe::Customer:0x3fd91a7a72a8 id=cus_xxxxxxxxxxxxxx> JSON: {
  "id": "cus_xxxxxxxxxxxxxx",
  "object": "customer",
  "address": null,
  "balance": 0,
  "created": 1234567890,
  "currency": "jpy",
  "default_source": "card_xxxxxxxxxxxxxxxxxxxxxxxx",
  # 略
  "subscriptions": {"object":"list","data":[{"id":"sub_xxxxxxxxxxxxxx","object":"subscription" #続く
  # 略
}

# 参照例（ユーザーの特定の定期課金ID）
customer.default_source => "card_xxxxxxxxxxxxxxxxxxxxxxxx"
customer.subscriptions["data"][0].id => "sub_xxxxxxxxxxxxxx"
```

以上のように、この顧客情報の取得のAPIを使用すると、

**顧客IDを入力するだけ**で登録しているクレジットカード情報や、定期課金の情報な、顧客に関する様々な情報にアクセスすることが可能になります。

この**顧客IDだけ**というのが何を意味するのか？

それは、**バックエンド側のDBに保存しておくべきものは、基本的に顧客IDのみ**であるということです。

後ほど説明する定期課金の処理で取得する定期課金ID（`"sub_xxxxxxxxxxxxxx"`）も、この顧客情報の取得を行うだけで参照が可能となります！

### 顧客削除
[**Stripe::Customer.delete**](https://stripe.com/docs/api/customers/delete)を利用します。

```rb:lib/autoloads/payment.rb
  def self.delete_customer(customer_id)
    Stripe::Customer.delete(customer_id)
  end
```

```rb
customer = Payment.delete_customer("cus_xxxxxxxxxxxxxx")
=> #<Stripe::Customer:0x3fccb338da00 id=cus_xxxxxxxxxxxxxx> JSON: {
  "id": "cus_xxxxxxxxxxxxxx",
  "object": "customer",
  "deleted": true
}

# 参照例
customer.deleted => true
```

# クレジットカード

### クレジットカード登録

**[Stripe::Customer.create_source](https://stripe.com/docs/api/cards/create)**を使用します。

`source`は入力必須のパラメータです。
指定した顧客のクレジットカードを登録するため、顧客ID（`cus_xxxxxxxxxxxxxx`）もパラメータとして入力しましょう。

```rb:lib/autoloads/payment.rb
  def self.register_card(customer_id:, card_token:)
    Stripe::Customer.create_source(
      customer_id,
      { source: card_token },
    )
  end
```

```rb
card = Payment.register_card(customer_id: "cus_xxxxxxxxxxxxxx", card_token: "tok_visa")
=> #<Stripe::Card:0x3fd0cfbc59c8 id=card_xxxxxxxxxxxxxxxxxxxxxxxx> JSON: {
  "id": "card_xxxxxxxxxxxxxxxxxxxxxxxx",
  "object": "card",
  "address_city": null,
  "address_country": null,
  # 略
}

# 参照例
card.id => "card_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### クレジットカード削除

**[Stripe::Customer.delete_source](https://stripe.com/docs/api/cards/delete)**を使用します。

```rb:lib/autoloads/payment.rb
  def self.delete_card(customer_id:, card_id:)
    Stripe::Customer.delete_source(
      customer_id,
      card_id,
    )
  end
```

このAPIでは`card_id`が必要となります。
これはどのように取得すれば良いでしょうか？

答えは、先程解説した[顧客情報の取得](#顧客情報の取得)の使用です！

[顧客情報の取得](#顧客情報の取得)で得られるデータには様々な情報が格納されていることから、今回説明していないstripeのAPIについても積極的に[顧客情報の取得](#顧客情報の取得)を使用するようにしましょう！

RailsのDBに保存するのは基本`顧客ID`ぐらいで、それ以外は都度参照するような方針で実装するようになります。

```rb
card_id = Payment.fetch_customer("cus_xxxxxxxxxxxxxx").default_source

card = Payment.delete_card(customer_id: "cus_xxxxxxxxxxxxxx", card_id: card_id)
=> #<Stripe::Card:0x3fc7b95d2ddc id=card_xxxxxxxxxxxxxxxxxxxxxxxx> JSON: {
  "id": "card_xxxxxxxxxxxxxxxxxxxxxxxx",
  "object": "card",
  "deleted": true
}

# 参照例
card.deleted => "true"
```

# 課金
### 一回課金（売り切り）

[**Stripe::Charge.create**](https://stripe.com/docs/api/charges/create)のAPIを使用します。

入力が必須なパラメータは2つですが、請求する顧客を指定する必要があるので、合わせて`customer`に顧客IDを入力させましょう（必要に応じて公式リファレンスを参考に追加して下さい）。

- `amount`（金額）
- `currency`（通貨）
- `customer`（顧客ID）

```rb:lib/autoloads/payment.rb
  def self.one_time_charge(price:, customer_id:)
    Stripe::Charge.create({
      amount: price,
      currency: "jpy", # 請求通貨は円で固定していますが変更可能です
      customer: customer_id,
    })
  end
```

```rb
charge = Payment.one_time_charge(price: 1000, customer_id: "cus_xxxxxxxxxxxxxx")
=> #<Stripe::Charge:0x3fde477a6510 id=ch_xxxxxxxxxxxxxxxxxxxxxxxx> JSON: {
  "id": "ch_xxxxxxxxxxxxxxxxxxxxxxxx",
  "object": "charge",
  "amount": 1000,
  "amount_refunded": 0,
  # 略
}

# 参照例
charge.id = "ch_xxxxxxxxxxxxxxxxxxxxxxxx"
charge.amount => 1000
charge.paid => true
charge.status => "succeeded"
```

### 定期課金（月額契約など）

[**Stripe::Subscription.delete**](https://stripe.com/docs/api/subscriptions/create)のAPIを使用します。

入力が必須なパラメータは以下の2つです。

- `customer`（顧客ID）
- `items (plan)`（課金するサービスプラン）

```rb:lib/autoloads/payment.rb
  def self.subscribe(customer_id:, plan_id:)
    Stripe::Subscription.create({
      customer: customer_id,
      items: [{ plan: plan_id }],
    })
  end
```

この`plan_id`は、後ほど[サービスプラン登録](#サービスプラン登録)で説明しますね。

```rb
subscription = Payment.subscribe(customer_id: "cus_xxxxxxxxxxxxxx", plan_id: "plan_xxxxxxxxxxxxxx")
=> #<Stripe::Subscription:0x3fc5c0ab0430 id=sub_xxxxxxxxxxxxxx> JSON: {
  "id": "sub_xxxxxxxxxxxxxx",
  "object": "subscription",
  "application_fee_percent": null,
  # 略
  "plan": {"id":"plan_H6GDh7cO9gRfLy","object":"plan","active":true # 続く
  # 略
}

# 参照例
subscription.id = "sub_xxxxxxxxxxxxxx"
subscription.plan.id = "plan_xxxxxxxxxxxxxx"
subscription.plan.product => "pro_xxxxxxxxxxxxxx"
```

### 定期課金解除

[**Stripe::Subscription.delete**](https://stripe.com/docs/api/subscriptions/cancel)のAPIを使用します。

メソッドの引数として使用する定期課金ID（`subscription_id`）は、サービスプランが同じであっても、
**各ユーザーごとに違うもの**であるのでご注意下さい！

`subscription_id`は`card_id`と同様に、[顧客情報の取得](#顧客情報の取得)で参照することが可能です！

```rb:lib/autoloads/payment.rb
  def self.unsubscribe(subscription_id)
    Stripe::Subscription.delete(subscription_id)
  end
```

```rb
subscription_id = Payment.fetch_customer("cus_xxxxxxxxxxxxxx").subscriptions["data"][0].id

subscription = Payment.unsubscribe(subscription_id)
=> #<Stripe::Subscription:0x3fcfb856c580 id=sub_xxxxxxxxxxxxxx> JSON: {
  "id": "sub_xxxxxxxxxxxxxx",
  "object": "subscription",
  "application_fee_percent": null,
  # 略
  "status": "canceled",
  "tax_percent": null,
  "trial_end": null,
  "trial_start": null
}

# 参照例
subscription.status => "canceled"
```

# サービスプラン
### サービスプラン登録

サービスプランについては、Rails側で管理するよりも、stripeのダッシュボードから設定を行う方が内容も充実しているので良いと思います。

Railsの内容ではないですが、サービスプラン登録の手順を軽くご説明します（変更や削除は解説しません）。

まずはダッシュボード左の`Billing`→`商品`の順に進み、商品の登録と、プランを決めていきます。

ここでいう`商品`とは、Netflixの`動画配信サービス`のようなものを指し、`プラン`とは、Netflixのサービスプランである、`ベーシック`、`スタンダード`、`プレミアム`のようなものです。

商品IDとプランIDはそれぞれ

- `prod_xxxxxxxxxxxxxx`（商品ID）
- `plan_xxxxxxxxxxxxxx`（プランID）

となっており、`plan_xxxxxxxxxxxxxx`については、[定期課金](#定期課金月額契約など)のパラメータとして使用するので確認しておく必要があります。

参考として操作画面を添付しますね。

- 商品登録画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/fd3a497d-85d9-2bad-0dd4-d31a3df0ac7d.png)

- プラン内容登録画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/93b5ec0c-32f9-3ed1-8238-9357d7ccde6e.png)

- 作成した商品、プランの概要画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/e9b3a9a9-6020-8c69-2f68-5eb4f1d4c9ce.png)