[Rails]Stripe Checkoutを利用して定期決済機能を実装する


 はじめに

この記事では、Stripeを用いた定期決済機能を実装します。
決済には、Ruby on RailsとCheckout Sessionを利用します。

 Stripeとは

決済サービスです。

WebサイトやWebアプリケーション、ネイティブアプリに決済システムを導入できます。似たようなサービスには、PayPal, Pay.JP, Omiseなどがあります。

Stripeは機能がとにかく豊富で、多彩な決済システムを構築できるのが特徴です。

 用語整理

Checkout
Stripeの決済ページには、Checkout と Elements の2つのタイプが用意されています。

Checkout:Stipeが用意した決済専用ページ。
Elements:決済フォームとシステムだけ用意され、決済ページはカスタマイズできる。

サクッと決済ページを作成したいときはCheckoutを利用するといいですね。定期決済、都度決済どちらにも対応しています。

Session ID
今回はセッションを用いた決済システムを構築します。こちらの決済システムでは、レスポンスにSession_idが返ってきます。
このSession_idにはcusntomer_id(顧客ID)subscription_id(定期決済ID)など、さまざまな決済情報が入っています。

 注意点

Stripeドキュメントに書かれているRubyコードの例は、主にSinatraで書かれているのでRailsではありません。

Sinatraとは、Rubyのフレームワークです。RubyのフレームワークはRailsだけではなくて、Sinatraもあります。以前StripeはRailsを使って例を出していましたが、、、現在ではSinatraに鞍替えしています。

RailsにSinatraを導入することはできないので、今回の実装では一部JavaScriptを利用しています。

 この記事でできること

  • チェックアウトを用いた決済ページの作成
  • 決済システムの構築
  • session_idを活用

 準備

商品を作成するためにStripe Dashboardに入る必要があります。Stripeアカウントを持っていない方は、ここで作成しましょう。

本番環境ではなく、テスト環境で行うだけでしたらアカウントを有効にさせる必要はありません。今回作成する商品や、APIキーはテスト用のものですので、今回の実装も本番環境を使用することはありません。

すでに本番環境を有効にしている方
もしすでに有効にしている場合は、注意点があります。

ダッシュボードの左側に View test data もしくは Viewing test data と表示されている切り替えボタンがあると思います。View test dataとなっている時は本番モード、Viewing test dataとなっている時はテストモードです。

テストモードで実装を行いたい場合は、商品の作成からテストモードで行わなければなりません。本番モードの時に作成した商品は本番環境でしか、テストモードの時に作成した商品はテスト環境でしか使用できません。こちらはご注意ください。

商品の作成

商品の作成にはダッシュボード左側のProductsを選択します。

Add productを選択します。

最低限、名前と金額さえ選択できていれば、商品は作成できます。

One timeは一回限りの都度決済、Recurringは定期決済となります。

今回は毎月の定期決済を実装するので、Recurringを選択し、Billing perio(期間)はMonthlyと設定します。

設定が完了したら、右上のSave productをクリックします。

そうすると、PricingのところにAPI IDという蘭があり、そちらにはprice_idが発行されています。こちらが発行されていれば準備は完了です。

※補足

2020年8月27日以前のStripe APIのバージョンでは、定期決済の実装にはplan_idを用いていました。現在のバージョンではprice_idを用いるので、ご注意ください。

 実装

Gemをインストール

Gemfile
gem 'stripe'

APIのシークレットキーを設定

StripeダッシュボードのHomeに行くと、Get your test API keysという欄があります。そちらにあるSecret keyをRailsのディレクトリに記述します。

シークレットキーを記述するのにはcredentials.ymlを利用してもいいですが、今回はenvファイルを使って行います。

.env
STRIPE_TEST_SECRET_KEY = sk_test_xxxxxx

また、config/initializersの中にstripr.rbというファイルを作成し、その中にシークレットキーを設定します。

stripe.rb
Stripe.api_key = ENV['STRIPE_TEST_SECRET_KEY']

Paymentsコントローラーを作成する

名前はなんでもいいですが、今回はPaymentsと命名します。
メソッドはnew_subscriptioncreate_subscriptionの2つを作成することにします。

payments_controller.rb
def new_subscription

    @session = Stripe::Checkout::Session.create({
      payment_method_types: ['card'],
      line_items: [{
        price: 'price_XXXX',
        quantity: 1,
      }],
      mode: 'subscription',
      success_url: request.base_url + '/payments/create_subscription?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: request.base_url + '/payments/subscription1',
    })

  end

def create_subscription
end

ドキュメントにはsessionに@はついていませんが、viewにsession_idを渡す必要があるので、@を付けます。
priceの欄に、先ほどダッシュボード上で商品を作成したときに発行されたprice_idを入力します。

今はcreate_subscriptionメソッドに何も書かなくていいです。ただ、今の設定ですと決済完了した時にはこのメソッドに遷移するようになっているので、viewファイルにcreate_subscription.html.erbを作成し、決済完了したことがわかるように何か書くといいかなと思います。

create_subscription.html.erb
<p>できたよ</p>

決済画面を実装

new_subscription.html.erb
<script src="https://js.stripe.com/v3"></script>

<script>
var stripe = Stripe('pk_test_XXXX');
stripe.redirectToCheckout({
sessionId: '<%= @session.id %>'
}).then(function (result) {
});
</script>

Stripe('pk_test_XXXX')のカッコ内には、公開可能APIキーを入れてください。シークレットキーとは別のものなので、注意してください。先ほどシークレットキーを取得したStripeダッシュボードからPublishable keyをコピーし、貼り付けましょう。

ドキュメントでは決済画面に遷移する前にボタンが実装されていますが、ボタンが不要だと思ったので今回は省いています。ボタンが必要な方はドキュメントを参考にしてください。

試しに決済

これで決済画面ができたので、遷移してみましょう。

こちらの画面に、テストカードを利用して決済してみましょう。
テストカードには、カード番号に4242 4242 4242 4242と入力すれば、後の記入欄はなんでもいいです。

決済完了し、この画面になるとおそらく決済できたと思います。Stripeダッシュボードでも確認できます。

create.subscription.html.erbの画面↓

session_id

レスポンスにはsession_idが返ってきています。これは、決済ごとに発行されるIDです。

こちらのsession_idを取り出すと、色々な情報が出てきます。取り出し方は以下です。

session_idを取り出す
Stripe::Checkout::Session.retrieve(
  'cs_test_XXXX',
)
レスポンス
{
  "id": "cs_test_XXXX",
  "object": "checkout.session",
  "allow_promotion_codes": null,
  "amount_subtotal": null,
  "amount_total": null,
  "billing_address_collection": null,
  "cancel_url": "https://example.com/cancel",
  "client_reference_id": null,
  "currency": null,
  "customer": null,
  "customer_email": null,
  "livemode": false,
  "locale": null,
  "metadata": {},
  "mode": "payment",
  "payment_intent": "pi_XXXX",
  "payment_method_types": [
    "card"
  ],
  "payment_status": "unpaid",
  "setup_intent": null,
  "shipping": null,
  "shipping_address_collection": null,
  "submit_type": null,
  "subscription": null,
  "success_url": "https://example.com/success",
  "total_details": null
}

この情報のどれかをDBに保存したい場合は、こちらから保存するといいかなと思います。例えば、customer_idを保存したい場合は以下のようになると思います。

payments_controller.rb
def create_subscription
  session = Stripe::Checkout::Session.retrieve(params[:session_id])
  Payment.create(customer_id: session.customer)
end

まとめ

StripeのAPIバージョンは2020年8月末で更新されています(おそらく)。このバージョンから仕組みが大きく変わっているところがあり、この日以前のQiitaの記事があまり参考にならない場合があります。例えば、price_idの登場だとか、ですね。

このバージョンの日本語記事が少なく、Stripeのドキュメントも英語で、かつドキュメントにあるRubyコードのサンプルはSinatra用となっているので、、Railsで実装をしようとすると難しい部分がありますね。

これからStripe系の記事もいくつか投稿していこうと思います。

参考資料

Stripeドキュメント: (Dynamic subscriptions の After 部分)
Stripe APIリファレンス: セッションを取得する
Qiita: Rails5.2でStripeを使う(v3)