MrTom_2020
@MrTom_2020 (と む)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

[ruby on rails] transactionとpayjpを使用してデータの一貫性を保ちたい。

transaction、payjp初心者です。
以下のようなアクションで
payjpで支払いをして
paymentsテーブルにsave!して
itemsテーブルにupdata!しています。

  def create
    ActiveRecord::Base.transaction do
      item = Item.find(params[:item_id])
      item.stock -= params[:quantity].to_i
      payment = Payment.new(payment_params)
      Payjp.api_key = ENV["PAYJP_SECRET_KEY"]
      charge = Payjp::Charge.create(
        amount: item.price.to_i * params[:quantity].to_i,
        customer: Card.find_by(user_id: current_user.id).customer_id,
        currency: 'jpy'
      )
      payment.charge_id = charge.id
      payment.save!
      item.update!(stock: item.stock)
      redirect_to root_path
    rescue
      @item = Item.find(params[:item_id])
      render "new"
    end
  end

間違っているかもしれませんが、この場合、ActiveRecord::Base.transaction do 〜 rescue 間の、一連の処理に問題がない場合のみDBに反映されるのでデータの一貫性が担保されるものと理解しております。

質問内容は
Payjp::Charge.createが問題なく処理され、その後、payment.save!、item.update!で問題が発生した場合、
・Payjp::Charge.createは取り消されるのか?
・取り消されない場合はどのようなコードを追記すべきか?
・Payjp::Charge.createで問題が発生した場合は、この記述でデータの一貫性が保たれると考えていますが、自分の考えに間違いはないか?

以上3点になります。
自身で様々なサイトを参考にして書き上げました。
問題点などありましたらご指摘いただきますと幸いです。
それでは宜しくお願いいたします。

0

1Answer

やっと出来ました。
要点を簡単に書くと、

payments_controller.rb
  def create
    begin
      charge = Payjp::Charge.create(
        amount:   "1000",
        customer: "cus_hogehogehoge*****",
        currency: "jpy",
      )#決済処理です。

      payment.save!
      @item.update!
      #Payjp::charge.create、payment.save!、@item.update!のいずれかで例外が発生したら下のrescueに飛びます。
    end
    redirect_to root_path#例外が発生しなかったらここが実行されます。

    rescue Payjp::PayjpError => e #Payjp::charge.createで例外が発生したらここ、以下2行が実行されます。
      @payjp_err = e
      render :new

    rescue => e #Payjp::charge.createで以外で例外が発生したらここ、以下が実行されます。
      if charge #もし決済していたら
        charge = Payjp::Charge.retrieve(charge.id)
        charge.refund #ここの2行で返金処理されます。
      end
      @err = e
      render :new
  end
0Like

Your answer might help someone💌