もふもふ技術部

IT技術系mofmofメディア

【Rails】Stripe決済で買い切りプレミアムプランを実装する

Stripe決済第二弾です。
今回は前回サブスクで実装したプレミアムプランを買い切りで実装してみます。
下準備は前回の記事を参考にしてみてください。

www.mof-mof.co.jp

決済を実装する

料金を作成する

こちら で料金を作成します。
前回作成したプレミアムプランに料金を追加します。

前回作成したプレミアムプラン

「料金」の右側にある「+」を押し、以下の画像のように入力して登録します。

料金追加画面

料金を追加することができました。
先ほど作成した「¥1,000」を選択します。

画面右上にある 「price_~~~」は後で使用するのでコピーしておきましょう。

料金の詳細

プレミアムプランへの動線を作る

ルーティングを追加します。

config/routes.rb

resources :plans, only: [:index]
コントローラーを作成します。

app/controllers/plans_controller.rb

class PlansController < ApplicationController
  def index; end
end
viewsを作成します。

app/viewa/plans/index.html.erb

<%= button_to checkouts_path, data: { turbo: false } do %>
  プレミアムプラン(¥1,000)に申し込む
<% end %>

Stripeで決済する

ルーティングを追加します。

config/routes.rb

resources :checkouts, only: [:create]
コントローラーを作成します。

app/controllers/checkouts_controller.rb

class CheckoutsController < ApplicationController
  def create
    create_customer if current_user.customer_id.blank?

    price_id = 'price_~~~' #先ほどコピーした値
    session = Stripe::Checkout::Session.create(
      customer: current_user.customer_id,
      mode: "payment",
      payment_method_types: ["card"],
      line_items: [
        {
          quantity: 1,
          price: price_id
        }
      ],
      success_url: root_url,
      cancel_url: plans_url
    )

    redirect_to session.url, allow_other_host: true
  end

  private

  def create_customer
    customer = Stripe::Customer.create({
      name: current_user.name,
      email: current_user.email,
    })
    current_user.update(customer_id: customer.id)
  end
end

ここまでで決済ができるようになっています。
実際に「プレミアムプラン(¥1,000)に申し込む」ボタンを押してみると、Stripeのカード情報入力ページへ遷移すると思います。

Stripeのカード情報入力ページ

ここで使用できるテストカードは こちら を参考にしてください。

Webhookを使用できるようにする

Stripe CLIをインストールします。

ローカル環境でWebhookを使用するためにStripe CLIをインストールします。

$ brew install stripe/stripe-cli/stripe
CLIにログインします。
$ stripe login
ローカル環境にイベントを送信します。
 stripe listen --forward-to localhost:3000/webhooks

「Your webhook signing secret is whsec_~~」 と表示されるかと思います。
ここに表示されている、 whsec_~~~ はWebhook用のsecretなのでコピーしましょう。

環境変数を追記します。
$ rails credentials:edit -e development 

エディタが開いたら以下を参考にWebhook用のsecretを設定します。

stripe:
  publishable_key: pk_test_~~~~
  secret_key: sk_test_~~~~
  endpoint_secret: whsec_~~~~

Stripeで決済した情報を保存する

Stripeで決済した情報を保存できるようにWebhookを実装します。

ルーティングを追加します。

config/routes.rb

resources :webhooks, only: [:create]
コントローラーを作成します。

app/controllers/webhooks_controller.rb

class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token
  skip_before_action :signed_in_user

  def create
    payload = request.body.read
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    endpoint_secret = Rails.application.credentials.dig(:stripe, :endpoint_secret)
    event = nil

    begin
      event = Stripe::Webhook.construct_event(
        payload, sig_header, endpoint_secret
      )
    rescue JSON::ParserError => e
      # Invalid payload
      p e
      status 400
      return
    rescue Stripe::SignatureVerificationError => e
      # Invalid signature
      p e
      status 400
      return
    end

    case event.type
    when 'checkout.session.completed'
      session = event.data.object
      user = User.find_by(customer_id: session.customer)
      return unless user

      ApplicationRecord.transaction do
        line_item = Stripe::Checkout::Session.list_line_items(session.id).data.first
        Payment.create!(
          user_id: user.id,
          product_id: line_item.price.product,
          price_id: line_item.price.id,
          customer_id: session.customer,
          price: line_item.price.unit_amount,
        )
        user.update!(premium: true)
      rescue => e
        p e
      end
    end
  end
end

決済情報を保存したあとは、ユーザーがプレミアム会員になった旨を保存して完成です。

終わり

これで実装完了です。
買い切りのプランがあると、長期で使用するユーザーに喜んでもらえそうですね!