Permalink
Browse files

Refactor Samurai gateway

  • Loading branch information...
1 parent 66bd06e commit 76f6242fba3ab9861875c0dc3190f125124de1eb Denis Odorcic committed Nov 9, 2011
View
@@ -255,3 +255,7 @@ CardSave (August, 2011)
Dwolla (September, 2011)
* James Armstead (armsteadj1)
+
+Samurai (November, 2011)
+
+* Joshua Krall (jkrall)
View
@@ -6,7 +6,7 @@ group :test do
gem 'jruby-openssl', :platforms => :jruby
# gateway-specific dependencies, keeping these gems out of the gemspec
- gem 'samurai', '>= 0.2.24'
+ gem 'samurai', '>= 0.2.25'
end
group :remote_test do
@@ -15,6 +15,6 @@ group :remote_test do
gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
# gateway-specific dependencies, keeping these gems out of the gemspec
- gem 'samurai', '>= 0.2.24'
+ gem 'samurai', '>= 0.2.25'
end
@@ -7,113 +7,114 @@ class SamuraiGateway < Gateway
self.supported_countries = ['US']
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
self.default_currency = 'USD'
- self.money_format = :cents
+ self.money_format = :dollars
def initialize(options = {})
begin
require 'samurai'
rescue LoadError
- raise "Could not load the samurai gem (>= 0.2.24). Use `gem install samurai` to install it."
+ raise "Could not load the samurai gem (>= 0.2.25). Use `gem install samurai` to install it."
end
- requires!(options, :merchant_key, :merchant_password, :processor_token)
- @sandbox = options[:sandbox] || false
+ requires!(options, :login, :password, :processor_token)
+ @options = options
Samurai.options = {
- :merchant_key => options[:merchant_key],
- :merchant_password => options[:merchant_password],
- :processor_token => options[:processor_token]
+ :merchant_key => options[:login],
+ :merchant_password => options[:password],
+ :processor_token => options[:processor_token]
}
end
+ def test?
+ @options[:test] || super
+ end
+
+ def authorize(money, credit_card_or_vault_id, options = {})
+ token = payment_method_token(credit_card_or_vault_id, options)
+ return token if token.is_a?(Response)
+
+ authorize = Samurai::Processor.authorize(token, amount(money), processor_options(options))
+ handle_result(authorize)
+ end
+
def purchase(money, credit_card_or_vault_id, options = {})
- if credit_card_or_vault_id.is_a?(ActiveMerchant::Billing::CreditCard)
- store_result = store(credit_card_or_vault_id, options)
- return store_result if !store_result.success?
- credit_card_or_vault_id = store_result.params["payment_method_token"]
- end
- result = Samurai::Processor.purchase(credit_card_or_vault_id,
- money,
- {
- :billing_reference => options[:billing_reference],
- :customer_reference => options[:customer_reference],
- :custom => options[:custom],
- :descriptor => options[:descriptor],
- })
- handle_result(result)
+ token = payment_method_token(credit_card_or_vault_id, options)
+ return token if token.is_a?(Response)
+
+ purchase = Samurai::Processor.purchase(token, amount(money), processor_options(options))
+ handle_result(purchase)
end
def capture(money, authorization_id, options = {})
- authorization = Samurai::Transaction.find(authorization_id) # get the authorization created previously
- capture = money.nil? ? authorization.capture : authorization.capture(money)
- handle_result(capture)
+ transaction = Samurai::Transaction.find(authorization_id)
+ handle_result(transaction.capture(amount(money)))
end
- def credit(money, transaction_id, options = {})
- transaction = Samurai::Transaction.find(transaction_id) # get the transaction
- credit = money.nil? ? transaction.credit : transaction.credit(money)
- handle_result(credit)
+ def refund(money, transaction_id, options = {})
+ transaction = Samurai::Transaction.find(transaction_id)
+ handle_result(transaction.credit(amount(money)))
end
- def authorize(money, credit_card_or_vault_id, options = {})
- if credit_card_or_vault_id.is_a?(ActiveMerchant::Billing::CreditCard)
- store_result = store(credit_card_or_vault_id, options)
- return store_result if !store_result.success?
- credit_card_or_vault_id = store_result.params["payment_method_token"]
- end
- authorize = Samurai::Processor.authorize(credit_card_or_vault_id, money, {:billing_reference => options[:billing_reference],:customer_reference => options[:customer_reference],:custom => options[:custom],:descriptor => options[:descriptor]})
- handle_result(authorize)
+ def void(transaction_id, options = {})
+ transaction = Samurai::Transaction.find(transaction_id)
+ handle_result(transaction.void)
end
- def void(money, transaction_id, options = {})
- void = Samurai::Processor.void(transaction_id, money, {:billing_reference => options[:billing_reference],:customer_reference => options[:customer_reference],:custom => options[:custom],:descriptor => options[:descriptor]})
- handle_result(void)
+ def store(creditcard, options = {})
+ address = options[:billing_address] || options[:address] || {}
+
+ result = Samurai::PaymentMethod.create({
+ :card_number => creditcard.number,
+ :expiry_month => creditcard.month.to_s.rjust(2, "0"),
+ :expiry_year => creditcard.year.to_s,
+ :cvv => creditcard.verification_value,
+ :first_name => creditcard.first_name,
+ :last_name => creditcard.last_name,
+ :address_1 => address[:address1],
+ :address_2 => address[:address2],
+ :city => address[:city],
+ :zip => address[:zip],
+ :sandbox => test?
+ })
+
+ Response.new(result.is_sensitive_data_valid,
+ message_from_result(result),
+ { :payment_method_token => result.is_sensitive_data_valid && result.payment_method_token })
+ end
+
+ private
+
+ def payment_method_token(credit_card_or_vault_id, options)
+ return credit_card_or_vault_id if credit_card_or_vault_id.is_a?(String)
+ store_result = store(credit_card_or_vault_id, options)
+ store_result.success? ? store_result.params["payment_method_token"] : store_result
end
def handle_result(result)
- response_params, response_options, avs_result, cvv_result = {}, {}, {}, {}
+ response_params, response_options = {}, {}
if result.success?
- response_options[:reference_id] = result.reference_id
+ response_options[:test] = test?
response_options[:authorization] = result.reference_id
- response_options[:transaction_token] = result.transaction_token
- response_options[:payment_method_token] = result.payment_method.payment_method_token
+ response_params[:reference_id] = result.reference_id
+ response_params[:transaction_token] = result.transaction_token
+ response_params[:payment_method_token] = result.payment_method.payment_method_token
end
- # TODO: handle cvv here
- response_options[:avs_result] = { :code => result.processor_response.avs_result_code }
+ response_options[:avs_result] = { :code => result.processor_response && result.processor_response.avs_result_code }
+ response_options[:cvv_result] = result.processor_response && result.processor_response.cvv_result_code
+
message = message_from_result(result)
Response.new(result.success?, message, response_params, response_options)
end
- def store(creditcard, options = {})
- options[:billing_address] ||= {}
-
- result = Samurai::PaymentMethod.create({
- :card_number => creditcard.number,
- :expiry_month => creditcard.month.to_s.rjust(2, "0"),
- :expiry_year => creditcard.year.to_s,
- :cvv => creditcard.verification_value,
- :first_name => creditcard.first_name,
- :last_name => creditcard.last_name,
- :address_1 => options[:billing_address][:address1],
- :address_2 => options[:billing_address][:address2],
- :city => options[:billing_address][:city],
- :zip => options[:billing_address][:zip],
- :sandbox => @sandbox
- })
-
- Response.new(result.is_sensitive_data_valid,
- message_from_result(result),
- { :payment_method_token => result.is_sensitive_data_valid && result.payment_method_token })
- end
-
def message_from_result(result)
- if result.success?
- "OK"
- else
- result.errors.map {|_, messages| [messages].flatten.first }.first
- end
+ return "OK" if result.success?
+ result.errors.values.flatten.join(" ")
end
+ def processor_options(options)
+ options.slice(:billing_reference, :customer_reference, :custom, :descriptor)
+ end
end
end
-end
+end
View
@@ -393,10 +393,9 @@ realex_mastercard_coms_error:
verification_value: '123'
samurai:
- merchant_key: 'a1ebafb6da5238fb8a3ac9f6'
- merchant_password: 'ae1aa640f6b735c4730fbb56'
+ login: 'a1ebafb6da5238fb8a3ac9f6'
+ password: 'ae1aa640f6b735c4730fbb56'
processor_token: '5a0e1ca1e5a11a2997bbf912'
- sandbox: true
sage:
login: login
@@ -2,59 +2,54 @@
class RemoteSamuraiTest < Test::Unit::TestCase
-
def setup
@gateway = SamuraiGateway.new(fixtures(:samurai))
@amount = 100
- @declined_amount = 100.02
- @invalid_card_amount = 100.07
- @expired_card_amount = 100.08
+ @declined_amount = 102
+ @invalid_card_amount = 107
+ @expired_card_amount = 108
@credit_card = credit_card('4111111111111111', :verification_value => '111')
-
- @options = {
- :address1 => "1000 1st Av",
- :zip => "10101",
- :billing_reference => "billing_reference",
- :customer_reference => "customer_reference",
- :custom => "custom",
- :descriptor => "descriptor",
- }
end
def test_successful_purchase
- assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert response = @gateway.purchase(@amount, @credit_card)
assert_success response
assert_equal 'OK', response.message
end
def test_declined_purchase
- assert response = @gateway.purchase(@declined_amount, @credit_card, @options)
+ assert response = @gateway.purchase(@declined_amount, @credit_card)
assert_failure response
assert_equal 'The card was declined.', response.message
end
def test_invalid_purchase
- assert response = @gateway.purchase(@invalid_card_amount, @credit_card, @options)
+ assert response = @gateway.purchase(@invalid_card_amount, @credit_card)
assert_failure response
assert_equal 'The card number was invalid.', response.message
end
def test_expired_purchase
- assert response = @gateway.purchase(@expired_card_amount, @credit_card, @options)
+ assert response = @gateway.purchase(@expired_card_amount, @credit_card)
assert_failure response
- assert_equal 'The expiration date month was invalid, or prior to today.', response.message
+ assert_equal 'The expiration date month was invalid, or prior to today. The expiration date year was invalid, or prior to today.', response.message
end
def test_successful_auth_and_capture
- assert authorize = @gateway.authorize(@amount, @credit_card, @options)
+ assert authorize = @gateway.authorize(@amount, @credit_card)
assert_success authorize
assert_equal 'OK', authorize.message
- assert capture = @gateway.capture(@amount, authorize.authorization, @options)
+ assert capture = @gateway.capture(@amount, authorize.authorization)
assert_success capture
assert_equal 'OK', capture.message
end
+ def test_successful_auth_and_void
+ assert_success authorize = @gateway.authorize(@amount, @credit_card)
+ assert_success @gateway.void(authorize.authorization)
+ end
+
def test_invalid_login
assert_raise(ArgumentError) do
SamuraiGateway.new( :login => '', :password => '' )
Oops, something went wrong.

0 comments on commit 76f6242

Please sign in to comment.