Ruby
JavaScript
Rails
pay.jp

Payjpでクレジットカード登録と削除機能を実装する(Rails)


実装する機能と前提条件

今回、Payjp(Pay.jp)を利用して入力フォームを直接ページ内に設置します。

実装するものとしては下記のとおりです。


  • 自作のカード情報入力フォーム

  • カード情報とユーザーの紐づけ

  • ユーザーとカードの登録と削除


  • 商品の購入次回の記事参照

イメージとしてはこんな感じの入力フォームです。

image.png

もしSDKを使う場合は別記事をご覧いただくかPAY.JP API 利用ガイド | PAY.JPを触るとイメージをつかみやすいと思います。


バージョン情報


  • ruby 2.3.1

  • Rails 5.0.7


前提条件


  • hamlでの記載(gem 'haml-rails')

  • deviseが導入済みでログインができている

→Devise未導入や何もない状態からスタートする場合は、

『Devise導入の設定手順 ~haml使用/pay.jp導入の前準備~ (Rails)』を先に実施ください。


1.Payjpのアカウントを作成しよう

Payjpのサイトでアカウントを作成します。


2.APIを確認しよう

ダッシュボードのAPIより確認ができます。

今回はテストモードでの実装なので、テスト秘密鍵テスト公開鍵を使用します。

スクリーンショット 2019-04-14 16.31.04.png


3.payjpのgemを設置しよう

下記をgemfileに記載しbundle installを実施します。

gem 'payjp'


4.payjp.jsを読み込めるようにしよう

%script{src: "https://js.pay.jp/", type: "text/javascript"}を下記の通り追記します。


app/views/layouts/application.html.haml

%html

%head
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title payjptest
%script{src: "https://js.pay.jp/", type: "text/javascript"}
-# このscriptを記載
= csrf_meta_tags
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
= javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
%body
= yield


5.テーブルを作成しよう

下記コマンドでpayjpのデータを保管するテーブルを作成します。

rails g model Card user_id:integer customer_id:string card_id:string

テーブルのカラムの紐づけは下記の通りです。


  • user_id ... Userテーブルのid

  • customer_id ... payjpの顧客id

  • card_id ... payjpのデフォルトカードid

(デフォルトカードidはトークンとは違います。ここの理解で結構時間をとってしまいました…)

作成したマイグレーションファイルは下記のとおりです。nullはお好みでつけてください。


db/migrate/20190400000000_create_cards.rb

class CreateCards < ActiveRecord::Migration[5.0]

def change
create_table :cards do |t|
t.integer :user_id, null: false
t.string :customer_id, null: false
t.string :card_id, null: false
t.timestamps
end
end
end

マイグレーションを実施します。

$ rails db:migrate

ちなみにカード情報そのものを保存することは禁止されていますので、

payjpに保管されている情報を顧客idやカードidで呼び出すことで情報取得や支払いなどに対応します。

カード情報非通過化対応のお願い


6.コントローラーを作成しよう

下記コマンドでコントローラーを作成します。

後ほどビューも2つ(new,show)作るのでそれも付け加えておきます。

$ rails g controller card new show

作成したコントローラーの内容を変更します。


app/controllers/card_controller.rb

class CardController < ApplicationController

require "payjp"

def new
card = Card.where(user_id: current_user.id)
redirect_to action: "show" if card.exists?
end

def pay #payjpとCardのデータベース作成を実施します。
Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
if params['payjp-token'].blank?
redirect_to action: "new"
else
customer = Payjp::Customer.create(
description: '登録テスト', #なくてもOK
email: current_user.email, #なくてもOK
card: params['payjp-token'],
metadata: {user_id: current_user.id}
) #念の為metadataにuser_idを入れましたがなくてもOK
@card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card)
if @card.save
redirect_to action: "show"
else
redirect_to action: "pay"
end
end
end

def delete #PayjpとCardデータベースを削除します
card = Card.where(user_id: current_user.id).first
if card.blank?
else
Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
customer = Payjp::Customer.retrieve(card.customer_id)
customer.delete
card.delete
end
redirect_to action: "new"
end

def show #Cardのデータpayjpに送り情報を取り出します
card = Card.where(user_id: current_user.id).first
if card.blank?
redirect_to action: "new"
else
Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
customer = Payjp::Customer.retrieve(card.customer_id)
@default_card_information = customer.cards.retrieve(card.card_id)
end
end
end


コントローラ内のENV["PAYJP_PRIVATE_KEY"]は環境変数でテスト秘密鍵を設定し読み込みます。

私はdotenvを利用していますので、下記のような形で記載しました。


.env

PAYJP_PRIVATE_KEY = 'sk_test_000000000000000000000000'

PAYJP_KEY = 'pk_test_00000000000000000000000'


7.カードの登録画面を作成しよう

今回は登録画面と確認兼削除画面の2つを作成します。デザインはアレンジしてください。

尚、ルーティングがまだなので画面の表示は『10.カードを登録してみよう』までお待ち下さい。

登録画面


app/view/card/new.html.haml

= form_tag(pay_card_index_path, method: :post, id: 'charge-form',  name: "inputForm") do

%label カード番号
= text_field_tag "number", "", class: "number", placeholder: "半角数字のみ" ,maxlength: "16", type: "text", id: "card_number"
%br
%label 有効期限
%select#exp_month{name: "exp_month", type: "text"}
%option{value: ""} --
%option{value: "1"}01
%option{value: "2"}02
%option{value: "3"}03
%option{value: "4"}04
%option{value: "5"}05
%option{value: "6"}06
%option{value: "7"}07
%option{value: "8"}08
%option{value: "9"}09
%option{value: "10"}10
%option{value: "11"}11
%option{value: "12"}12
%span 月/
%select#exp_year{name: "exp_year", type: "text"}
%option{value: ""} --
%option{value: "2019"}19
%option{value: "2020"}20
%option{value: "2021"}21
%option{value: "2022"}22
%option{value: "2023"}23
%option{value: "2024"}24
%option{value: "2025"}25
%option{value: "2026"}26
%option{value: "2027"}27
%option{value: "2028"}28
%option{value: "2029"}29
%span
%br
%label セキュリティコード
= text_field_tag "cvc", "", class: "cvc", placeholder: "カード背面3~4桁の番号", maxlength: "4", id: "cvc"
#card_token
= submit_tag "追加する", id: "token_submit"

image.png

最初、= sectionを使っていたのですがうまく行かなかったため

%optionが連続発生し駄長なコードになっているのはご了承ください…

確認兼削除画面


app/view/card/show.html.haml

%label 登録クレジットカード情報

%br
= "**** **** **** " + @default_card_information.last4
%br
- exp_month = @default_card_information.exp_month.to_s
- exp_year = @default_card_information.exp_year.to_s.slice(2,3)
= exp_month + " / " + exp_year
= form_tag(card_delete_path, method: :post, id: 'charge-form', name: "inputForm") do
%input{ type: "hidden", name: "card_id", value: "" }
%button 削除する

image.png


8.Payjpにデータを送りトークンを取得しよう

提供されているpay.jpのサンプルを参照し一部アレンジしております。

jQueryを使用するので、railsに未設定の場合は設定をしてください。

設定方法はこちら


app/assets/javascripts/payjp.js

document.addEventListener(

"DOMContentLoaded", e => {
if (document.getElementById("token_submit") != null) { //token_submitというidがnullの場合、下記コードを実行しない
Payjp.setPublicKey("pk_test_79ae2d2743199a76f3eb36aa"); //ここに公開鍵を直書き
let btn = document.getElementById("token_submit"); //IDがtoken_submitの場合に取得されます
btn.addEventListener("click", e => { //ボタンが押されたときに作動します
e.preventDefault(); //ボタンを一旦無効化します
let 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) => {
if (status === 200) { //成功した場合
$("#card_number").removeAttr("name");
$("#cvc").removeAttr("name");
$("#exp_month").removeAttr("name");
$("#exp_year").removeAttr("name"); //データを自サーバにpostしないように削除
$("#card_token").append(
$('<input type="hidden" name="payjp-token">').val(response.id)
); //取得したトークンを送信できる状態にします
document.inputForm.submit();
alert("登録が完了しました"); //確認用
} else {
alert("カード情報が正しくありません。"); //確認用
}
});
});
}
},
false
);


9.ルートを作成しよう

今回はshow,pay,new,deleteの4つのメゾットがあるので下記の通り追記します。

一部はresoursesで設定してもよいかと思います。


config/routes.rb

resources :card, only: [:new, :show] do

collection do
post 'show', to: 'card#show'
post 'pay', to: 'card#pay'
post 'delete', to: 'card#delete'
end
end


10.カードを登録してみよう

http://localhost:3000/card/new にアクセスして登録できるか確認してみましょう。

その時、下記のテストカードで登録するようにしてください。

それ以外を打ち込んだ場合はトークンが発行できずはねられてしまいます。

image.png

以上でカード登録から削除まで一通り実装できました。

次回はこれを使って商品支払いを実装します。


参考