Rails5.2にPayjp(クレジットカード管理システム)を導入する。vol.1顧客ID作成

目次

目的

Rails 5.2にPayjpを導入してクレジットカードを登録する。

Payjpとは

開発者がクレジットカード情報を扱わなくてもいいように、入力されたカード情報をトークンに置き換えて管理するものです。

なぜPayjpを使うのか

クレジットカードの情報をデータベースに保存して管理するのはセキュリティリスクが高いため、情報をトークン化(暗号化)してやりとりする方法が推奨されているためです。

(前提、環境)

mac
macOS Mojave 10.14.5
ruby 2.5.1
rails 5.2.3

はじめに

公式

PAY.JP API 利用ガイド

参考記事

導入手順

Payjpのgemを導入

Gemfileに追記してbundle installします。

# Gemfile
gem 'payjp'
# ターミナル
$ bundle install

userモデルとcardモデルを作成

クレジットカードを取り扱うためのモデルを作成します。
今回はcardモデルとして作成します。
また、登録者としてuserモデルを作成してアソシエーションを組んでおきます。
簡単なログイン機能も実装したいのでdeviseも合わせて導入します。

deviseのgemを導入

Gemfileに追記してbundle installします。

# Gemfile
gem 'devise'
# ターミナル
$ bundle install
$ rails g devise:install
$ rails g devise user
$ rake db:migrate

ルーティングは以下のように設定しておきます。
※仮置きです。

# config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  root "cards#index"
  resources :cards
end
# ターミナル
$ rails g model card
$ rails g devise user

カードモデルに関して、あとでトークンについて解説しますが、顧客IDを絶対保存させるバリデーションを設定しておきます。
また、カードとユーザーは1対1の関係性を示すためhas_oneでアソシエーションを組んでいます。

# app/models/card.rb
class Card < ApplicationRecord
  belongs_to :user, optional: true
  validates :customer_token, presence: true
end

# app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_one :card, optional: true
end

またcardのマイグレーションは下記のようにします。
※userはdeviseを利用し他ので特に変更なしです。必要に応じてカラムを追加してください。

# db/migrations/~~~~~~~~~create_cards.rb
class CreateCards < ActiveRecord::Migration[5.2]
  def change
    create_table :cards do |t|
      t.string :customer_token, null: false
      t.references :user, forign_key: true
      t.timestamps
    end
  end
end

Payjp APIの登録

公式サイトにアクセス

公式サイトにアクセスします。
https://pay.jp/signup

ログイン

payjpログイン

APIキーを確認

https://pay.jp/d/settings
こちらにアクセスした上で登録されているAPIキーを確認しましょう!
こちらのキーはあとで登録に使うので要注意です!
payjpのAPIキー

Railsにキーをセット

今回Rails 5.2を入れているのでcredentials.ymlでセットします。

# ターミナル
$ EDITOR="vi" bin/rails credentials:edit

credentials.ymlが開いたら下記を登録しましょう。

payjp:
  public_key: pkで始まる公開鍵
  secret_key: skで始まる秘密鍵

Payjpのキーを使う

例としてあげますが、コントローラ内では以下のようにしてセットして使います。

# app/controllers/cards_controller.rb
Class CardsController < ApplicationController
  def index
    Payjp.api_key = Rails.application.credentials.payjp[:secret_key]
  end
end

カード情報のトークン化

リファレンス(Payjp API公式サイト)を参照して作っていきます。
公式サイトをほぼそのまま活用しているのですが、jQueryを利用しての前提とした実装になっています。
今回はサンプルに記載のpayjp.jsを少しカスタマイズして作成していきます。

jQueryをRailsに導入

# Gemfile
gem 'jquery-rails'
# ターミナル
$ bundle install
# app/javascripts/application.js
//= require rails-ujs
//= require activestorage
//= require turbolinks
# ----追記----
//= require jquery
//= require rails-ujs
# -----------
//= require_tree .

登録フォームを実装

日付の入力部分など少し適当です笑
今回重要なのはpayjpのJavaScriptを読み込むためにscriptタグでpayjpが用意したファイルを呼び出していることです。

# app/views/cards/index.html.erb
<script type="text/javascript" src="https://js.pay.jp/"></script>
<script type="text/javascript">Payjp.setPublicKey("<pkから始まる公開鍵を入力します>");</script>
<%= form_with model: @card, id: "card_form" do |f| %>

  <span class="charge-errors"></span>

  <h4>支払い</h4>
  <%= f.label :number, "カード番号"%>
  <%= f.text_field :number, class: "number", maxlength: "16", placehplder: "カード番号"%>

  <%= f.label :cvc, "CVC"%>
  <%= f.number_field :cvc, class: "cvc", maxlength: "3", placehplder: "CVC"%>

  <%= f.label :exp_month, "有効期限"%>
  <%= f.number_field :exp_month, class: "exp_month", maxlength: "2", placehplder: "月"%>
  <%= f.number_field :exp_year, class: "exp_year", maxlength: "4", placehplder: "年"%>

  <%= f.submit "送信" ,id: "regist_card"%>
  <div id="card_token"></div>
<% end %>

カードトークン作成

リファレンス(Payjp API公式サイト)を参照し、railsで用いているturbolinksの設定を追加しました。
また、カードトークンの説明です。

カード情報を代替するトークンオブジェクトです。
トークンは、カード番号やCVCなどのセキュアなデータを隠しつつも、カードと同じように扱うことができます。
顧客にカードを登録するときや、支払い処理を行うときにカード代わりとして使用します。
一度使用したトークンは再び使用することはできませんが、 顧客にカードを登録すれば、顧客IDを支払い手段として用いることで、何度でも同じカードで支払い処理ができるようになります。

通常inputタグに入力された値はparamsに渡されてコントローラーに向かいますが、クレジットカードの番号などの情報をparamsにそのまま入れることは禁じられています。(そのためにpayjpがあるのですが。)
そのため、一旦それらの貴重な情報を暗号化したトークンにして管理してしまうのです。
以下がリファレンスを参照にしたJavaScriptです。

# app/assets/javascripts/cards.js
$(document).on('turbolinks:load', function () {
  var form = $("#card_form");
    number = form.find(".number"),
    cvc = form.find(".cvc"),
    exp_month = form.find(".exp_month"),
    exp_year = form.find(".exp_year");

  $("#card_form").on("click", "#regist_card", function (e) {
    e.preventDefault();
    form.find("input[type=submit]").prop("disabled", true);
    var card = {
      number: number.val(),
      cvc: cvc.val(),
      exp_month: exp_month.val(),
      exp_year: exp_year.val()
    };

    Payjp.createToken(card, function (s, response) {

      if (response.error) {
        alert("error")
        form.find('button').prop('disabled', false);
      }
      else {
        $(".number").removeAttr("name");
        $(".cvc").removeAttr("name");
        $(".exp_month").removeAttr("name");
        $(".exp_year").removeAttr("name");

        var token = response.id;
        $("#card_form").append(`<input type="hidden" name="card_token" class="payjp-token" value=${token} />`)
        $("#card_form").get(0).submit();
      }
    });
  });
});

顧客IDの作成

カードトークンは一度使用すると二度と使えなくなってしまうので、顧客IDを同時に作成して保持します。

# app/controllers/cards_controller.rb
class CardsController < ApplicationController
  def index
    @card = Card.new
  end

  def create
    email = current_user.email
    Payjp.api_key = Rails.application.credentials.payjp[:secret_key]
    customer = Payjp::Customer.create(  ## 顧客の作成
      email: email,
      card: params[:card_token]
    )
    @card = Card.new(customer_token: customer&.id)
    redirect_to action: "new", alert: "カードの登録に失敗しました。" and return if @card.invalid?
    ## 保存に成功した場合
    @card.user_id = current_user.id
    @card.save
    redirect_to cards_path and return
  end
end

結果

顧客情報がトークン化されて色々なことができるようになる。

終わりに

全然機能の紹介が終わらないのでシリーズ化します。
まだ顧客情報の作成だけとは・・・・泣
※payjpの実装はリファレンスをとにかくよく読んで欲しいです!
しかし、APIのやり取りをするということのいい練習になるかと思います。
普通にアプリ作っていたらクレカの登録とかさせないといけないし必須機能ですかね〜!
自分の備忘録としても役に立ちそうです。

https://hirocorpblog.com/roadmap-engineer/

よかったらシェアしてね!
  • URL Copied!
  • URL Copied!
目次
閉じる