某スクールにおいて、チーム開発で、フリーマーケットアプリを作成中であり、使用した技術について公開しています。
※初学者のため、ミスや認識違いが多々あると思いますがご了承ください。
フリマアプリにおいて、PAY.JPを用いたクレジットカード決済機能を実装しました!!
前回記事
今回の記事は運用編(購入)となります。
それでは、実際にPAY.JPを用いてクレジットカード機能を用いた購入ができるように実装して行きたいと思います。
##カード情報表示
「購入する」ボタンをクリックしたら、cardsコントローラーのshowアクションに遷移します。
遷移先の「購入確認画面」です。ご覧のように、カードの情報が記載されているため、showコントローラーではユーザーに紐づいたカード情報を取得してくる必要があります。
では、showコントローラーを確認してみます。
class CardsController < ApplicationController
require 'payjp'
before_action :set_item, only:[:show,:pay]
before_action :take_card, only:[:show,:pay]
before_action :set_api_key
def show
if @card.blank?
#登録された情報がない場合にカード登録画面に移動
flash[:alert] = '購入前にカード登録してください'
redirect_to cards_path and return
else
#保管した顧客IDでpayjpから情報取得
set_customer
#保管したカードIDでpayjpから情報取得、カード情報表示のためインスタンス変数に代入
set_card_information
end
if current_user.address == nil
flash[:alert] = '購入前に住所登録してください'
redirect_to new_address_path
end
end
private
def set_item
@item = Item.find(params[:id])
@address = Address.find_by(user_id:current_user.id)
end
def set_api_key
Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_PRIVATE_KEY]
binding.pry
end
def set_customer
@customer = Payjp::Customer.retrieve(@card.customer_id)
end
def set_card_information
@card_information = @customer.cards.retrieve(@card.card_id)
end
def take_card
@card = Card.find_by(user_id: current_user.id)
end
end
解説します。
まずは before_action :set_item が実行されます。これは、商品と配送先住所を引っ張ってくるためで、クレジットカード決済とは直接関係はありません。
次に before_action :take_card が実行されます。
cardsテーブルから現在のユーザーに紐づくレコードを変数@cardに格納します。(payjp側に保存してる顧客データーではありません。)
def show
if @card.blank?
#登録された情報がない場合にカード登録画面に移動
flash[:alert] = '購入前にカード登録してください'
redirect_to cards_path and return
else
登録しているカード情報がなければ、カード新規登録画面へ遷移します。
「and return」は直接関係ないので、後ほど番外で説明します。
else
#保管した顧客IDでpayjpから情報取得
set_customer
#保管したカードIDでpayjpから情報取得、カード情報表示のためインスタンス変数に代入
set_card_information
カードが登録されている場合は、set_customerメソッドが呼び出されます。
def set_customer
@customer = Payjp::Customer.retrieve(@card.customer_id)
end
@cardのcustomer_idを元に、Payjpから顧客データーを取得して、変数@customerに格納します。
次に set_card_informationメソッドが呼び出されます。
def set_card_information
@card_information = @customer.cards.retrieve(@card.card_id)
end
@customerに紐づく、クレジットカード情報を取得して 変数@card_informationに格納します。
これにより、クレジットカードの情報を表示することができます。ちなみに、カード情報を表示するhaml部分は以下の通りです。
-# カード番号
= "**** **** **** " + @card_information.last4
-# 有効期限
- exp_month = @card_information.exp_month.to_s
- exp_year = @card_information.exp_year.to_s.slice(2,3)
= exp_month + " / " + exp_year
Payjp側でlast4というキーに下4桁を格納してくれています。
##クレジットカードを用いて購入する
「購入する」をクリックしたら、cardsコントローラーのpayアクションへと遷移するようにリンクをはっています
cardsコントローラーのpayアクションを見てみます。
class CardsController < ApplicationController
require 'payjp'
before_action :set_item, only: [:show,:pay]
before_action :take_card, only:[:show,:pay]
before_action :set_api_key
def pay
@item.update(buyer_id: current_user.id)
# 現在のユーザーを購入者に登録
Payjp::Charge.create(
:amount => @item.price,
:customer => @card.customer_id,
:currency => 'jpy', #日本円
)
redirect_to item_purchase_index_path(@item.id)
# 購入確認画面に遷移
end
private
def set_item
@item = Item.find(params[:id])
@address = Address.find_by(user_id:current_user.id)
end
def set_api_key
Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_PRIVATE_KEY]
binding.pry
end
def take_card
@card = Card.find_by(user_id: current_user.id)
end
end
解説します。
before_action :set_item で 購入しようとしているItemが@itemに、ユーザーの配送先が@addressに格納されています。クレジットカード購入機能と直接は関係ありません。
before_action :take_card
before_action :set_api_key
については、showアクションの時と同じです。
def pay
@item.update(buyer_id: current_user.id)
現在のユーザーを購入者に登録として、buyer_idカラムに格納します。クレジットカード購入機能と直接は関係ありません。
Payjp::Charge.create(
:amount => @item.price,
:customer => @card.customer_id,
:currency => 'jpy', #日本円
)
商品の値段や、@cardに紐づく顧客データーを元に、payjp側で決済してくれます。
無事に決済が完了したら、以下のようにpayjp側に反映されます。
以上でクレジットカードを用いた購入機能が実装できました。