##概要
Pay.jpを用いた購入機能の実装を備忘録としてまとめます。
修正点ありましたらご指摘お願いいたします。
Transaction(取り引き)テーブルおよびProduct(商品)テーブルをもとに作っていきます。
##前提
- Pay.jpのアカウント作成済み
- Pay.jpにてクレジットカード登録機能は実装済み
- ビューはHamlで記載
- deviseにてログイン済み
##手順
- Transactionテーブルを作成(購入済みの場合SOLD OUTを表示させるため)
- アソシエーションの設定
- Transactionコントローラーを作成
- 環境変数の設定
- ルーティングの設定
- マークアップ:購入内容確認画面
- マークアップ:購入完了画面
- マークアップ:購入済みの場合SOLD OUTを表示
- 購入データの確認
##Transactionテーブルを作成
今回は購入済みの場合SOLD OUTを表示させるためにTransactionテーブルを作成します。
$ rails g model Transaction
class CreateTransactions < ActiveRecord::Migration[5.2]
def change
create_table :transactions do |t|
t.references :product, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
マイグレートを実行
$ rails db:migrate
##アソシエーションの設定
class Transaction < ApplicationRecord
belongs_to :user, optional: true
belongs_to :product, optional: true
end
##Transactionコントローラーを作成
$ rails g controller transactions
class TransactionsController < ApplicationController
require 'payjp'
before_action :set_card, only: [:pay_index, :pay]
before_action :set_product
def pay_index
@top_image = @product.images.first
@card = @set_card.first
if @card.blank?
redirect_to controller: "cards", action: "new"
else
Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"]
customer = Payjp::Customer.retrieve(@card.customer_id)
@default_card_information = customer.cards.retrieve(@card.card_id)
end
end
def pay
@card = @set_card.first
Payjp.api_key = ENV['PAYJP_PRIVATE_KEY']
Payjp::Charge.create(
:amount => @product.price,
:customer => @card.customer_id,
:currency => 'jpy',
)
redirect_to action: 'done', product_id: @product
end
def done
@top_image = @product.images.first
Transaction.create(product_id: @product.id, user_id: current_user.id)
end
private
def set_card
@set_card = Card.where(user_id: current_user.id)
end
def set_product
@product = Product.find(params[:product_id])
end
end
##環境変数の設定
コントローラ内のENV["PAYJP_PRIVATE_KEY"]は環境変数でテスト秘密鍵を設定し読み込む。
今回はdotenvとgonを利用する。
dotenv:Railsの環境変数管理
gon:JSにてRailsで定義した環境変数を使用
参考:https://qiita.com/3443/items/44202ff6504210592570#comments
※gonはCard登録機能にて使用したため今回は関係ありません
##ルーティングの設定
Rails.application.routes.draw do
devise_for :users
root "products#index"
resources :users, only: [:edit, :update]
resources :products
resources :cards, only: [:new, :show, :destroy] do
collection do
post 'pay_show', to: 'cards#pay_show'
post 'pay', to: 'cards#pay'
end
end
##今回の該当箇所
resources :transactions, only: [:index] do
collection do
get 'pay_index', to: 'transactions#pay_index'
post 'pay', to: 'transactions#pay'
get 'done', to: 'transactions#done'
end
end
end
##マークアップ:購入内容確認画面
.transaction-pay
.transaction-pay__content
%h2.transaction-pay__title 購入内容の確認
.transaction-pay__item
.transaction-pay__item-box
= image_tag @top_image.image.url, alt:"商品画像", class: "transaction-pay__item-image"
.transaction-pay__item-detail
%p.transaction-pay__item-detail--name
= @product.name
.transaction-pay__item-detail-price
.transaction-pay__item-detail-price--text
¥
.transaction-pay__item-detail-price--text
= @product.price
.transaction-pay__item-detail-price--shipping (税込)送料込み
.transaction-pay__table
.transaction-pay__table-inner
.transaction-pay__table-form
.transaction-pay__table-content
.transaction-pay__table-pay
%p.transaction-pay__table-pay--title 支払い金額
.transaction-pay__table-price
%p.transaction-pay__table-price--title
¥
%p.transaction-pay__table-price--title
= @product.price
.transaction-pay__table-way
%h3 支払い方法
.transaction-pay__table-register
- if @default_card_information.blank?
%i.fas.fa-plus-circle
%span.icon-register
= link_to "登録してください", new_card_path
- else
= "**** **** **** " + @default_card_information.last4
- 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
.transaction-pay__table-buy
= form_tag(action: :pay, method: :post, product_id: @product) do
%button.transaction-pay__table-buy-button 購入する
##マークアップ:購入完了画面
.transaction-done
.transaction-done__content
.transaction-done__text
購入が完了しました!
.transaction-done__image
= image_tag @top_image.image.url, alt:"商品画像", class: "transaction-done__image--img"
.transaction-done__title
= @product.name
.transaction-done__price
.transaction-done__price--text
= @product.price
.transaction-done__price--info
(送料込み)
##マークアップ:購入済みの場合SOLD OUTを表示
.product-show
.product-show__main
.product-show__content
.product-show__top-content
.product-show__item-box
.product-show__item-box--name
= @product.name
.product-show__item-box__body
.product-show__item-box__body--top-img
= image_tag @top_image.image.url, alt:"トップ画像", class: "product-show__item-top-img"
.product-show__item-box__body--list
- @images.each do |image|
.product-show__item-box__body--sub-img
= image_tag image.image.url, alt:"サブ画像", class: "product-show__item-sub-img"
.product-show__item-box--price
%span
= "#{@product.price}円"
.product-show__item-box--price-detail
%span.product-show__item-box--price-detail-text
(税込)
%span.product-show__item-box--price-detail-text
= @product.delivery_charge
.product-show__item-box--item-detail
= @product.name
-# 商品出品者であれば表示させない
- if user_signed_in? && (current_user.id == @product.user_id)
- else
.product-show__transaction
.product-show__transaction-box
-# 商品購入済みであればSOLD OUT
- if @product_id.present?
.product-transaction-btn
SOLD OUT
- else
= link_to "購入画面に進む", pay_index_transactions_path(product_id: @product), class: "product-transaction-btn"
##購入データの確認
購入ができていれば下記のURLにて履歴が確認できます。
https://pay.jp/d/charges
##以上です