我使用带有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
任何人都可以伸出援助之手吗?
非常感谢
答案 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%>