某プログラミングスクールで学習中の著者です。
Pay.jpでクレジットカード登録・削除機能を実装したので、
記録として残しておきます。
開発環境
Rails 5.2.4.2
ruby 2.5.1
実装する機能
Pay.jpでクレジットカード登録・削除機能
(登録画面も写真みたいに作ります。)
実装手順
①Pay.jpのサイトでアカウントを作成(こちらをクリック)
②gemファイルに gem 'payjp' を記載し、bundle installする
gem 'payjp'
③application.html.hamlに payjp.jsを読み込めるようにする。
%script{src: "https://js.pay.jp/", type: "text/javascript"} を追記する
(これにより、カード情報をトークン化できるようになります)
%html
%head
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title fulima
-# ↓これ
-#
= stylesheet_link_tag 'application', media: 'all'
④カード情報を保存するテーブルを作成する。
マイグレーションファイルを作成し、以下のように記載。
その後、ターミナル で rails db:migrate を行います。
def change
create_table :cards do |t|
t.integer :user_id, foreign_key: true, null: false
t.string :customer_id, null: false
t.string :card_id, null: false
t.timestamps
end
end
end
*ここに登録される customer_id、card_id を用いてPay.jpから顧客情報やカード情報を
取得します。(カード情報そのものをDBに保存する訳ではありません)
⑤コントローラーの作成
今回は credit という名前で作成しました。
pay メソッドがカードの情報を保存する処理に相当します。
class CreditController < ApplicationController
require "payjp"
before_action :set_card, only: [:index, :delete, :show]
before_action :get_payjp_info, only: [:pay, :delete, :show]
def new
end
def pay #pay.jpとcardデータベースへのデータを保存する処理
if params['payjp_token'].blank?
redirect_to action: :new
else
customer = Payjp::Customer.create(
description: 'test', #なくてもOK
email: current_user.email,#なくてもOK
card: params['payjp_token'],
metadata: {user_id: current_user.id}
)
@card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card)
if @card.save
redirect_to action: :index
else
redirect_to action: :new
end
end
end
def delete
if @card.present?
customer = Payjp::Customer.retrieve(@card.customer_id)
customer.delete
@card.delete
end
redirect_to action: :index
end
def show
if @card.blank?
redirect_to action: :index
else
customer = Payjp::Customer.retrieve(@card.customer_id)
@default_card_information = customer.cards.retrieve(@card.card_id)
end
end
def index
redirect_to action: :show,id:current_user.id if @card.present?
end
private
def get_payjp_info
Payjp.api_key = Rails.application.credentials.dig(:payjp, :PAYJP_SECRET_KEY)
end
def set_card
@card = Card.where(user_id: current_user.id).first
end
end
*get_payjp_info では、秘密鍵の設定を行っています。
今回は、credentials.yml に秘密鍵を記載したため、このような記述になっています。
*秘密鍵の確認方法、PAY.jpのAPIで確認することができます。
(今回は、テスト秘密鍵を使いました)
⑥登録画面の作成
写真のような、カード情報の登録画面を作ります。
(コード見辛くてすみません)
.mypage-content
%section.purchace
%h2.profile__top クレジットカード情報入力
.content
= form_with url: pay_credit_index_path, method: :post, html: { name: "inputForm" } do |f|
.content__inner
.resister-credit
= f.label :カード番号, class: "resister-credit__number"
%span.resister-credit__need 必須
= f.text_field :card_number, name: "number", id:"number", type: 'text', placeholder: "半角数字のみ", maxlength: "16", class:"resister-credit__text"
%ul.resister-credi__errow
%ul.resister-credi__card
= image_tag "credit01.JPG", class: "resister-credit__list"
.resister-credit.margin
= f.label :有効期限, class: "resister-credit__number"
%span.resister-credit__need 必須
%br
.resister-credit__limit
= f.select :exp_month, [["01",1],["02",2],["03",3],["04",4],["05",5],["06",6],["07",7],["08",8],["09",9],["10",10],["11",11],["12",12]],{}, class: "resister-credit__limit__mm", name: "exp_month", id: "exp_month"
%span 月
.resister-credit__limit
= f.select :exp_year, [["19",2019],["20",2020],["21",2021],["22",2022],["23",2023],["24",2024],["25",2025],["26",2026],["27",2027],["28",2028],["29",2029]],{}, class: "resister-credit__limit__mm", name: "exp_year", id:"exp_year"
%span 年
.resister-credit.margin
= f.label :セキュリティーコード, class: "resister-credit__number"
%span.resister-credit__need 必須
= f.text_field :cvc, name: "cvc", id:"cvc", type: 'text',placeholder: "カード背面4桁もしくは3桁の番号", maxlength: "4",class:"resister-credit__text"
.submitter
= f.submit "追加する", class: 'profile__top__content__button margin', id: "token_submit"
- #↓これ忘れないように!
%input{:id => "card_token", :type => "hidden"}
この時、%input{:id => "card_token", :type => "hidden"} の記載を
忘れないようにしましょう
(この後、出てくるjsで作ったトークンを送信するための記載です)
(自分はこれを忘れたせいで、丸1日悩み続けました)
document.addEventListener(
"DOMContentLoaded", e => {
if (document.getElementById("token_submit") != null) {
Payjp.setPublicKey("pk_test_fa4c0aef52ad35e72960c1b3"); //公開鍵をセット
let btn = document.getElementById("token_submit");
btn.addEventListener("click", e => {
e.preventDefault();
var card = {
number: document.getElementById("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) => {
if (status === 200) {
$("#number").removeAttr("name"); //データがDBに保存されないよう削除する
$("#cvc").removeAttr("name"); //データがDBに保存されないよう削除する
$("#exp_month").removeAttr("name"); //データがDBに保存されないよう削除する
$("#exp_year").removeAttr("name"); //データがDBに保存されないよう削除する
$("#card_token").append(
$('<input type="hidden" name="payjp_token">').val(response.id)
document.inputForm.submit();
alert("登録が完了しました");
} else {
alert("カード情報が正しくありません。");
}
});
});
}
},
false
);
⑧確認画面の作成
こんな感じの、登録情報の確認画面を作ります。
カードの登録がない時は、コントローラーでカードの登録ボタンが表示されるようにしています。
.mypage-content
%section.purchace
%h2.profile__top 支払い情報
.resister
%h3.resister__title 登録クレジットカード情報
.resister__form
= form_with url: delete_credit_index_path, method: :post, local: true do |f|
%br
.resister__form__number
= "**** **** **** " + @default_card_information.last4
%br
.resister__form__number
- exp_month = @default_card_information.exp_month.to_s
.resister__form__number
- exp_year = @default_card_information.exp_year.to_s.slice(2,3)
.resister__form__number
= exp_month + " / " + exp_year
= f.submit "削除する", class: 'resister__form__delete'
⑨ルートの作成
resources :credit, only: [:new, :index, :show] do
collection do
post :pay
post :delete
end
end
⑩テストカードで登録確認
最後はテストカード(Pay.jpで用意されているダミーのカード)で登録確認。
登録ができれば、成功です!
お疲れ様でした。
参考にさせていただいたサイト
https://qiita.com/takachan_coding/items/f7e70794b9ca03b559dd
https://pay.jp/