LoginSignup
2
4

More than 3 years have passed since last update.

Payjp クレジットカード登録・削除

Last updated at Posted at 2020-03-03

はじめに

今回 gem payjp を使用しクレジットカードの登録・削除機能を実装したので
備忘録として書きます

バージョン情報

ruby '2.5.1'
rails '5.2.4'
mysql2 '5.6系'

導入済みのgem

gem haml-rails
gem devise

PAY.JPとは

PAY.JPの重要な機能であるカード情報のトークン化、支払い処理、定期課金を簡単に実装ができる凄い子なのです
※クレジットカード情報を保存する事は禁止されているため
payjpがトークン化(暗号化)してこちらのmysqlに返して保存できるようにしてくれます

今回下記流れを頭に入れておくと実装しやすいかも!

❶フォームにカード情報を入力し送信
❷入力されたカード情報は直接PAY.JPサーバーへ送られ、PAY.JPは一意のトークンを返す
❸サーバーサイドでトークンを受け取り、トークンを使った各種処理を行う(支払い処理、顧客へカードを紐付ける)

1.PAY.JPへ登録を行う

APIの確認

今回はテスト秘密鍵とテスト公開鍵を使用します
api.png

payjpのgemを導入

Gemfile
gem  payjp

bundle install をお忘れなく

$ bundle install

payjp.のjsを読み込めるようにする

%script{src: "https://js.pay.jp/", type: "text/javascript"}
を下記のように入れてください

app/view/layouts/application.html.haml
!!!
%html
  %head
    %meta{content: "text/html; charset=UTF-8", "http-equiv": "Content-Type"}/
    %title test
    %script{src: "https://js.pay.jp/", type: "text/javascript"}
    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag    'application', media: 'all'
    = javascript_include_tag 'application'
  %body
    = yield

テーブルを作成

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

テーブルは下記になります

db/migrate/20190400000000_create_cards.rb
class CreateCards < ActiveRecord::Migration[5.2]
  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

環境変数を設定

テスト秘密鍵とテスト公開鍵を入れます

$ vim ~/.bash_profile

i で入力できるようにして
自身のテスト秘密鍵とテスト公開鍵を入れてください

export PAYJP_PRIVATE_KEY='sk_test_*****************'
export PAYJP_KEY='pk_test_*****************'

入力できたら esc ⇨ :wp ⇨ ENTER で保存

最後に環境変数を記述したら必ず下記のコマンドで設定を有効する

$ source ~/.bash_profile

設定できているかは

$printenv

にて確認

PAYJP_PRIVATE_KEY='sk_test_*****************'
PAYJP_KEY='pk_test_*****************'

が入っていればOK!

環境変数の使用方法

ENV['PAYJP_PRIVATE_KEY']
ENV['PAYJP_KEY']

上記の表示で環境変数として使用ができます!

routesの設定

config/routes
  resources :cards,only:[:index,:new,:show]do
    collection do
      #payjpでトークン化を行う
      post 'pay', to: 'cards#pay'
      #カード削除
      post 'delete', to: 'cards#delete'
      #カード情報入力
      post 'show', to: 'cards#show'
    end
  end

Payjpのjavascripts を設定

app/asstes/javascriptsにpay.jsのファイルを作成してください

app/asstes/javascripts/pay.js
document.addEventListener(
  "DOMContentLoaded", e => {
    if (document.getElementById("token_submit") != null) { //token_submitというidnullの場合、下記コードを実行しない
      Payjp.setPublicKey("pk_test_4842a1069943b3e72c287e0b"); //ここに公開鍵を直書き
      let btn = document.getElementById("token_submit"); //IDtoken_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
);

コントローラーを作成

$ rails g controller cards new show
app/controllers/cards_controller.rb
class CardsController < ApplicationController

  require "payjp"

  def new
    #current_user.idでログインしてるユーザーのみ登録ができるようにしてます
    card = Card.where(user_id: current_user.id)
    #カード登録がまだならshowページへ飛ぶ
    redirect_to action: "show" if card.exists?
  end

  def pay #payjpとCardのデータベース作成
    Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
    if params['payjp-token'].blank?
       # paramsの中にjsで作った'payjpTokenが存在するか確かめる
      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}
        ) 
      @card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card)
      if @card.save
        redirect_to action: "show"
        flash[:notice] = 'クレジットカードの登録が完了しました'
      else
        redirect_to action: "pay"
        flash[:alert] = 'クレジットカード登録に失敗しました'
      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

カードの登録画面を作成

app/view/cards/new.html.haml
       .form-wapper
          = form_tag(pay_cards_path, method: :post, id: 'charge-form',  name: "inputForm") do
            .signup-content_text
              .form-group.form-group_text
                %label.form-group_label カード番号
                %span.essential 必須
              = text_field_tag "number", "", class: "number", placeholder: "半角数字のみ" ,maxlength: "16", type: "text", id: "card_number"
              .form-group.form-group_text.card_label
                %label.form-group_label 有効期限
                %span.essential 必須
            .form-group
              .form-flex#form-flex
                .birth-group
                  %select#exp_month{name: "exp_month", type: "text", class: "select-default"}
                    %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
                  %i.fa.fa-chevron-down
                %span.birth-group__month 
                .birth-group
                  %select#exp_year{name: "exp_year", type: "text", class: "select-default2"}
                    %option{value: ""} --
                    %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
                    %option{value: "2030"}30
                  %i.fa.fa-chevron-down.down
                %span.birth-group__year 
            .form-group.form-group_text.card_code
              %label.form-group_label セキュリティコード
              %span.essential3 必須
            = text_field_tag "cvc", "", class: "cvc", placeholder: "カード背面3~4桁の番号", maxlength: "4", id: "cvc"
            #card_token
            .form-group
            = submit_tag "追加する", id: "token_submit"

カード削除画面を作成

app/view/cards/show.html.haml
      .card-group
        .card-group__title
          %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(delete_cards_path, method: :post, id: 'charge-form',  name: "inputForm") do
            %input{ type: "hidden", name: "card_id", value: "" }
            %button.btn_delate  削除する

カード登録ができる確認

http://localhost:3000/card/new にアクセスして登録できるか確認してください
※このときテストカードを使用して登録をしてください!

登録.png

35d4e6735af7a0f631f97daacb7d5783.png

ができていれば成功です!!!

もし下記エラーが起きたら

400 Bad Request=不正なパラメーターなどのリクエストエラー
もしくは
Invalid email address provided=(無効なメールアドレスが提供されました)
と出た場合は
a@gmail.com / b@yahoo.co.jp で試してみたら解決します
アドレス a@a などのアドレスが無効と返されているみたいです 

2
4
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
2
4