payjpを使って購入機能を実装でい!!


こんにちは。
今日は雨ですね。
偏頭痛持ちの方は気をつけてください。

毎年傘を10本無くす私が言うのは全然説得力が無いと思うのですが、

傘は忘れない様に!!!

さぁ今回はpayjpを使って購入機能を実装するわよ。
(フリマアプリを作成中デスゥ)

payjp導入編もあるので見てない方は先にそちらをチェケラッ

payjp導入編
クレジットカード登録編
ビューなどの補足編

1 まずはルーティングを決めます。

この購入機能をどのコントローラーに入れるかですわねぇ。
色んな記事を読む限り

・商品コントローラーに入れる
・カードコントローラーに入れる
・購入コントローラーを新しく作る

アタイ的には商品テーブルに購入者、購入された時間のカラムを入れているので商品コントローラーの中に入れることにしました。

ですが既存のアクションじゃできないっ!!
なのでこんな感じでルーティングを作りましたわ。

routes.rb
resources :items, only: [:index, :new, :show, :create, :destroy] do
    member do
      get  'purchase'=>  'items#purchase', as: 'purchase'
      patch 'pay'=>   'items#pay', as: 'pay'
      get 'done'=>  'items#done', as: 'done'
    end

なぜmemberにしたかって言うと商品のidが欲しいから。
流れとしては

商品詳細ページ→商品購入ページ→購入アクション→購入完了しましたページ

2 次はコントローラージャイ

商品詳細はいらんからmemberで定義したアクションのみ書いていくわよ!!

items_controller.rb
def purchase
    @item = Item.find(params[:id])
    @card = Card.find_by(user_id: current_user.id)
    if @card == nil
      redirect_to new_card_path
      flash[:noCard] = "Cardが登録されていませんので登録してください"
    else
      Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_PRIVATE_KEY]
      customer = Payjp::Customer.retrieve(@card.customer_id)
      @card_information = customer.cards.retrieve(@card.card_id)
      # 購入確認ページでカード情報出したいからここで取得。
      # 画像無い人はなくても良いかも。
      @card_brand = @card_information.brand      
      case @card_brand
      when "Visa"
        @card_src = "if-visa-2593666_86609.svg"
      when "JCB"
        @card_src = "jcbcard.png"
      when "MasterCard"
        @card_src = "mastercard.png"
      when "American Express"
        @card_src = "americancard.png"
      when "Diners Club"
        @card_src = "diners_club.png"
      when "Discover"
        @card_src = "discover.png"
      end
      # ---------------------------------------------------------------
    end
  end

  def pay
    @item = Item.find(params[:id])
    card = Card.find_by(user_id: current_user.id)
    Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_PRIVATE_KEY]
    Payjp::Charge.create(
      amount: @item.price, # Payjpに載る金額
      customer: card.customer_id, # 顧客ID
      currency: 'jpy'
    )
    @item.update(buyer: current_user.id)
    require 'date'
    @item.update(bought_at: Time.now )
  # アタイは購入時間を入れているからここもいらん人はなくてよし
    redirect_to done_item_path(@item.id)
    flash[:notice] = "購入が完了しました"
  end

  def done
  end

こんな感じだわよ。

3 一応ビューファイルも

purchase.html.haml
.purchaseBackground
  = render 'layouts/global-header-simple'

  %main.purchaseMain
    %h2.purchaseMain__content.purchaseTitle 購入内容の確認
    = form_with model: @item, local: true do |f|
      .purchaseMain__content.purchaseItem
        .purchaseItem__imageArea
          = image_tag asset_path('curry.png'), class: 'purchaseItem__imageArea--image', alt: '購入アイテム画像'
        .purchaseItem__box
          %p 
            = @item.name
          .purchaseItem__box--price
            %span 
              = @item.price%span.shipping-fee (税込) 送料込み
      %section.purchaseMain__content
        .purchaseMain__content__wrapper
          .purchaseMain__content__wrapper__price
            .purchaseMain__content__wrapper__price--label 支払い金額
            .purchaseMain__content__wrapper__price--value 
              = @item.price.purchaseMain__content__wrapper
          .purchaseMain__content__wrapper__payMethod
            .purchaseMain__content__wrapper__payMethod--label 支払い方法
            = link_to card_path(@card.id), class: 'changeBtn' do
              変更する
          %p.user-card-info
            クレジットカード
            = "**** **** **** " + @card_information.last4 
          %p.user-card-info
            有効期限
            - exp_month = @card_information.exp_month.to_s
            - exp_year = @card_information.exp_year.to_s.slice(2,3)
            = exp_month + " / " + exp_year
          %figure.user-card-logo
            = image_tag "#{@card_src}",width:'34',height:'20', alt:'master-card'
        .purchaseMain__content__wrapper
          .purchaseMain__content__wrapper__delivery
            .purchaseMain__content__wrapper__delivery--label 配送先
            = link_to '#', class: 'changeBtn' do
              変更する
          %p.user-address-info
        .purchaseMain__content__wrapper
          %p.purchase-info
            郵便局/コンビニ受取をご希望の方は、購入後に<strong>取引画面</strong>から受取場所を変更をすることが可能です。出品者が発送作業を開始した後は受取場所の変更ができませんので、早めに変更を行ってください。
          .btn-enter
            = link_to pay_item_path(@item.id), method: :patch do
              .purchase-btn
                購入する

  = render 'layouts/global-footer-simple'

写真はこんな感じだわよ

これでフリマアプリで買い放題だZE!!!

クレジット機能に関してはこんなもんですかね。