[RUBY] [Rails] Implement the product purchase function with a credit card registered with PAY.JP

Introduction

We have introduced PAY.JP to make credit card payments with a personal app. Regarding the function implementation, it is described as a memorandum.

Previous article Implement credit card registration / deletion function in PAY.JP

Prerequisites

We have created a Card model and a Card controller to register card information up to the last time. This time, we will create a new purchase model and controller and perform the purchase process.

procedure

  1. Creating a model
  2. Create table
  3. Creating a controller

Creating a model

This time we will create an Order model.

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: {paid: 0,Preparing for delivery: 1,Delivered: 2}

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

Since I created an EC site, I have defined instance methods etc. because I have implemented cart functions etc., but this time I will omit it because I am focusing on the purchase function. So, one line of belongs_to: card is the part you want to use.

Creating a table

Make the migration file as follows.


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

The card is installed as a foreign key.

Creating a controller

We will create an Order controller. This time we will use two actions, new and create.


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"

  #Order entry screen
  def new
    @line_items = current_cart.line_items
    @cart = current_cart
    if @cart.line_items.empty?
      redirect_to current_cart, notice: "Cart is empty"
      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

  #Registering an order
  def create
    unless user_signed_in?
      redirect_to cart_path(@current_cart), notice: "Please login"
      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] = 'The order is complete. You can check the order history on My Page.'
      redirect_to root_path
    else
      flash[:alert] = "The order could not be registered"
      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: "You need to log in to proceed to the cashier"
    end
  end
end

The new action takes the form of a purchase confirmation page. If the user has not registered, the specifications are such that the purchase confirmation page cannot be visited in the first place. Moreover, it is a specification so that the user can register the card on My Page.

If you want to register the card for the first time on the purchase confirmation page, you may have the instance variable of the new action of the Card controller created in the previous article.

The create action requires the following: The contents are extracted for easy viewing.


def create
  @purchaseByCard = Payjp::Charge.create(
  amount: @cart.total_price,
  customer: @card.customer_id,
  currency: 'jpy',
  card: params['payjpToken']
  )
  if @purchaseByCard.save
    flash[:notice] = 'The order is complete.'
    redirect_to root_path
  else
    flash[:alert] = "The order could not be registered"
    redirect_to action: :new
  end
end

When the purchase is completed above, the sales are also registered in PAY.JP as shown below. alt

Recommended Posts

[Rails] Implement the product purchase function with a credit card registered with PAY.JP
[Rails] Implement credit card registration / deletion function in PAY.JP
Let's introduce the credit card function using payjp (preparation)
Let's roughly implement the image preview function with Rails + refile + jQuery.
I tried to implement the image preview function with Rails / jQuery
[Rails withdrawal] Create a simple withdrawal function with rails
Make a login function with Rails anyway
Implement the product category function using ancestry ① (Preparation)
Let's make a search function with Rails (ransack)
Implement the Like feature in Ajax with Rails.
Let's implement a function to limit the number of access to the API with SpringBoot + Redis
Using PAY.JP API with Rails ~ Card Registration ~ (payjp.js v2)
[Rails] Implement search function
I want to implement a product information editing function ~ part1 ~
A note about the seed function of Ruby on Rails
[Ruby on Rails] Implement login function by add_token_to_users with API
Implement login function simply with name and password in Rails (3)
A story about using the CoreImage framework to erase stains with Swift and implement a blur erase function
Implement application function in Rails
[Rails] Implement User search function
Introduced graph function with rails
Implement follow function in Rails
Rails ~ Understanding the message function ~
Login function implementation with rails
[Rails] Implement image posting function
Implement search function with form_with
The story of the first Rails app refactored with a self-made helper
[Rails] A simple way to implement a self-introduction function in your profile
Implement a refined search function for multiple models without Rails5 gem.
I want to add a browsing function with ruby on rails
I made a reply function for the Rails Tutorial extension (Part 1)
I got a warning message with the rails _6.0.3_ new hello_myapp command
I made a reply function for the Rails Tutorial extension (Part 5):
[Illustration] Finding the sum of coins with a recursive function [Ruby]
(Ruby on Rails6) Create a function to edit the posted content
I tried to make a group function (bulletin board) with Rails
[Rails] I will write the mechanism and method of using payjp (API) very carefully (Credit card registration)