【フリマアプリ】PAY.JPでのクレジットカード決済機能について(第3回) 〜運用編(購入)〜


 某スクールにおいて、チーム開発で、フリーマーケットアプリを作成中であり、使用した技術について公開しています。
※初学者のため、ミスや認識違いが多々あると思いますがご了承ください。

フリマアプリにおいて、PAY.JPを用いたクレジットカード決済機能を実装しました!!

前回記事 

今回の記事は運用編(購入)となります。

それでは、実際にPAY.JPを用いてクレジットカード機能を用いた購入ができるように実装して行きたいと思います。

カード情報表示

「購入する」ボタンをクリックしたら、cardsコントローラーのshowアクションに遷移します。

遷移先の「購入確認画面」です。ご覧のように、カードの情報が記載されているため、showコントローラーではユーザーに紐づいたカード情報を取得してくる必要があります。

では、showコントローラーを確認してみます。

cards_controller
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

@cardcustomer_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アクションを見てみます。

cards_controller.rb
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側に反映されます。

以上でクレジットカードを用いた購入機能が実装できました。