LoginSignup
4
3

More than 3 years have passed since last update.

[Rails][完全版]Payjpを使ったECサイト作成

Posted at

Payjpとは

シンプルなAPIでクレジットカード決済機能を導入出来る、クレジット決済代行サービスです。
ApplePayに対応していたり、cronを使わず定期課金を組み込むことができたりと便利です!

実装手順

1.Payjpに登録する。

2.登録後、画面左側にある、「API」をクリックします。テスト用、本番用の鍵が表示されますので本番用のキーを使用します。(テスト環境等ではテスト用を使いましょう)

3.Gemfileに以下を記述する。

Gemfile.
gem 'payjp'

忘れず実行する。

$ bundle install

4.Pay.jpの公式のjavascriptを読み込ませられるようする

application.html.haml
%script{src: "https://js.pay.jp/", type: "text/javascript"}

5.cardsテーブルを作成する

20××××××××××.rb
class CreateCards < ActiveRecord::Migration[5.2]
  def change
    create_table :cards do |t|
      t.references :user ,foreign_key: true, null: false  # ログインユーザー
      t.string :customer_id, null: false                  # 顧客ID情報(pay.jpから返ってくるデータ)
      t.string :card_id, null: false                      # カードID情報(pay.jpから返ってくるデータ)
      t.timestamps
    end
  end
end

忘れず実行する。

$ rails db:migrate

6.クレジットカード情報の追加と削除のコントローラを作成する

$ rails g controller cards

コントローラー内は以下を記述する。

app/controllers/cards_controller.rb

class CardController < ApplicationController

  before_action :get_user_params, only: [:edit, :confirmation, :show]
  before_action :get_payjp_info, only: [:new_create, :create, :delete, :show]

  def edit
  end

  def create
    if params['payjp-token'].blank?
      redirect_to action: "edit", id: current_user.id
    else
      customer = Payjp::Customer.create(
      email: current_user.email,
      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"
      else
        redirect_to action: "edit", id: current_user.id
      end
    end
  end

  def delete
    card = current_user.cards.first
    if card.present?
      customer = Payjp::Customer.retrieve(card.customer_id)
      customer.delete
      card.delete
    end
      redirect_to action: "confirmation", id: current_user.id
  end

  def show
    card = current_user.cards.first
    if card.present?
      customer = Payjp::Customer.retrieve(card.customer_id)
      @default_card_information = customer.cards.retrieve(card.card_id)
    else
      redirect_to action: "confirmation", id: current_user.id
    end
  end

  def confirmation
    card = current_user.cards
    redirect_to action: "show" if card.exists?
  end

  private

  def get_payjp_info
    if Rails.env == 'development'
      Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
    else
      Payjp.api_key = Rails.application.credentials.payjp[:PAYJP_PRIVATE_KEY]
    end
  end
end

7.クレジット情報の、確認と削除、追加のフォームを作成する

confirmation

クレジットカードを追加するか選択する画面

confirmation.html.haml

.main__content
    %section.chapter__container
      %h2.chapter__head 支払い方法
      .payment__main
        .payment__list
          .payment__list__content
            %h3.sub__head クレジットカード一覧
        .add__card
          .payment__list__content
            = link_to edit_card_path(current_user), class: "red__btn", data: {"turbolinks" => false} do
              %i
              = icon('fas', 'credit-card', class: "card__icon")
              クレジットカードを追加する
        .not__regist
          %span 支払い方法について

edit

クレジットカードの新規登録画面

edit.html.haml

  .main__content
    %section.chapter__container
      %h2.chapter__head クレジットカード情報入力
      = form_tag('/card', method: :post, action: "create", id: 'charge-form',  name: "inputForm", class: "chapter__container__inner") do
        .form__main__container
          .form__content
            %label.payment__card カード番号
            %span.require__form 必須
            = text_field_tag "number", "", class: "number input__deafult", placeholder: "半角数字のみ" ,maxlength: "16", type: "text", id: "card_number"
            .card__list
              .card__list__picture
          .form__content.top__margin
            %label.payment__card 有効期限
            %span.require__form 必須
            .select__box.top__margin
              .select__box__half
                %select.select__default#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
                %i
                  = icon('fas', 'chevron-down')
                %span.select__box__half
                .icon
                %select.select__default#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
                %i
                  = icon('fas', 'chevron-down')
                %span.form__content.top__margin
            %label セキュリティーコード
            %span.require__form 必須
            = text_field_tag "cvc", "", class: "cvc", placeholder: "カード背面4桁もしくは3桁の番号", maxlength: "4", id: "cvc"
            .single__code
              .single__code__text
              %span.form__question ? 
              %span カードの裏面の番号とは?
          #card_token
          = submit_tag "追加する", id: "token_submit", class: "top__margin"

show

DBのCard情報を、payjpに送りcustomer情報を取り出す

show.html.haml

 .main__content
    %section.chapter__container
      %h2.chapter__head 支払い方法
      .payment__main
        .payment__list
          .payment__list__content
            %h3.sub__head クレジットカード一覧
        .card__payment__list
          %form.card__payment__content
          .card__list
            .card__list__picture  
          .card__number 
            = "**** **** **** " + @default_card_information.last4
          .expire__date 
            - 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_credit_card_index_path, method: :post, id: 'charge-form',  name: "inputForm") do
            %input{ type: "hidden", name: "card_id", value: "" }
            %button.delete__button 削除する
        .how__not__regist
          %span 支払い方法について

8.payjpにデータを送るため、入力されたクレジット情報を参考にし、トークンを作成する

payjp.js

document.addEventListener(
  "DOMContentLoaded", e => {
    if (document.getElementById("token_submit") != null) { //token_submitというidがnullの場合、下記コードを実行しない
      Payjp.setPublicKey("ここに公開鍵を書く"); 
      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.最後にルーティングを設定する

routes.rb

  resources :_card, only: [:create, :show, :edit] do
    collection do
      post 'delete', to: 'card#delete'
      post 'show'
    end
    member do
      get 'confirmation'
    end
  end 
4
3
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
4
3