
前回に引き続き、今回も決済機能を追加していきたいと思います!
今回やること
・購入が確定した時点でカートが空になる
こんな感じで今回もやっていきたいと思います!!
参考にした記事
今回もこちらのページを参考にさせて頂きました!
作成手順
支払いの合計額の設定
前回では合計金額を設定してなかったので、まずは合計金額を設定していきます。
<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_id
をcontroller
に渡していきます。
<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)
では、カートに入ってる商品の合計金額を計算します。
そしてStripe
のamount
に渡してあげれば、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
では例外を発生させないので、今回は上記のメソッドを使用しました。
これで、決済とともにカートの中身が下記のようになくなったはずです。

まとめ
今回は決済完了と同時にカートの中身を空にする機能を設定しました!
次回は、購入履歴の保存と保存と同時にカートの中身を空にする機能をつけていきます。
最後まで読んでいただきありがとうございました🙇♂️