diff --git a/lib/stripe.rb b/lib/stripe.rb index 9c7c2647..9f524ec4 100644 --- a/lib/stripe.rb +++ b/lib/stripe.rb @@ -442,14 +442,26 @@ module Stripe include Stripe::APIOperations::Create end - class StripeError < StandardError; end + class StripeError < StandardError + attr_reader :message + attr_reader :http_status + attr_reader :http_body + attr_reader :json_body + + def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil) + @message = message + @http_status = http_status + @http_body = http_body + @json_body = json_body + end + end class APIError < StripeError; end class APIConnectionError < StripeError; end class CardError < StripeError attr_reader :param, :code - def initialize(message, param, code) - super(message) + def initialize(message, param, code, http_status=nil, http_body=nil, json_body=nil) + super(message, http_status, http_body, json_body) @param = param @code = code end @@ -457,8 +469,8 @@ module Stripe class InvalidRequestError < StripeError attr_accessor :param - def initialize(message, param) - super(message) + def initialize(message, param, http_status=nil, http_body=nil, json_body=nil) + super(message, http_status, http_body, json_body) @param = param end end @@ -568,7 +580,7 @@ module Stripe # some library out there that makes symbolize_names not work. resp = JSON.parse(rbody) rescue JSON::ParserError - raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})") + raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody) end resp = Util.symbolize_names(resp) @@ -585,27 +597,27 @@ module Stripe begin error_obj = JSON.parse(rbody) error_obj = Util.symbolize_names(error_obj) - error = error_obj[:error] or raise StripeError.new + error = error_obj[:error] or raise StripeError.new # escape from parsing rescue JSON::ParserError, StripeError - raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})") + raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody) end case rcode when 400, 404 then - raise invalid_request_error(error) + raise invalid_request_error(error, rcode, rbody, error_obj) when 401 - raise authentication_error(error) + raise authentication_error(error, rcode, rbody, error_obj) when 402 - raise card_error(error) + raise card_error(error, rcode, rbody, error_obj) else - raise api_error(error) + raise api_error(error, rcode, rbody, error_obj) end end - def self.invalid_request_error(error); InvalidRequestError.new(error[:message], error[:param]); end - def self.authentication_error(error); AuthenticationError.new(error[:message]); end - def self.card_error(error); CardError.new(error[:message], error[:param], error[:code]); end - def self.api_error(error); APIError.new(error[:message]); end + def self.invalid_request_error(error, rcode, rbody, error_obj); InvalidRequestError.new(error[:message], error[:param], rcode, rbody, error_obj); end + def self.authentication_error(error, rcode, rbody, error_obj); AuthenticationError.new(error[:message], rcode, rbody, error_obj); end + def self.card_error(error, rcode, rbody, error_obj); CardError.new(error[:message], error[:param], error[:code], rcode, rbody, error_obj); end + def self.api_error(error, rcode, rbody, error_obj); APIError.new(error[:message], rcode, rbody, error_obj); end def self.handle_restclient_error(e) case e diff --git a/test/test_stripe.rb b/test/test_stripe.rb index 05bd911c..0aae5151 100644 --- a/test/test_stripe.rb +++ b/test/test_stripe.rb @@ -73,13 +73,14 @@ class TestStripeRuby < Test::Unit::TestCase end should "not specifying api credentials should raise an exception" do + Stripe.api_key = nil assert_raises Stripe::AuthenticationError do Stripe::Customer.new("test_customer").refresh end end should "specifying invalid api credentials should raise an exception" do - Stripe.api_key="invalid" + Stripe.api_key = "invalid" response = test_response(test_invalid_api_key_error, 401) assert_raises Stripe::AuthenticationError do @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401)) @@ -87,6 +88,20 @@ class TestStripeRuby < Test::Unit::TestCase end end + should "AuthenticationErrors should have an http status, http body, and JSON body" do + Stripe.api_key = "invalid" + response = test_response(test_invalid_api_key_error, 401) + begin + @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401)) + Stripe::Customer.retrieve("failing_customer") + rescue Stripe::AuthenticationError => e + assert_equal(401, e.http_status) + assert_equal(true, !!e.http_body) + assert_equal(true, !!e.json_body[:error][:message]) + assert_equal(test_invalid_api_key_error['error']['message'], e.json_body[:error][:message]) + end + end + context "with valid credentials" do setup do Stripe.api_key="foo" @@ -96,6 +111,54 @@ class TestStripeRuby < Test::Unit::TestCase Stripe.api_key=nil end + should "a 400 should give an InvalidRequestError with http status, body, and JSON body" do + response = test_response(test_missing_id_error, 400) + @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404)) + begin + Stripe::Customer.retrieve("foo") + rescue Stripe::InvalidRequestError => e + assert_equal(400, e.http_status) + assert_equal(true, !!e.http_body) + assert_equal(true, e.json_body.kind_of?(Hash)) + end + end + + should "a 401 should give an AuthenticationError with http status, body, and JSON body" do + response = test_response(test_missing_id_error, 401) + @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404)) + begin + Stripe::Customer.retrieve("foo") + rescue Stripe::AuthenticationError => e + assert_equal(401, e.http_status) + assert_equal(true, !!e.http_body) + assert_equal(true, e.json_body.kind_of?(Hash)) + end + end + + should "a 402 should give a CardError with http status, body, and JSON body" do + response = test_response(test_missing_id_error, 402) + @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404)) + begin + Stripe::Customer.retrieve("foo") + rescue Stripe::CardError => e + assert_equal(402, e.http_status) + assert_equal(true, !!e.http_body) + assert_equal(true, e.json_body.kind_of?(Hash)) + end + end + + should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do + response = test_response(test_missing_id_error, 404) + @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404)) + begin + Stripe::Customer.retrieve("foo") + rescue Stripe::InvalidRequestError => e + assert_equal(404, e.http_status) + assert_equal(true, !!e.http_body) + assert_equal(true, e.json_body.kind_of?(Hash)) + end + end + should "setting a nil value for a param should exclude that param from the request" do @mock.expects(:get).with('https://api.stripe.com/v1/charges', { :offset => 5, :sad => false }, nil).returns(test_response({ :count => 1, :data => [test_charge] })) c = Stripe::Charge.all(:count => nil, :offset => 5, :sad => false)