文系でもプログラマーになりたい!

文系プログラマー(になりたい人)のメモです。現在、プログラミングスクールで学習中。WEBエンジニアへの転職目指して活動中です!

【Ruby on Rails】Pay.jpでクレジットカード登録・削除機能を実装する

某プログラミングスクールで学習中の著者です。

Pay.jpでクレジットカード登録・削除機能を実装したので、

記録として残しておきます。

 

開発環境

Rails 5.2.4.2
ruby 2.5.1 

 

実装する機能

 Pay.jpでクレジットカード登録・削除機能

(登録画面も写真みたいに作ります。)

f:id:zoekun:20200519075431j:plain

 

実装手順

①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
    -# ↓これ
    %script{src: "https://js.pay.jp/"type: "text/javascript"}
    -# 
    = csrf_meta_tags
    = stylesheet_link_tag    'application'media: 'all'
    = javascript_include_tag 'application'

 

④カード情報を保存するテーブルを作成する。

マイグレーションファイルを作成し、以下のように記載。

その後、ターミナル で rails db:migrate を行います。

class CreateCards < ActiveRecord::Migration[5.2]
  def change
    create_table :cards do |t|
      t.integer :user_idforeign_key: truenull: false
      t.string :customer_idnull: false
      t.string :card_idnull: false
      t.timestamps
    end
  end
end

*ここに登録される customer_id、card_id を用いてPay.jpから顧客情報やカード情報を

 取得します。(カード情報そのものをDBに保存する訳ではありません)

⑤コントローラーの作成

今回は credit という名前で作成しました。

pay メソッドがカードの情報を保存する処理に相当します。

class CreditController < ApplicationController
  require "payjp"
  before_action :set_cardonly: [:index:delete:show]
  before_action :get_payjp_infoonly: [: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.idcustomer_id: customer.idcard_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で確認することができます。

(今回は、テスト秘密鍵を使いました)

 

⑥登録画面の作成

f:id:zoekun:20200519075431j:plain

写真のような、カード情報の登録画面を作ります。

(コード見辛くてすみません)

.mypage-content
  %section.purchace
    %h2.profile__top クレジットカード情報入力
    .content
      = form_with url: pay_credit_index_pathmethod: :posthtml: { name: "inputForm" } do |f|
        .content__inner
          .resister-credit
            = f.label :カード番号class: "resister-credit__number" 
            %span.resister-credit__need 必須
            = f.text_field :card_numbername: "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"
              %i.fas.fa-chevron-down
              %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"
              %i.fas.fa-chevron-down
              %span 年
          .resister-credit.margin
            = f.label :セキュリティーコードclass: "resister-credit__number" 
            %span.resister-credit__need 必須
            = f.text_field :cvcname: "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日悩み続けました)

javascriptにデータを送り、トークンを取得する。(jquery使用)

 

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, (statusresponse=> {
          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
);

 

⑧確認画面の作成

f:id:zoekun:20200519091613j:plain

こんな感じの、登録情報の確認画面を作ります。

カードの登録がない時は、コントローラーでカードの登録ボタンが表示されるようにしています。

 

.mypage-content
  %section.purchace
    %h2.profile__top 支払い情報
    .resister
      %h3.resister__title 登録クレジットカード情報
      .resister__form
        = form_with url: delete_credit_index_pathmethod: :postlocal: 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 :creditonly: [:new:index:showdo
    collection do
      post :pay
      post :delete
    end
  end

 

⑩テストカードで登録確認

最後はテストカード(Pay.jpで用意されているダミーのカード)で登録確認。

 

登録ができれば、成功です!

お疲れ様でした。

 

参考にさせていただいたサイト

https://qiita.com/takachan_coding/items/f7e70794b9ca03b559dd

https://pay.jp/