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
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.
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.
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.
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.
Recommended Posts