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
ビューについては、割愛。