PROGRAMMING

RailsでECサイトを作る!【決済機能の追加⑵】









前回に引き続き、今回も決済機能を追加していきたいと思います!

今回やること
・購入が確定した時点でカートが空になる

こんな感じで今回もやっていきたいと思います!!

参考にした記事

今回もこちらのページを参考にさせて頂きました!

作成手順

支払いの合計額の設定

前回では合計金額を設定してなかったので、まずは合計金額を設定していきます。

<div class='container'>
    <div class ='header-cart'>
        <h1 class='text-center mb-50'>カートの中身</h1>
    </div>
    <ul class='list-group'>
        <% @products.each do |product| %>
        <li class='list-group-product d-flex justify-content-between border p-3'>
        <p><%= product.name %></p>
        <span><%= product.price %>円 <a><%= link_to '×',product_delete_in_carts_path(product), method: :post, data: {confirm: '削除してもいいですか?'} %></a></span>
        </li>
        <% end %>
    </ul>
  <p class='text-right mt-3'>合計金額 <%= @products.sum(:price) %>円</p>

上のように表示されているので、これでOKですね!

それでは、カートの部分にStripeのフォームを設置していきます。

<div class='container'>
    <div class ='header-cart'>
        <h1 class='text-center mb-50'>カートの中身</h1>
    </div>
    <ul class='list-group'>
        <% @products.each do |product| %>
        <li class='list-group-product d-flex justify-content-between border p-3'>
        <p><%= product.name %></p>
        <span><%= product.price %>円 <a><%= link_to '×',product_delete_in_carts_path(product), method: :post, data: {confirm: '削除してもいいですか?'} %></a></span>
        </li>
        <% end %>
    </ul>
  <p class='text-right mt-3'>合計金額 <%= @products.sum(:price) %>円</p>

<%= form_tag charge_path do%>
      <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
          data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
          data-description="payment"
          data-amount=<%= @products.sum(:price) %>
          data-currency="jpy"
          data-locale="auto">
   </script>
<% end %>
</div>

下記のcharge/show.html.erbの一部を上記のように貼り付けただけです。

そうすると下記のように決済ボタンが設置されます。

ボタンを押すとこんな感じになります。

data-amountの部分で設定した値が、"~を支払う"の部分で表示されるようになっています。しかし、このボタンを押しても実際に決済が実行される訳ではありません。実際に決済処理を行うためにcontroller側で決済の設定をしていきます。

class ChargesController < ApplicationController
  def create
    Stripe.api_key = ENV['STRIPE_SECRET_KEY']
    token = params[:stripeToken]
    Stripe::Charge.create({
      amount: 999,
      currency: 'jpy',
      description: 'Example charge',
      source: token
    })
    redirect_to root_path, notice: '決済に成功しました'
  end
end

元々のコードは上記のサンプルコードのままなので、正しく決済できるように修正していきます。実際このまま決済をすると999円だけ決済されるようになります。Stripeのダッシュボードで確認することができます。

controllerの設定

productのIDをフォームからcontrollerに渡し、カートの商品の合計金額を計算して、カートの商品だけを購入履歴に追加する必要があります。

それでは、product_idcontrollerに渡していきます。

<div class='container'>
    <div class ='header-cart'>
        <h1 class='text-center mb-50'>カートの中身</h1>
    </div>
    <ul class='list-group'>
        <% @products.each do |product| %>
        <li class='list-group-product d-flex justify-content-between border p-3'>
        <p><%= product.name %></p>
        <span><%= product.price %>円 <a><%= link_to '×',product_delete_in_carts_path(product), method: :post, data: {confirm: '削除してもいいですか?'} %></a></span>
        </li>
        <% end %>
    </ul>
  <p class='text-right mt-3'>合計金額 <%= @products.sum(:price) %>円</p>

<%= form_tag charge_path do%>
    <%= hidden_field_tag 'product_ids[]', @products.ids %>
      <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
          data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
          data-description="payment"
          data-amount=<%= @products.sum(:price) %>
          data-currency="jpy"
          data-locale="auto">
   </script>
<% end %>
</div>
class ChargesController < ApplicationController
  def create
    Stripe.api_key = ENV['STRIPE_SECRET_KEY']
    token = params[:stripeToken]
    product_ids = params[:product_ids].map(&:to_i)

    Stripe::Charge.create({
      amount: 999,
      currency: 'jpy',
      description: 'Example charge',
      source: token
    })
    redirect_to root_path, notice: '決済に成功しました'

    rescue Stripe::CardError => e
      flash[:error] = e.message
      redirect_to cart_path
    end
  end
end

hidden_field_tagはフォームを非表示にしつつ、値をcontrollerに送ることができます。

配列の要素は文字列で値が渡されるので、to_iで数字に変換します。

それでは、合計金額を設定していきたいと思います。

class ChargesController < ApplicationController

    def create
      Stripe.api_key = ENV.fetch('STRIPE_SECRET_KEY')
      token = params[:stripeToken]
      product_ids = params[:product_ids].map(&:to_i)
      cart_products = current_user.cart.cart_products.where(id: product_ids)
      total = products.sum(:price)
            
      Stripe::Charge.create({
          amount: total,
          currency: 'jpy',
          description: 'Example charge',
          source: token,
      })
      redirect_to root_path, notice: '決済に成功しました'
      
    rescue Stripe::CardError => e
      flash[:error] = e.message
      redirect_to cart_path
    end
end

products = current_user.cart.products.where(id: product_ids)では、カートに入っている商品と同じIDの商品を検索しています。total = products.sum(:price)では、カートに入ってる商品の合計金額を計算します。

そしてStripeamountに渡してあげれば、OKです。

これで正しい合計金額が計算されたはずです。Stripeサイトのダッシュボードで確認してみましょう。

決済と同時にカートを空にする

購入対象の商品IDはcontroller側で取得できているので、決済時にカートから削除していきます。

class ChargesController < ApplicationController
  
    def create
      Stripe.api_key = ENV.fetch('STRIPE_SECRET_KEY')
      token = params[:stripeToken]
      product_ids = params[:product_ids].map(&:to_i)
      products = current_user.cart.products.where(id: product_ids)
      cart_products = current_user.cart.cart_products.where(product_id: product_ids)
      cart_products.each(&:destroy!)
      total = products.sum(:price)
            
      Stripe::Charge.create({
          amount: total,
          currency: 'jpy',
          description: 'Example charge',
          source: token,
      })
      redirect_to root_path, notice: '決済に成功しました'
      
    rescue Stripe::CardError => e
      flash[:error] = e.message
      redirect_to cart_path
    end
end

 カートの商品を消すために、中間テーブルのcart_productsも削除します。

cart_products = cart.cart_products.where(product_id: product_ids)では、idで関連するテーブルを探します。

cart_products.each(&:destroy!)では、カートの商品を削除しています。delete_allでは例外を発生させないので、今回は上記のメソッドを使用しました。

これで、決済とともにカートの中身が下記のようになくなったはずです。

まとめ

今回は決済完了と同時にカートの中身を空にする機能を設定しました!

次回は、購入履歴の保存と保存と同時にカートの中身を空にする機能をつけていきます。

最後まで読んでいただきありがとうございました🙇‍♂️

-PROGRAMMING

Copyright © Iseblog ,@2020 All Rights Reserved.