diff --git a/lib/active_merchant/billing/gateways/eway_managed.rb b/lib/active_merchant/billing/gateways/eway_managed.rb
index a3b01cfd3ad..f89e5bb075b 100644
--- a/lib/active_merchant/billing/gateways/eway_managed.rb
+++ b/lib/active_merchant/billing/gateways/eway_managed.rb
@@ -45,7 +45,7 @@ def store(creditcard, options = {})
add_creditcard(post, creditcard)
add_address(post, billing_address)
- add_misc_fields(post, billing_address)
+ add_misc_fields(post, options)
commit("CreateCustomer", post)
end
@@ -63,17 +63,30 @@ def update(billing_id, creditcard, options={})
post[:managedCustomerID]=billing_id
add_creditcard(post, creditcard)
add_address(post, billing_address)
- add_misc_fields(post, billing_address)
+ add_misc_fields(post, options)
commit("UpdateCustomer", post)
end
- #process payment for given amount from stored CC "ManagedCustomerID = billing_id"
+ # Process a payment in the given amount against the stored credit card given by billing_id
+ #
+ # ==== Parameters
+ #
+ # * money -- The amount to be purchased as an Integer value in cents.
+ # * billing_id -- The eWay provided card/customer token to charge (managedCustomerID)
+ # * options -- A hash of optional parameters.
+ #
+ # ==== Options
+ #
+ # * :order_id -- The order number, passed to eWay as the "Invoice Reference"
+ # * :invoice -- The invoice number, passed to eWay as the "Invoice Reference" unless :order_id is also given
+ # * :description -- A description of the payment, passed to eWay as the "Invoice Description"
def purchase(money, billing_id, options={})
post = {}
post[:managedCustomerID] = billing_id.to_s
post[:amount]=money
-
+ add_invoice(post, options)
+
commit("ProcessPayment", post)
end
@@ -102,14 +115,21 @@ def add_address(post, address)
end
def add_misc_fields(post, options)
- post[:CustomerRef]=options[:customer_ref].to_s
- post[:Title]=options[:title]
- post[:Company]=options[:company]
- post[:JobDesc]=options[:job_desc]
- post[:Email]=options[:email]
- post[:URL]=options[:url]
+ post[:CustomerRef]=options[:billing_address][:customer_ref] || options[:customer]
+ post[:Title]=options[:billing_address][:title]
+ post[:Company]=options[:billing_address][:company]
+ post[:JobDesc]=options[:billing_address][:job_desc]
+ post[:Email]=options[:billing_address][:email] || options[:email]
+ post[:URL]=options[:billing_address][:url]
+ post[:Comments]=options[:description]
+ end
+
+ def add_invoice(post, options)
+ post[:invoiceReference] = options[:order_id] || options[:invoice]
+ post[:invoiceDescription] = options[:description]
end
+
# add credit card details to be stored by eway. NOTE eway requires "title" field
def add_creditcard(post, creditcard)
post[:CCNumber] = creditcard.number
@@ -188,7 +208,12 @@ def commit(action, post)
# Where we build the full SOAP 1.2 request using builder
def soap_request(arguments, action)
# eWay demands all fields be sent, but contain an empty string if blank
- post=default_fields.merge(arguments)
+ post = case action
+ when 'ProcessPayment'
+ default_payment_fields.merge(arguments)
+ else
+ default_customer_fields.merge(arguments)
+ end
xml = Builder::XmlMarkup.new :indent => 2
xml.instruct!
@@ -211,7 +236,7 @@ def soap_request(arguments, action)
xml.target!
end
- def default_fields
+ def default_customer_fields
hash={}
%w( CustomerRef Title FirstName LastName Company JobDesc Email Address Suburb State PostCode Country Phone Mobile Fax URL Comments CCNumber CCNameOnCard CCExpiryMonth CCExpiryYear ).each do |field|
hash[field.to_sym]=''
@@ -219,6 +244,14 @@ def default_fields
return hash
end
+ def default_payment_fields
+ hash={}
+ %w( managedCustomerID amount invoiceReference invoiceDescription ).each do |field|
+ hash[field.to_sym]=''
+ end
+ return hash
+ end
+
class EwayResponse < Response
# add a method to response so we can easily get the eway token "ManagedCustomerID"
def token
diff --git a/test/remote/gateways/remote_eway_managed_test.rb b/test/remote/gateways/remote_eway_managed_test.rb
index dc5f2c3bd93..e8cf6e26691 100644
--- a/test/remote/gateways/remote_eway_managed_test.rb
+++ b/test/remote/gateways/remote_eway_managed_test.rb
@@ -35,7 +35,7 @@ def test_invalid_login
:username => ''
)
assert response = gateway.purchase(@amount, @valid_customer_id, @options)
- assert_equal 'Login failed', response.message
+ assert_equal 'Login failed. ', response.message
assert_failure response
end
diff --git a/test/unit/gateways/eway_managed_test.rb b/test/unit/gateways/eway_managed_test.rb
index b3cdaaeeb6b..c49469c0818 100644
--- a/test/unit/gateways/eway_managed_test.rb
+++ b/test/unit/gateways/eway_managed_test.rb
@@ -26,7 +26,10 @@ def setup
:phone => '(555)555-5555'
},
:email => 'someguy1232@fakeemail.net',
- :order_id => '1000'
+ :order_id => '1000',
+ :customer => 'mycustomerref',
+ :description => 'My Description',
+ :invoice => 'invoice-4567'
}
end
@@ -78,6 +81,51 @@ def test_successful_purchase
assert_equal "123456", response.authorization
assert response.test?
end
+
+ def test_expected_request_on_purchase
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ # Compare the actual and expected XML documents, by converting them to Hashes first
+ expected = Hash.from_xml(expected_purchase_request)
+ actual = Hash.from_xml(data)
+ expected == actual
+ }.returns(successful_purchase_response)
+ @gateway.purchase(@amount, @valid_customer_id, @options)
+ end
+
+ def test_purchase_invoice_reference_comes_from_order_id_or_invoice
+ options = @options.dup
+
+ # invoiceReference == options[:order_id]
+ options[:order_id] = 'order_id'
+ options.delete(:invoice)
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['ProcessPayment']['invoiceReference'] == 'order_id'
+ }.returns(successful_purchase_response)
+ @gateway.purchase(@amount, @valid_customer_id, options)
+
+ # invoiceReference == options[:invoice]
+ options[:invoice] = 'invoice'
+ options.delete(:order_id)
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['ProcessPayment']['invoiceReference'] == 'invoice'
+ }.returns(successful_purchase_response)
+ @gateway.purchase(@amount, @valid_customer_id, options)
+
+ # invoiceReference == options[:order_id] || options[:invoice]
+ options[:order_id] = 'order_id'
+ options[:invoice] = 'invoice'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['ProcessPayment']['invoiceReference'] == 'order_id'
+ }.returns(successful_purchase_response)
+ @gateway.purchase(@amount, @valid_customer_id, options)
+
+ end
def test_invalid_customer_id
@gateway.expects(:ssl_post).returns(unsuccessful_authorization_response)
@@ -97,6 +145,84 @@ def test_successful_store
assert_equal "1234567", response.token
assert response.test?
end
+
+ def test_expected_request_on_store
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ # Compare the actual and expected XML documents, by converting them to Hashes first
+ expected = Hash.from_xml(expected_store_request)
+ actual = Hash.from_xml(data)
+ expected == actual
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, @options)
+ end
+
+ def test_email_on_store_may_come_from_options_root_or_billing_address
+ options = @options.dup
+
+ # Legacy Behavior
+ options.delete(:email)
+ options[:billing_address][:email] = 'email+billing@example.com'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['Email'] == 'email+billing@example.com'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+
+ # Desired Behavior
+ options[:billing_address].delete(:email)
+ options[:email] = 'email+root@example.com'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['Email'] == 'email+root@example.com'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+
+ # Precedence given to billing address when email is in both hashes (to support legacy behavior)
+ options[:billing_address][:email] = 'email+billing@example.com'
+ options[:email] = 'email+root@example.com'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['Email'] == 'email+billing@example.com'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+ end
+
+ def test_customer_ref_on_store_may_come_from_options_root_or_billing_address
+ options = @options.dup
+
+ # Legacy Behavior
+ options.delete(:customer)
+ options[:billing_address][:customer_ref] = 'customer_ref+billing'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['CustomerRef'] == 'customer_ref+billing'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+
+ # Desired Behavior
+ options[:billing_address].delete(:customer_ref)
+ options[:customer] = 'customer_ref+root'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['CustomerRef'] == 'customer_ref+root'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+
+ # Precedence given to billing address when customer_ref is in both hashes (to support legacy behavior)
+ options[:billing_address][:customer_ref] = 'customer_ref+billing'
+ options[:customer] = 'customer_ref+root'
+
+ @gateway.expects(:ssl_post).with { |endpoint, data, headers|
+ request_hash = Hash.from_xml(data)
+ request_hash['Envelope']['Body']['CreateCustomer']['CustomerRef'] == 'customer_ref+billing'
+ }.returns(successful_store_response)
+ @gateway.store(@credit_card, options)
+ end
def test_sucessful_update
@gateway.expects(:ssl_post).returns(successful_update_response)
@@ -164,5 +290,70 @@ def successful_update_response
XML
end
+
+ # Documented here: https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?op=CreateCustomer
+ def expected_store_request
+ <<-XML
+
+
+
+
+ login
+ username
+ password
+
+
+
+
+ Mr.
+ #{@credit_card.first_name}
+ #{@credit_card.last_name}
+ #{@options[:billing_address][:address1]}
+ #{@options[:billing_address][:city]}
+ #{@options[:billing_address][:state]}
+ #{@options[:billing_address][:company]}
+ #{@options[:billing_address][:zip]}
+ #{@options[:billing_address][:country]}
+ #{@options[:email]}
+
+ #{@options[:billing_address][:phone]}
+
+ #{@options[:customer]}
+
+ #{@options[:description]}
+
+ #{@credit_card.number}
+ #{@credit_card.first_name} #{@credit_card.last_name}
+ #{sprintf("%.2i", @credit_card.month)}
+ #{sprintf("%.4i", @credit_card.year)[-2..-1]}
+
+
+
+ XML
+ end
+
+ # Documented here: https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?op=CreateCustomer
+ def expected_purchase_request
+ <<-XML
+
+
+
+
+ login
+ username
+ password
+
+
+
+
+ #{@valid_customer_id}
+ #{@amount}
+ #{@options[:order_id] || @options[:invoice]}
+ #{@options[:description]}
+
+
+
+ XML
+ end
end