如何在视图中显示支付网关响应消息 - Rails 4,Active Merchant

时间:2014-05-09 14:14:10

标签: ruby ruby-on-rails-4 stripe-payments activemerchant

我使用带有Stripe的Active Merchant作为支付网关。一切正常,但我不知道如何从Stripe获取网关响应错误消息(当卡被拒绝,无效等)以在结账页面上显示给用户。我可以引发一个StandardError,重定向到带有响应消息的错误页面,但是就是这样。

订购模式

class Order < ActiveRecord::Base

has_many :order_products
has_many :products, through: :order_products

attr_accessor :card_number, :security_code, :card_expires_on

validate :validate_card, :on => :create

    def validate_card
    unless credit_card.valid? 
      credit_card.errors.full_messages.each do |message|
       errors[:base] << message

      end

   end
end

def purchase(basket)

    response = GATEWAY.purchase(Product.total_basket_price(basket)*100, credit_card, purchase_options)
        unless response.success? 
         raise StandardError, response.message



    end
end



def credit_card

    @credit_card ||= ActiveMerchant::Billing::CreditCard.new(
        :number                 => card_number,
        :first_name             => first_name,
        :last_name              => last_name,
        :verification_value     => security_code,
        :month                  => card_expires_on.month,
        :year                   => card_expires_on.year
        )
end

def purchase_options 
{
    :billing_address => {
        :address1 => address_1,
        :address2 => address_2,
        :city     => city,
        :country  => country_code,
        :zip      => postal_code 
        }
}

end


end

ORDERS CONTROLLER

class OrdersController < ApplicationController

def create



    @order = Order.new(order_params)

    # @product = basket.find(params[:product_id])


    basket.each do |item_id|
        @order.order_products.build(product: Product.find(item_id))
    end

    if @order.save
        if @order.purchase(basket)

            render "show"
        else
            render "failure"
        end
    else
        render "new"


    end
end

任何人都可以伸出援助之手吗?

非常感谢

2 个答案:

答案 0 :(得分:0)

轻松自在!

这是控制流程的简单问题。在Ruby中,与大多数语言一样,异常会中断正常的程序流程。由于您的代码现在已经编写,#purchase在失败时会引发异常。

这很好,是一个完全有效的设计决定。但与#purchase交互的代码是这样的:

if @order.purchase(basket)
    render "show"
else
    render "failure"
end

该代码没有异常处理,因此任何异常都将被Rails捕获,程序流将停止,并且您将获得详细的错误页面(在开发模式下)或通用的500错误页面(在生产中)模式)。

由于你自称是Ruby和Rails的新手,一点代码替换可能会使这一点更加清晰:

# If #purchase is successful, it evaluates to true.
if true
  render "show"       # 'show' view is rendered as expected. Flow stops.
else
  render "failure"
end

# If #purchase fails, it raises an exception.
if raise StandardError, response.message
  # ^^^ Exception is raised, flow stops here.
  render "show"       # This code is never reached.
else                  # This code is never reached.
  render "failure"    # This code is never reached.
end

正如我在开始时暗示的那样,一旦你知道问题是什么,它就很容易解决。您只需使用rescue处理异常即可。如果您当前有if / else块,则可以交换if块和救援块:

if @order.purchase(basket)
  render 'show'
end
rescue => e
  render 'failure'

根据您的需求,这里还有改进空间 - 例如,您提升并抢救StandardError,您无法轻易区分网络故障和被拒绝卡 - 但它会让你再次移动。

答案 1 :(得分:0)

经过大量的提示和帮助之后,工作解决方案是在响应参数哈希中搜索error密钥,如果存在错误,则将消息添加到对象错误中。不是特别优雅,但它现在做我想要的。

订购模式

def purchase(basket)

    response = GATEWAY.purchase(Product.total_basket_price(basket)*100, credit_card, purchase_options)

        if response.params.key?('error')

            self.errors.add :base, response.message

            false

        else 
            true

        end 

end

ORDERS CONTROLLER

还切换控制器中if语句的顺序,以便在保存订单之前先运行def purchase(basket),从而允许捕获并显示响应中的错误消息。 / p>

if @order.purchase(basket)
        if @order.save

            render "show"   
        else 

            render "new"


        end
    else
        render "new"


    end

查看

<%= if @order.errors.any?
           @order.errors[:base].to_sentence

end%>
相关问题