0
0

More than 3 years have passed since last update.

[Rails]PAY.JPで登録したクレジットカードで商品購入機能を実装する

Last updated at Posted at 2020-05-25

はじめに

個人アプリにて、クレジットカード決済を行うため、PAY.JPを導入しました。
機能実装に関して、備忘録として記載しています。

前回の記事
PAY.JPでクレジットカードの登録・削除機能を実装する

前提条件

  • Rails 5.2.4.2
  • Ruby 2.5.1
  • devise使用
  • haml使用
  • VSCode使用

前回までにカード情報の登録を行うためCardモデル及びCardコントローラーを作成しました。
今回は新たに購入用モデル及びコントローラーを作成して購入処理を行っていきます。

手順

  1. モデルの作成
  2. テーブルの作成
  3. コントローラーの作成

モデルの作成

今回はOrderモデルを作成していきます。

class Order < ApplicationRecord
  belongs_to :user
  has_many :products, through: :order_details
  has_many :order_details, dependent: :destroy
  belongs_to :card
  belongs_to :address

  enum postage: {burden: 0, free: 1}
  enum status: {支払済み: 0, 配送準備中: 1, 配送済み: 2}

  def add_items(cart)
    cart.line_items.target.each do |item|
      item.cart_id = nil
      line_items << item
    end
  end
end

ECサイトを作成したので、カート機能などを実装している関係で、インスタンスメソッドなど定義しておりますが、今回は購入機能にフォーカスしているため、割愛します。
なので、belongs_to :cardの1行が使いたい部分になります。

テーブルの作成

マイグレーションファイルを以下のようにします。


class CreateOrders < ActiveRecord::Migration[5.2]
  def change
    create_table :orders do |t|
      t.references :user, foreign_key: true
      t.references :address, foreign_key: true
      t.references :card, foreign_key: true
      t.references :product, foreign_key: true
      t.integer :quantity, null: false
      t.integer :status, default: 0, null: false
      t.integer :postage, default: 0, null: false
      t.integer :price, null: false
      t.timestamps
    end
  end
end

cardを外部キーとして設置しています。

コントローラーの作成

Orderコントローラーを作成していきます。
今回はnewとcreateの2つのアクションを使用します。


class OrdersController < ApplicationController
  before_action :set_cart
  before_action :user_signed_in
  before_action :set_user
  before_action :set_card
  before_action :set_address

  require "payjp"

  #注文入力画面
  def new
    @line_items = current_cart.line_items
    @cart = current_cart
    if @cart.line_items.empty?
      redirect_to current_cart, notice: "カートは空です"
      return
    end
    if @card.present?
      customer = Payjp::Customer.retrieve(@card.customer_id)
      default_card_information = customer.cards.retrieve(@card.card_id)
      @card_info = customer.cards.retrieve(@card.card_id)
      @exp_month = default_card_information.exp_month.to_s
      @exp_year = default_card_information.exp_year.to_s.slice(2,3)
      customer_card = customer.cards.retrieve(@card.card_id)
      @card_brand = customer_card.brand
      case @card_brand
      when "Visa"
        @card_src = "icon_visa.png"
      when "JCB"
        @card_src = "icon_jcb.png"
      when "MasterCard"
        @card_src = "icon_mastercard.png"
      when "American Express"
        @card_src = "icon_amex.png"
      when "Diners Club"
        @card_src = "icon_diners.png"
      when "Discover"
        @card_src = "icon_discover.png"
      end
      @order = Order.new
    end
  end

  #注文の登録
  def create
    unless user_signed_in?
      redirect_to cart_path(@current_cart), notice: "ログインしてください"
      return
    end
    @purchaseByCard = Payjp::Charge.create(
    amount: @cart.total_price,
    customer: @card.customer_id,
    currency: 'jpy',
    card: params['payjpToken']
    )
    @order = Order.new(order_params)
    @order.add_items(current_cart)
    if @purchaseByCard.save && @order.save!
      OrderDetail.create_items(@order, @cart.line_items)
      flash[:notice] = '注文が完了しました。マイページにて注文履歴の確認ができます。'
      redirect_to root_path
    else
      flash[:alert] = "注文の登録ができませんでした"
      redirect_to action: :new
    end
  end

  private
  def order_params
    params.permit(:user_id, :address_id, :card_id, :quantity, :price)
  end

  def set_user
    @user = current_user
  end

  def set_cart
    @cart = current_cart
  end

  def set_card
    @card = Card.find_by(user_id: current_user.id)
  end

  def set_address
    @address = Address.find_by(user_id: current_user.id)
  end

  def user_signed_in
    unless user_signed_in?
      redirect_to cart_path(@cart.id), alert: "レジに進むにはログインが必要です"
    end
  end
end

newアクションにおいては、購入確認ページの形態をとっています。
ユーザーが登録していないと、そもそも購入確認ページに訪問できない仕様になっております。
かつ、ユーザーがマイページでカードを登録できるように仕様です。

購入確認ページで初めてカード登録を行う仕様にするのであれば、前回の記事で作成したCardコントローラーのnewアクションのインスタンス変数を持ってこればいいかもですね。

createアクションでは以下の内容が必要です。
見易いように内容抽出しております。


def create
  @purchaseByCard = Payjp::Charge.create(
  amount: @cart.total_price,
  customer: @card.customer_id,
  currency: 'jpy',
  card: params['payjpToken']
  )
  if @purchaseByCard.save
    flash[:notice] = '注文が完了しました。'
    redirect_to root_path
  else
    flash[:alert] = "注文の登録ができませんでした"
    redirect_to action: :new
  end
end

上記で購入が完了すると以下のようにPAY.JPにも売上が登録されています。
alt

0
0
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
0
0