学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails

Ruby on Rails6.0 | 空き部屋を登録・予約・決済できるWebサイトを作成する 43 | クレジットカード決済の実装

[42]クレジットカード決済 | Stripe(ストライプ)コネクト<< [ホームに戻る] >> [44]ページネーション


「app\controllers\reservations_controller.rb」ファイルの記述を更新します。


1.5行目の「create()」メソッドの記述を以下のように更新します。

    def create
      room = Room.find(params[:room_id])
  
      if current_user == room.user
        flash[:alert] = "オーナーが予約することはできません。"
      elsif current_user.stripe_id.blank?
        flash[:alert] = "予約する前にクレジットカードを登録する必要があります。"
        return redirect_to settings_payment_path
      else
  
          start_date = Date.parse(reservation_params[:start_date])
          end_date = Date.parse(reservation_params[:end_date])
          days = (end_date - start_date).to_i
        if days == 0
          flash[:alert] = "宿泊日数が1泊以上でなければ予約することはできません。"
        else
          @reservation = current_user.reservations.build(reservation_params)
          @reservation.room = room
          @reservation.price = room.price
          @reservation.total = room.price * days
          #@reservation.save
  
          if @reservation.Waiting!
            if room.Request?
              flash[:notice] = "予約承認申請を送信しました。予約が承認されるまでしばらくお待ち下さい。"
            else
              charge(room, @reservation)
            end
          else
            flash[:alert] = "ご予約できません!"
          end
        end
      end
      redirect_to room
    end



2.68行目に「charge()」メソッドを追加します。

    def charge(room, reservation)
      host_amount = (reservation.total * 0.8).to_i # 売上の80%がホストに入る
      if !reservation.user.stripe_id.blank?
        customer = Stripe::Customer.retrieve(reservation.user.stripe_id)
        charge = Stripe::Charge.create(
          :customer => customer.id,
          :amount => reservation.total,
          :description => room.listing_name,
          :currency => "jpy",
          transfer_data: {
            amount: host_amount, 
            destination: room.user.merchant_id, # ホストのストライプID
          },
        )
  
        if charge
          reservation.Approved!
          flash[:notice] = "お支払い手続きが完了し、ご予約されました。お越しをお待ちしております!"
        else
          reservation.Declined!
          flash[:notice] = "お支払い手続きができません。予約ができませんでした。"
        end
      end
    rescue Stripe::CardError => e
      reservation.declined!
      flash[:alert] = e.message
    end



app\controllers\reservations_controller.rb

class ReservationsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_reservation, only: [:approve, :decline]

  def create
    room = Room.find(params[:room_id])

    if current_user == room.user
      flash[:alert] = "オーナーが予約することはできません。"
    elsif current_user.stripe_id.blank?
      flash[:alert] = "予約する前にクレジットカードを登録する必要があります。"
      return redirect_to settings_payment_path
    else

        start_date = Date.parse(reservation_params[:start_date])
        end_date = Date.parse(reservation_params[:end_date])
        days = (end_date - start_date).to_i
      if days == 0
        flash[:alert] = "宿泊日数が1泊以上でなければ予約することはできません。"
      else
        @reservation = current_user.reservations.build(reservation_params)
        @reservation.room = room
        @reservation.price = room.price
        @reservation.total = room.price * days
        #@reservation.save

        if @reservation.Waiting!
          if room.Request?
            flash[:notice] = "予約承認申請を送信しました。予約が承認されるまでしばらくお待ち下さい。"
          else
            charge(room, @reservation)
          end
        else
          flash[:alert] = "ご予約できません!"
        end
      end
    end
    redirect_to room
  end

  def your_trips
    @trips = current_user.reservations.order(start_date: :asc)
  end

  def your_reservations
    @rooms = current_user.rooms
  end

  def approve
    @reservation.Approved!
    redirect_to your_reservations_path
  end

  def decline
    @reservation.Declined!
    redirect_to your_reservations_path
  end

  private
  def reservation_params
    params.require(:reservation).permit(:start_date, :end_date)
  end

  def set_reservation
    @reservation = Reservation.find(params[:id])
  end

  def charge(room, reservation)
    host_amount = (reservation.total * 0.8).to_i # 売上の80%がホストに入る
    if !reservation.user.stripe_id.blank?
      customer = Stripe::Customer.retrieve(reservation.user.stripe_id)
      charge = Stripe::Charge.create(
        :customer => customer.id,
        :amount => reservation.total,
        :description => room.listing_name,
        :currency => "jpy",
        transfer_data: {
          amount: host_amount, 
          destination: room.user.merchant_id, # ホストのストライプID
        },
      )

      if charge
        reservation.Approved!
        flash[:notice] = "お支払い手続きが完了し、ご予約されました。お越しをお待ちしております!"
      else
        reservation.Declined!
        flash[:notice] = "お支払い手続きができません。予約ができませんでした。"
      end
    end
  rescue Stripe::CardError => e
    reservation.declined!
    flash[:alert] = e.message
  end


end
  



ブラウザ確認
http://localhost:3000/


クレジットカードを登録しないと予約ができないようになっています。

先にクレジットカード登録
先にクレジットカード登録



予約すると登録したクレジットカードで決済されます。

決済完了
決済完了



ストライプでテスト決済が確認できます。
ストライプのダッシュボードページで「payments」を選択し、テスト決済を確認します。

決済確認
決済確認

支払いの詳細をみると売上の80%が送金されるようになっています。

売上の80%を送金
売上の80%を送金



振込先の登録をしないとお部屋の登録ができないようにします。


記述追加 app\controllers\rooms_controller.rb(18行目)

    if !current_user.is_active_host
      return redirect_to settings_payout_path, alert: "振込口座の登録を先に行ってください。"
    end    



app\controllers\rooms_controller.rb

class RoomsController < ApplicationController

  protect_from_forgery except: [:upload_photo]
  before_action :set_room, except: [:index, :new, :create]
  before_action :authenticate_user!, except: [:show]
  before_action :is_authorised, only: [:listing, :pricing, :description, :photo_upload, :amenities, :location, :update]

  def index
     @rooms = current_user.rooms
  end

  def new
    @room = current_user.rooms.build
  end

  def create

    if !current_user.is_active_host
      return redirect_to settings_payout_path, alert: "振込口座の登録を先に行ってください。"
    end    

    @room = current_user.rooms.build(room_params)
    if @room.save
      redirect_to listing_room_path(@room), notice: "保存しました。"
    else
      flash[:alert] = "問題が発生しました。"
      render :new
    end
  end

  def show
    @photos = @room.photos
    @guest_reviews = @room.guest_reviews
  end

  def listing
  end

  def pricing
  end

  def description
  end

  def photo_upload
  end

  def amenities
  end

  def location
  end

  def update
    new_params = room_params
    new_params = room_params.merge(active: true) if is_ready_room

    if @room.update(new_params)
      flash[:notice] = "保存しました。"
    else
      flash[:alert] = "問題が発生しました。"
    end
    redirect_back(fallback_location: request.referer)
  end

  def upload_photo
    @room.photos.attach(params[:file])
    render json: { success: true }
  end

  def delete_photo
    @image = ActiveStorage::Attachment.find(params[:photo_id])
    @image.purge
    redirect_to photo_upload_room_path(@room)
  end

  # 予約 開始日のAJAX
  def preload
    today = Date.today
    reservations = @room.reservations.where("(start_date >= ? OR end_date >= ?) AND status = ?", today, today, 1)
    render json: reservations
  end
  # 予約 終了日のAJAX
  def preview
    start_date = Date.parse(params[:start_date])
    end_date = Date.parse(params[:end_date])
    output = {
      conflict: is_conflict(start_date, end_date, @room)
    }
    render json: output
  end

  private

    def set_room
      @room = Room.find(params[:id])
    end
    
    def room_params
      params.require(:room).permit(:home_type, :room_type, :accommodate, :bed_room, :bath_room, :listing_name, :summary, :address, :is_tv, :is_kitchen, :is_air, :is_heating, :is_internet, :price, :active, :description, :instant)
    end

    def is_authorised
      redirect_to root_path, alert: "権限がありません。" unless current_user.id == @room.user_id
    end

    def is_ready_room
      !@room.active && !@room.price.blank? && !@room.listing_name.blank? && !@room.photos.blank? && !@room.address.blank?
    end

    # 予約 プライベートメソッド
    def is_conflict(start_date, end_date, room)
      check = room.reservations.where("(? < start_date AND end_date < ?) AND status = ?", start_date, end_date, 1)
      check.size > 0? true : false
    end

  end



ブラウザ確認
http://localhost:3000/rooms/new

先に振込口座登録
先に振込口座登録



[42]クレジットカード決済 | Stripe(ストライプ)コネクト<< [ホームに戻る] >> [44]ページネーション