LoginSignup
3
1

More than 3 years have passed since last update.

【フリマアプリ】PAY.JPでのクレジットカード決済機能について(第4回) 〜コード全文〜

Posted at
cards_controller.rb
class CardsController < ApplicationController

  require 'payjp'

  before_action :set_item, only: [:show,:pay]
  before_action :card_present,only:[:index,:destroy]
  before_action :take_card,only:[:show,:pay]
  before_action :set_api_key


  def index 
    if @card.present?
      set_customer
      set_card_information
    end
  end

  def create
    if params['payjp-token'].blank?
      redirect_to action: "new"
      # トークンが取得出来てなければループ
    else
      user_id = current_user.id
      customer = Payjp::Customer.create(
      card: params['payjp-token']
      # params['payjp-token'](response.id)からcustomerを作成
      ) 
      @card = Card.new(user_id: user_id, customer_id: customer.id, card_id: customer.default_card)
      if @card.save
        flash[:notice] = '登録しました'
        binding.pry
        redirect_to "/"
      else
        flash[:alert] = '登録できませんでした'
        redirect_to action: "new"
      end
    end
  end

  def destroy #PayjpとCardのデータベースを削除
    set_customer
    @customer.delete
    if @card.destroy #削除に成功した時にポップアップを表示します。
      flash[:notice2] = '削除しました'
      redirect_to action: "index"
    else #削除に失敗した時にアラートを表示します。
      flash[:alert2] = '削除できませんでした'
      redirect_to action: "index"
    end
  end

  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

  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 card_present
    @card = Card.where(user_id: current_user.id).first if Card.where(user_id: current_user.id).present?
  end

  def set_api_key
    Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_PRIVATE_KEY]
  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
payjp.js
document.addEventListener(
  "DOMContentLoaded", e => {
    if (document.getElementById("token_submit") != null) {
      // "token_submit"というidをもつhtmlがあるページか?つまりカード作成ページか
      Payjp.setPublicKey("pk_test_ae272d63392590ed7095ba52"); 
      let btn = document.getElementById("token_submit");  // 送信ボタンをbtnに格納
      btn.addEventListener("click", e => {  // 送信ボタンがクリックされたとき
        e.preventDefault(); // デフォルトのブラウザの動きをいったんとめる(createアクションへの遷移を)
        let card = {  // cardに入力された値をハッシュで格納
          number: document.getElementById("card_number").value,
          cvc: document.getElementById("cvc").value,
          exp_month: document.getElementById("exp_month").value,
          exp_year: document.getElementById("exp_year").value
        }; 
        Payjp.createToken(card, (status, response) => {
          // カード情報をpayjpに送りカードトークンを(response.id)を受け取る。
          if (status === 200) {  // 正常な値の場合 
            $("#card_number").removeAttr("name");
            $("#cvc").removeAttr("name");
            $("#exp_month").removeAttr("name");
            $("#exp_year").removeAttr("name"); 
            // name属性を削除することにより、dataベースに送るのを防ぐ。
            $("#card_token").append(
              $('<input type="hidden" name="payjp-token">').val(response.id)
              // <input type="hidden" name="payjp-token" value= response.id>が#card_tokenに追加される。
            ); 
            document.inputForm.submit(); // inputFormのsubmitを発動。(上記で停止していた)
            alert("登録が完了しました"); 
          } else {
            alert("カード情報が正しくありません。");
          }
        });
      });
    }
  },
  false
);
migrate/20200320083820_create_cards.rb
class CreateCards < ActiveRecord::Migration[5.2]
  def change
    create_table :cards do |t|
      t.integer :user_id
      t.string :customer_id
      t.string :card_id
      t.timestamps
    end
  end
end
routes.rb
  resources :cards, only:[:index, :new, :create,:destroy,:show] do
    member do
      post 'pay'
    end
  end

ビューについては、割愛。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1