0

私はレールを初めて使用し、アクティブなマーチャントを初めて使用します。次のコードがアクティブなマーチャントを使用した支払い処理に十分かどうかを知りたいだけです。

ご覧のとおり、購入方法の代わりにオーソライズ アンド キャプチャを使用しています。私の主な懸念は、コード内の「brought_quantity」の減算です(支払い処理が失敗した場合の対応部分です)。競合状態または支払いゲートウェイからのエラーが発生した場合の対処方法がよくわかりません。

変数 transactions はモデル/テーブルのインスタンス変数であり、支払いゲートウェイの応答情報を保存することに注意してください。

def purchase(item)
  price = price_in_cents(item.value)
  if !item.can_purchase
    errors[:base] << "We are sorry, all items are sold out at the moment."
    return false
  else
    response = GATEWAY.authorize(price, credit_card, purchase_options)
    transactions.create!(:action => "authorize", :value => price, :params => response)
    #p response
    if response.success?
      item.brought_quantity = item.brought_quantity + 1
      if item.save!
        response = GATEWAY.capture(price, response.authorization)
        transactions.create!(:action => "capture", :value => price, :params => response)
        if !response.success?
          errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com with this error id: 111"
          @rd = RunningDeal.find_by_id(@item.id)
          @rd.brought_quantity = @rd.brought_quantity - 1
          @rd.save!
          return false
        end
      else
        errors[:base] << "We are sorry, all items are sold out at the moment."
        return false
      end
    else
      # problem process their payment, put out error
      errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com with this error id: 111"
      return false
    end
  end
  return true
end

編集 OK、いくつかのリファクタリングを行いました。これが更新されたコードです。コメントや提案は大歓迎です。を削除しました ! これは、例外を発生させるほど重要な操作ではないためです。

フィードバックに基づいて更新されたコードを次に示します。

#from running_deal.rb
def decrement_deal_quantity
  self.brought_quantity = self.brought_quantity + 1
  return self.save!
end


def purchase(running_deal)
  price = price_in_cents(running_deal.value)
  if !running_deal.can_purchase
    errors[:base] << "We are sorry, all items are sold out at the moment."
    return false
  else
    auth_resp = GATEWAY.authorize(price, credit_card, purchase_options)
    transactions.create(:action => "authorize", :value => price, :success => auth_resp.success?, :message => auth_resp.message, :authorization => auth_resp.authorization, :params => auth_resp)
    if auth_resp.success?
      begin
        running_deal.decrement_deal_quantity
        cap_resp = GATEWAY.capture(price, auth_resp.authorization)
        transactions.create(:action => "capture", :value => price, :success => cap_resp.success?, :message => cap_resp.message, :authorization => cap_resp.authorization, :params => cap_resp)
      rescue
        GATEWAY.void(auth_resp.authorization, purchase_options) if auth_resp.success?
        errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com"
        return false
      end
    else
      # problem process their payment, put out error
      errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com"
      return false
    end
  end
  return true

終わり

4

1 に答える 1

3

トランザクションの処理はトリッキーです。

いくつかの考え:

  • 承認が成功すると、99.9% のケースでキャプチャが成功します。今回の件は特に気にする必要はありません。
  • authorize() が成功した後にコードで何かが失敗した場合 (データベースへの例外書き込みなど)、ゲートウェイに void() を呼び出して、承認を削除します。それ以外の場合、資金は 7 日間凍結されます。
  • このコードは、モデル メソッドに移動する必要があります。

      @rd = RunningDeal.find_by_id(@item.id)
      @rd.brought_quantity = @rd.brought_quantity - 1
      @rd.save!
    
  • create() ではなく create!() を呼び出しているため (保存すると true を返す)、例外をキャッチするためにメソッドの最後に句を追加する必要があります。

    rescue Exception => e # エラー処理終了

  • item.save の理由は不明です。エラーメッセージがアイテムが売り切れであることを示していませんか? それはまったくあいまいです。

全体として、次のようなことをしたい:

  • 十分な在庫があるかどうかを確認する
  • AUTH を実行する
  • データベーストランザクションを開始
  • すべてのデータベース オブジェクトを保存/更新する
  • トランザクションをコミットする
  • CAPTUREを実行する
  • 例外をキャッチし、AUTH が成功した場合 - VOID を実行します

お役に立てれば。

于 2011-05-19T20:18:47.983 に答える