はじめに
stripe とは
決済代行サービスです(類似サービスとしてはPayPal
があります)。
具体的に説明すると、stripeのAPIを使う(stripeのサービスプラットフォームを使う)ことで、自身のサービスの決済処理を担ってくれます!
つまり、
- ユーザーにお金を請求してその支払を受け取りたい!
- 「買切り」や「定額プラン」を設定して請求したい!
といったことが可能になります。
私がstripeの特に良いと思ったところは、ユーザーがstripeのアカウントがなくても支払ができるということです。
アカウント作成の手間を省けるのは、UXとして大事な要素だと思います!
また、ドキュメントが読みやすいですね。
英語なので読めない人にとっては辛いかもしれないですが、よくまとまっていると思います(そういった方々のために少しでも記事が参考になれば幸いです)。
そこで今回は、Railsで処理を行うStripe API
(バックエンド側)を説明いたします!
(stripeの決済処理を実現するためには、フロントエンドとしてJavascript、Vueなどを使い、クレジットカード情報の入力を処理する stripe checkout、stripe element などの実装や、バックエンド側に送信してあげる処理が必要となりますが、今回はバックエンド側の処理にフォーカスを当てています!)
stripeで何をやりたい?
Railsでstripeを実装するとなると、
顧客情報をstripeに登録し、その際に作られた顧客IDを中心にその他の課金等の処理を実行する
というのが実装の方針になるかと考えています。
それはなぜかと言うと、この顧客ID(cus_xxxxxxxxxxxxxx
)を取得してしまえば、その顧客に対して定期課金や登録しているクレジットカードの削除などの処理を行えば良いからです!
後で詳しく説明しますが、この顧客IDをもとにstripe側からクレジットカードの情報や、課金の内容等を取得することができるようになります。
以下のように機能ごとにまとめましたので、適宜やりたい内容の箇所に飛んで確認して下さい!
(掲載しているものは特に使用頻度の高いAPIとなっていますが、その他にも沢山ありますので是非チャレンジしてみて下さい!)
顧客管理
クレジットカード管理
課金
サービスプラン
Stripe APIを利用するための準備
stripeのサービス登録や、本番環境利用の申請等の準備は行っている前提でご説明しますね。
stripe gemのインストール
Gemfileに以下を追加し、bundle install
をして下さい。
gem "stripe"
シークレットキーの設定
Rails(ruby)でstripeのAPIを利用するためには、アプリケーションにシークレットキーを設定する必要があります。
そのシークレットキーはstripeのダッシュボード
(開発者→APIキー)から確認することができます。
画面左側下あたりのテストデータの表示中
トグルをONにするとテスト用のシークレットキー、OFFにすると本番環境用のシークレットキーを取得することができます
参考に、テスト用のシークレットキー記載箇所の画像を添付しますね。
ここで重要なポイントがあり、このシークレットキー(特に本番用)はセキュリティ上、直でアプリケーションに入力するのは望ましくありません。
Rails5.2から追加されたcredentials.yml.enc
を使用したシークレットキーの参照をおすすめいたします。
今回の記事でシークレットキーを記述すべきところは、テスト用のシークレットキーを利用するという前提で、以下のように定数STRIPE_TEST_SECRET_KEY
を使用して解説します。
Stripe.api_key = STRIPE_TEST_SECRET_KEY
シークレットキーは以下の場所に追加し、いつでもstripeのAPIにアクセスできる状態にしておきましょう!
Stripe.api_key = STRIPE_TEST_SECRET_KEY
Stripe.api_version = "2020-03-02" # 最新のバージョンにしましょう
stripe APIの実装場所
単体クラスとしてlib/autoloads/payment.rb
に私は実装しています。
config/application.rb
に以下内容を追加すると、lib/autoloads
配下のクラスを読むようになります。
config.autoload_paths += %W[#{config.root}/lib/autoloads]
顧客管理
顧客登録
顧客登録のAPIであるStripe::Customer.createに実装方法が記載されていますが、私は以下のような実装を行っています。
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が暗号化したもの(トークン)がパラメータとして渡されなければなりません。
実際の流れで説明すると、
- ユーザーがクレジットカードの登録フォームに自身のクレジットカード情報を入力
- そのクレジットカード情報がフロントエンドを通してstripeで暗号化される
- その暗号化されたものをトークンとしてバックエンド(今回使用するRails側)に渡す
- そのトークン(
card_token
)をもとにStripe::Customer.create
(stripeの顧客登録API)を行うことで、stripe側へ顧客情報(クレジットカード情報)を登録する
のようになっています!
その結果として、
- ユーザーの顧客ID(
cus_xxxxxxxxxxxxxx
) - 登録したクレジットカード情報(
card_xxxxxxxxxxxxxxxxxxxxxxxx
)
を含む以下のような様々な情報が登録されます!
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が準備したトークンで、このトークン以外にもテスト用に必要となるパラメータはこちらで準備されています。
実際のトークンはtok_xxxxxxxxxxxxxxxxxxxxxxxx
のような文字列になっています。
それでは、このsource
は顧客登録のAPIに本当に必要なのか?というと、実はそうではありません。
公式リファレンスでは、
Stripe::Customer.create({
description: 'My First Test Customer (created for API docs)',
})
となっており、このdescription
(ダッシュボードで表示される説明
欄の内容)のパラメータを渡すだけでも顧客登録ができます。
つまり、このAPIを使うにあたって入力が必須なパラメーターはありません
が、source
、description
、email
など、自身が顧客登録に必要と考える何らかのパラメーターを渡してあげましょう!
それではなぜ私はsource
(クレジットカードのトークン情報)を採用しているのか?
通常のアプリの流れを考えると、ユーザーが初めてサービスの支払(課金)を登録する際は、必ずクレジットカード情報を登録するはずです。
ですので、初回のクレジットカード登録時に一緒にstripeの顧客登録を行うことが望ましいと考えています!
顧客情報の取得
Stripe::Customer.retrieveのAPIを使用します。
def self.fetch_customer(customer_id)
Stripe::Customer.retrieve(customer_id)
end
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を利用します。
def self.delete_customer(customer_id)
Stripe::Customer.delete(customer_id)
end
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を使用します。
source
は入力必須のパラメータです。
指定した顧客のクレジットカードを登録するため、顧客ID(cus_xxxxxxxxxxxxxx
)もパラメータとして入力しましょう。
def self.register_card(customer_id:, card_token:)
Stripe::Customer.create_source(
customer_id,
{ source: card_token },
)
end
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を使用します。
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
ぐらいで、それ以外は都度参照するような方針で実装するようになります。
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のAPIを使用します。
入力が必須なパラメータは2つですが、請求する顧客を指定する必要があるので、合わせてcustomer
に顧客IDを入力させましょう(必要に応じて公式リファレンスを参考に追加して下さい)。
-
amount
(金額) -
currency
(通貨) -
customer
(顧客ID)
def self.one_time_charge(price:, customer_id:)
Stripe::Charge.create({
amount: price,
currency: "jpy", # 請求通貨は円で固定していますが変更可能です
customer: customer_id,
})
end
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のAPIを使用します。
入力が必須なパラメータは以下の2つです。
-
customer
(顧客ID) -
items (plan)
(課金するサービスプラン)
def self.subscribe(customer_id:, plan_id:)
Stripe::Subscription.create({
customer: customer_id,
items: [{ plan: plan_id }],
})
end
このplan_id
は、後ほどサービスプラン登録で説明しますね。
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のAPIを使用します。
メソッドの引数として使用する定期課金ID(subscription_id
)は、サービスプランが同じであっても、
各ユーザーごとに違うものであるのでご注意下さい!
subscription_id
はcard_id
と同様に、顧客情報の取得で参照することが可能です!
def self.unsubscribe(subscription_id)
Stripe::Subscription.delete(subscription_id)
end
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
については、定期課金のパラメータとして使用するので確認しておく必要があります。
参考として操作画面を添付しますね。
- 作成した商品、プランの概要画面