activemerchant 1.56.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +42 -0
  3. data/lib/active_merchant/billing/gateways/authorize_net.rb +52 -21
  4. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -0
  5. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +243 -0
  6. data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
  7. data/lib/active_merchant/billing/gateways/braintree_blue.rb +11 -11
  8. data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
  9. data/lib/active_merchant/billing/gateways/card_stream.rb +36 -11
  10. data/lib/active_merchant/billing/gateways/checkout_v2.rb +3 -0
  11. data/lib/active_merchant/billing/gateways/clearhaus.rb +2 -2
  12. data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
  13. data/lib/active_merchant/billing/gateways/cyber_source.rb +12 -1
  14. data/lib/active_merchant/billing/gateways/element.rb +335 -0
  15. data/lib/active_merchant/billing/gateways/forte.rb +8 -0
  16. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  17. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +2 -1
  19. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  20. data/lib/active_merchant/billing/gateways/payeezy.rb +54 -12
  21. data/lib/active_merchant/billing/gateways/sage.rb +379 -128
  22. data/lib/active_merchant/billing/gateways/stripe.rb +13 -3
  23. data/lib/active_merchant/billing/gateways/trans_first.rb +26 -6
  24. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +573 -0
  25. data/lib/active_merchant/billing/gateways/worldpay.rb +7 -0
  26. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +11 -0
  27. data/lib/active_merchant/version.rb +1 -1
  28. metadata +7 -6
  29. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
  30. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
  31. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
  32. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
6
6
  self.display_name = "BridgePay"
7
7
  self.homepage_url = "http://www.bridgepaynetwork.com/"
8
8
 
9
- self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/transact.asmx"
10
- self.live_url = "https://gateway.itstgate.com/SmartPayments/transact.asmx"
9
+ self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/transact3.asmx"
10
+ self.live_url = "https://gateway.itstgate.com/SmartPayments/transact3.asmx"
11
11
 
12
12
  self.supported_countries = ["CA", "US"]
13
13
  self.default_currency = "USD"
@@ -75,6 +75,17 @@ module ActiveMerchant #:nodoc:
75
75
  end
76
76
  end
77
77
 
78
+ def store(creditcard, options={})
79
+ post = initialize_required_fields('')
80
+ post[:transaction] = 'Create'
81
+ post[:CardNumber] = creditcard.number
82
+ post[:CustomerPaymentInfoKey] = ''
83
+ post[:token] = ''
84
+ add_payment_method(post, creditcard)
85
+
86
+ commit(post)
87
+ end
88
+
78
89
  def supports_scrubbing?
79
90
  true
80
91
  end
@@ -96,6 +107,8 @@ module ActiveMerchant #:nodoc:
96
107
  post[:ExpDate] = expdate(payment_method)
97
108
  post[:CardNum] = payment_method.number
98
109
  post[:CVNum] = payment_method.verification_value
110
+ elsif payment_method.is_a?(String)
111
+ add_token(post, payment_method)
99
112
  else
100
113
  post[:CheckNum] = payment_method.number
101
114
  post[:TransitNum] = payment_method.routing_number
@@ -105,6 +118,11 @@ module ActiveMerchant #:nodoc:
105
118
  end
106
119
  end
107
120
 
121
+ def add_token(post, payment_method)
122
+ payment_method = payment_method.split("|")
123
+ post[:ExtData] = "<Force>T</Force><CardVault><Transaction>Read</Transaction><CustomerPaymentInfoKey>#{payment_method[1]}</CustomerPaymentInfoKey><Token>#{payment_method[0]}</Token><ExpDate>#{payment_method[2]}</ExpDate></CardVault>"
124
+ end
125
+
108
126
  def initialize_required_fields(transaction_type)
109
127
  post = {}
110
128
  post[:TransType] = transaction_type
@@ -164,9 +182,8 @@ module ActiveMerchant #:nodoc:
164
182
  end
165
183
 
166
184
  def commit(parameters)
167
- url = url(parameters[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard')
168
185
  data = post_data(parameters)
169
- raw = parse(ssl_post(url, data))
186
+ raw = parse(ssl_post(url(parameters), data))
170
187
 
171
188
  Response.new(
172
189
  success_from(raw),
@@ -177,9 +194,17 @@ module ActiveMerchant #:nodoc:
177
194
  )
178
195
  end
179
196
 
180
- def url(action)
181
- base = test? ? test_url : live_url
182
- "#{base}/#{action}"
197
+ def url(params)
198
+ if params[:transaction]
199
+ "#{base_url}/ManageCardVault"
200
+ else
201
+ action = params[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard'
202
+ "#{base_url}/#{action}"
203
+ end
204
+ end
205
+
206
+ def base_url
207
+ test? ? test_url : live_url
183
208
  end
184
209
 
185
210
  def success_from(response)
@@ -191,7 +216,11 @@ module ActiveMerchant #:nodoc:
191
216
  end
192
217
 
193
218
  def authorization_from(response)
194
- [response[:authcode], response[:pnref]].join("|")
219
+ if response[:token]
220
+ [response[:token], response[:customerpaymentinfokey], response[:expdate]].join("|")
221
+ else
222
+ [response[:authcode], response[:pnref]].join("|")
223
+ end
195
224
  end
196
225
 
197
226
  def split_authorization(authorization)
@@ -75,11 +75,12 @@ module ActiveMerchant #:nodoc:
75
75
 
76
76
  def authorize(money, creditcard, options = {})
77
77
  post = {}
78
+ add_pair(post, :captureDelay, -1)
78
79
  add_amount(post, money, options)
79
80
  add_invoice(post, creditcard, money, options)
80
81
  add_creditcard(post, creditcard)
81
82
  add_customer_data(post, options)
82
- commit('PREAUTH', post)
83
+ commit('SALE', post)
83
84
  end
84
85
 
85
86
  def purchase(money, creditcard, options = {})
@@ -94,8 +95,9 @@ module ActiveMerchant #:nodoc:
94
95
  def capture(money, authorization, options = {})
95
96
  post = {}
96
97
  add_pair(post, :xref, authorization)
97
- add_amount(post, money, options)
98
- commit('SALE', post)
98
+ add_pair(post, :amount, amount(money), :required => true)
99
+
100
+ commit('CAPTURE', post)
99
101
  end
100
102
 
101
103
  def refund(money, authorization, options = {})
@@ -154,8 +156,8 @@ module ActiveMerchant #:nodoc:
154
156
  add_pair(post, :item1GrossValue, amount(money))
155
157
  end
156
158
 
157
- add_pair(post, :threeDSRequired, (options[:threeds_required] || @threeds_required) ? 'Y' : 'N')
158
159
  add_pair(post, :type, options[:type] || '1')
160
+ add_threeds_required(post, options)
159
161
  end
160
162
 
161
163
  def add_creditcard(post, credit_card)
@@ -175,6 +177,10 @@ module ActiveMerchant #:nodoc:
175
177
  add_pair(post, :cardCVV, credit_card.verification_value)
176
178
  end
177
179
 
180
+ def add_threeds_required(post, options)
181
+ add_pair(post, :threeDSRequired, (options[:threeds_required] || @threeds_required) ? 'Y' : 'N')
182
+ end
183
+
178
184
  def add_hmac(post)
179
185
  result = post.sort.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
180
186
  result = Digest::SHA512.hexdigest("#{result}#{@options[:shared_secret]}")
@@ -194,11 +200,10 @@ module ActiveMerchant #:nodoc:
194
200
  end
195
201
 
196
202
  def commit(action, parameters)
197
-
203
+ parameters.update(:countryCode => self.supported_countries[0]) unless action == 'CAPTURE'
198
204
  parameters.update(
199
205
  :merchantID => @options[:login],
200
- :action => action,
201
- :countryCode => self.supported_countries[0],
206
+ :action => action
202
207
  )
203
208
  # adds a signature to the post hash/array
204
209
  add_hmac(parameters)
@@ -211,13 +216,32 @@ module ActiveMerchant #:nodoc:
211
216
  :test => test?,
212
217
  :authorization => response[:xref],
213
218
  :cvv_result => CVV_CODE[response[:avscv2ResponseCode].to_s[0, 1]],
214
- :avs_result => {
215
- :postal_match => AVS_POSTAL_MATCH[response[:avscv2ResponseCode].to_s[1, 1]],
216
- :street_match => AVS_STREET_MATCH[response[:avscv2ResponseCode].to_s[2, 1]]
217
- }
219
+ :avs_result => avs_from(response)
218
220
  )
219
221
  end
220
222
 
223
+ def avs_from(response)
224
+ postal_match = AVS_POSTAL_MATCH[response[:avscv2ResponseCode].to_s[1, 1]]
225
+ street_match = AVS_STREET_MATCH[response[:avscv2ResponseCode].to_s[2, 1]]
226
+
227
+ code = if postal_match == "Y" && street_match == "Y"
228
+ "M"
229
+ elsif postal_match == "Y"
230
+ "P"
231
+ elsif street_match == "Y"
232
+ "A"
233
+ else
234
+ "I"
235
+ end
236
+
237
+ AVSResult.new({
238
+ :code => code,
239
+ :postal_match => postal_match,
240
+ :street_match => street_match
241
+ })
242
+ end
243
+
244
+
221
245
  def currency_code(currency)
222
246
  CURRENCY_CODES[currency]
223
247
  end
@@ -229,6 +253,7 @@ module ActiveMerchant #:nodoc:
229
253
  def add_pair(post, key, value, options = {})
230
254
  post[key] = value if !value.blank? || options[:required]
231
255
  end
256
+
232
257
  end
233
258
  end
234
259
  end
@@ -78,6 +78,9 @@ module ActiveMerchant #:nodoc:
78
78
  post[:value] = amount(money)
79
79
  post[:trackId] = options[:order_id]
80
80
  post[:currency] = options[:currency] || currency(money)
81
+ post[:descriptor] = {}
82
+ post[:descriptor][:name] = options[:descriptor_name] if options[:descriptor_name]
83
+ post[:descriptor][:city] = options[:descriptor_city] if options[:descriptor_city]
81
84
  end
82
85
 
83
86
  def add_payment_method(post, payment_method)
@@ -90,7 +90,7 @@ module ActiveMerchant #:nodoc:
90
90
  # options - A standard ActiveMerchant options hash
91
91
  def capture(amount, authorization, options={})
92
92
  post = {}
93
- add_amount(post, amount, options)
93
+ add_invoice(post, amount, options)
94
94
 
95
95
  commit("/authorizations/#{authorization}/captures", post)
96
96
  end
@@ -145,7 +145,7 @@ module ActiveMerchant #:nodoc:
145
145
  def add_invoice(post, money, options)
146
146
  add_amount(post, money, options)
147
147
  post[:reference] = options[:order_id] if options[:order_id]
148
- post[:text_on_statement] = options[:description] if options[:description]
148
+ post[:text_on_statement] = options[:text_on_statement] if options[:text_on_statement]
149
149
  end
150
150
 
151
151
  def add_amount(post, amount, options)
@@ -120,7 +120,7 @@ module ActiveMerchant #:nodoc:
120
120
 
121
121
  def add_card_details(xml, payment_method, options={})
122
122
  xml.CardDetails do
123
- xml.Manual(type: "cnp") do
123
+ xml.Manual(type: "ecommerce") do
124
124
  xml.PAN payment_method.number
125
125
  xml.ExpiryDate exp_date(payment_method)
126
126
  xml.CSC payment_method.verification_value unless empty?(payment_method.verification_value)
@@ -33,7 +33,7 @@ module ActiveMerchant #:nodoc:
33
33
  self.test_url = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
34
34
  self.live_url = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'
35
35
 
36
- XSD_VERSION = "1.109"
36
+ XSD_VERSION = "1.121"
37
37
 
38
38
  # visa, master, american_express, discover
39
39
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
@@ -261,6 +261,7 @@ module ActiveMerchant #:nodoc:
261
261
  def build_auth_request(money, creditcard_or_reference, options)
262
262
  xml = Builder::XmlMarkup.new :indent => 2
263
263
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
264
+ add_mdd_fields(xml, options)
264
265
  add_auth_service(xml, creditcard_or_reference, options)
265
266
  add_business_rules_data(xml, creditcard_or_reference, options)
266
267
  xml.target!
@@ -291,6 +292,7 @@ module ActiveMerchant #:nodoc:
291
292
  def build_purchase_request(money, payment_method_or_reference, options)
292
293
  xml = Builder::XmlMarkup.new :indent => 2
293
294
  add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
295
+ add_mdd_fields(xml, options)
294
296
  if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
295
297
  add_check_service(xml)
296
298
  else
@@ -476,6 +478,15 @@ module ActiveMerchant #:nodoc:
476
478
  end
477
479
  end
478
480
 
481
+ def add_mdd_fields(xml, options)
482
+ xml.tag! 'merchantDefinedData' do
483
+ (1..20).each do |each|
484
+ key = "mdd_field_#{each}".to_sym
485
+ xml.tag!("field#{each}", options[key]) if options[key]
486
+ end
487
+ end
488
+ end
489
+
479
490
  def add_check(xml, check)
480
491
  xml.tag! 'check' do
481
492
  xml.tag! 'accountNumber', check.account_number
@@ -0,0 +1,335 @@
1
+ require 'nokogiri'
2
+ require 'securerandom'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class ElementGateway < Gateway
7
+ self.test_url = 'https://certtransaction.elementexpress.com/express.asmx'
8
+ self.live_url = 'https://transaction.elementexpress.com/express.asmx'
9
+
10
+ self.supported_countries = ['US']
11
+ self.default_currency = 'USD'
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
13
+
14
+ self.homepage_url = 'http://www.elementps.com'
15
+ self.display_name = 'Element'
16
+
17
+ SERVICE_TEST_URL = 'https://certservices.elementexpress.com/express.asmx'
18
+ SERVICE_LIVE_URL = 'https://service.elementexpress.com/express.asmx'
19
+
20
+ def initialize(options={})
21
+ requires!(options, :account_id, :account_token, :application_id, :acceptor_id, :application_name, :application_version)
22
+ super
23
+ end
24
+
25
+ def purchase(money, payment, options={})
26
+ action = payment.is_a?(Check) ? "CheckSale" : "CreditCardSale"
27
+
28
+ request = build_soap_request do |xml|
29
+ xml.send(action, xmlns: "https://transaction.elementexpress.com") do
30
+ add_credentials(xml)
31
+ add_payment_method(xml, payment)
32
+ add_transaction(xml, money)
33
+ add_terminal(xml, options)
34
+ add_address(xml, options)
35
+ end
36
+ end
37
+
38
+ commit(action, request, money)
39
+ end
40
+
41
+ def authorize(money, payment, options={})
42
+ request = build_soap_request do |xml|
43
+ xml.CreditCardAuthorization(xmlns: "https://transaction.elementexpress.com") do
44
+ add_credentials(xml)
45
+ add_payment_method(xml, payment)
46
+ add_transaction(xml, money)
47
+ add_terminal(xml, options)
48
+ add_address(xml, options)
49
+ end
50
+ end
51
+
52
+ commit('CreditCardAuthorization', request, money)
53
+ end
54
+
55
+ def capture(money, authorization, options={})
56
+ trans_id, _ = split_authorization(authorization)
57
+ options.merge!({trans_id: trans_id})
58
+
59
+ request = build_soap_request do |xml|
60
+ xml.CreditCardAuthorizationCompletion(xmlns: "https://transaction.elementexpress.com") do
61
+ add_credentials(xml)
62
+ add_transaction(xml, money, options)
63
+ add_terminal(xml, options)
64
+ end
65
+ end
66
+
67
+ commit('CreditCardAuthorizationCompletion', request, money)
68
+ end
69
+
70
+ def refund(money, authorization, options={})
71
+ trans_id, _ = split_authorization(authorization)
72
+ options.merge!({trans_id: trans_id})
73
+
74
+ request = build_soap_request do |xml|
75
+ xml.CreditCardReturn(xmlns: "https://transaction.elementexpress.com") do
76
+ add_credentials(xml)
77
+ add_transaction(xml, money, options)
78
+ add_terminal(xml, options)
79
+ end
80
+ end
81
+
82
+ commit('CreditCardReturn', request, money)
83
+ end
84
+
85
+ def void(authorization, options={})
86
+ trans_id, trans_amount = split_authorization(authorization)
87
+ options.merge!({trans_id: trans_id, trans_amount: trans_amount, reversal_type: "Full"})
88
+
89
+ request = build_soap_request do |xml|
90
+ xml.CreditCardReversal(xmlns: "https://transaction.elementexpress.com") do
91
+ add_credentials(xml)
92
+ add_transaction(xml, trans_amount, options)
93
+ add_terminal(xml, options)
94
+ end
95
+ end
96
+
97
+ commit('CreditCardReversal', request, trans_amount)
98
+ end
99
+
100
+ def store(payment, options = {})
101
+ request = build_soap_request do |xml|
102
+ xml.PaymentAccountCreate(xmlns: "https://services.elementexpress.com") do
103
+ add_credentials(xml)
104
+ add_payment_method(xml, payment)
105
+ add_payment_account(xml, payment, options[:payment_account_reference_number] || SecureRandom.hex(20))
106
+ add_address(xml, options)
107
+ end
108
+ end
109
+
110
+ commit('PaymentAccountCreate', request, nil)
111
+ end
112
+
113
+ def verify(credit_card, options={})
114
+ MultiResponse.run(:use_first_response) do |r|
115
+ r.process { authorize(100, credit_card, options) }
116
+ r.process(:ignore_result) { void(r.authorization, options) }
117
+ end
118
+ end
119
+
120
+ def supports_scrubbing?
121
+ true
122
+ end
123
+
124
+ def scrub(transcript)
125
+ transcript.
126
+ gsub(%r((<AccountToken>).+?(</AccountToken>))i, '\1[FILTERED]\2').
127
+ gsub(%r((<CardNumber>).+?(</CardNumber>))i, '\1[FILTERED]\2').
128
+ gsub(%r((<CVV>).+?(</CVV>))i, '\1[FILTERED]\2').
129
+ gsub(%r((<AccountNumber>).+?(</AccountNumber>))i, '\1[FILTERED]\2').
130
+ gsub(%r((<RoutingNumber>).+?(</RoutingNumber>))i, '\1[FILTERED]\2')
131
+ end
132
+
133
+ private
134
+
135
+ def add_credentials(xml)
136
+ xml.credentials do
137
+ xml.AccountID @options[:account_id]
138
+ xml.AccountToken @options[:account_token]
139
+ xml.AcceptorID @options[:acceptor_id]
140
+ end
141
+ xml.application do
142
+ xml.ApplicationID @options[:application_id]
143
+ xml.ApplicationName @options[:application_name]
144
+ xml.ApplicationVersion @options[:application_version]
145
+ end
146
+ end
147
+
148
+ def add_payment_method(xml, payment)
149
+ if payment.is_a?(String)
150
+ add_payment_account_id(xml, payment)
151
+ elsif payment.is_a?(Check)
152
+ add_echeck(xml, payment)
153
+ else
154
+ add_credit_card(xml, payment)
155
+ end
156
+ end
157
+
158
+ def add_payment_account(xml, payment, payment_account_reference_number)
159
+ xml.paymentAccount do
160
+ xml.PaymentAccountType payment_account_type(payment)
161
+ xml.PaymentAccountReferenceNumber payment_account_reference_number
162
+ end
163
+ end
164
+
165
+ def add_payment_account_id(xml, payment)
166
+ xml.extendedParameters do
167
+ xml.ExtendedParameters do
168
+ xml.Key "PaymentAccount"
169
+ xml.Value("xsi:type" => "PaymentAccount") do
170
+ xml.PaymentAccountID payment
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ def add_transaction(xml, money, options = {})
177
+ xml.transaction do
178
+ xml.ReversalType options[:reversal_type] if options[:reversal_type]
179
+ xml.TransactionID options[:trans_id] if options[:trans_id]
180
+ xml.TransactionAmount amount(money.to_i) if money
181
+ xml.MarketCode "Default" if money
182
+ xml.ReferenceNumber options[:order_id] || SecureRandom.hex(20)
183
+ end
184
+ end
185
+
186
+ def add_terminal(xml, options)
187
+ xml.terminal do
188
+ xml.TerminalID "01"
189
+ xml.CardPresentCode "UseDefault"
190
+ xml.CardholderPresentCode "UseDefault"
191
+ xml.CardInputCode "UseDefault"
192
+ xml.CVVPresenceCode "UseDefault"
193
+ xml.TerminalCapabilityCode "UseDefault"
194
+ xml.TerminalEnvironmentCode "UseDefault"
195
+ xml.MotoECICode "NonAuthenticatedSecureECommerceTransaction"
196
+ end
197
+ end
198
+
199
+ def add_credit_card(xml, payment)
200
+ xml.card do
201
+ xml.CardNumber payment.number
202
+ xml.ExpirationMonth format(payment.month, :two_digits)
203
+ xml.ExpirationYear format(payment.year, :two_digits)
204
+ xml.CardholderName payment.first_name + " " + payment.last_name
205
+ xml.CVV payment.verification_value
206
+ end
207
+ end
208
+
209
+ def add_echeck(xml, payment)
210
+ xml.demandDepositAccount do
211
+ xml.AccountNumber payment.account_number
212
+ xml.RoutingNumber payment.routing_number
213
+ xml.DDAAccountType payment.account_type.capitalize
214
+ end
215
+ end
216
+
217
+ def add_address(xml, options)
218
+ if address = options[:billing_address] || options[:address]
219
+ xml.address do
220
+ xml.BillingAddress1 address[:address1] if address[:address1]
221
+ xml.BillingAddress2 address[:address2] if address[:address2]
222
+ xml.BillingCity address[:city] if address[:city]
223
+ xml.BillingState address[:state] if address[:state]
224
+ xml.BillingZipcode address[:zip] if address[:zip]
225
+ xml.BillingEmail address[:email] if address[:email]
226
+ xml.BillingPhone address[:phone_number] if address[:phone_number]
227
+ end
228
+ end
229
+ end
230
+
231
+ def parse(xml)
232
+ response = {}
233
+
234
+ doc = Nokogiri::XML(xml)
235
+ doc.remove_namespaces!
236
+ root = doc.root.xpath("//response/*")
237
+
238
+ if root.empty?
239
+ root = doc.root.xpath("//Response/*")
240
+ end
241
+
242
+ root.each do |node|
243
+ if (node.elements.empty?)
244
+ response[node.name.downcase] = node.text
245
+ else
246
+ node_name = node.name.downcase
247
+ response[node_name] = Hash.new
248
+
249
+ node.elements.each do |childnode|
250
+ response[node_name][childnode.name.downcase] = childnode.text
251
+ end
252
+ end
253
+ end
254
+
255
+ response
256
+ end
257
+
258
+ def commit(action, xml, amount)
259
+ response = parse(ssl_post(url(action), xml, headers(action)))
260
+
261
+ Response.new(
262
+ success_from(response),
263
+ message_from(response),
264
+ response,
265
+ authorization: authorization_from(action, response, amount),
266
+ test: test?
267
+ )
268
+ end
269
+
270
+ def authorization_from(action, response, amount)
271
+ if action == "PaymentAccountCreate"
272
+ response["paymentaccount"]["paymentaccountid"]
273
+ else
274
+ "#{response['transaction']['transactionid']}|#{amount}" if response['transaction']
275
+ end
276
+ end
277
+
278
+ def success_from(response)
279
+ response["expressresponsecode"] == "0"
280
+ end
281
+
282
+ def message_from(response)
283
+ response["expressresponsemessage"]
284
+ end
285
+
286
+ def split_authorization(authorization)
287
+ authorization.split("|")
288
+ end
289
+
290
+ def build_soap_request
291
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
292
+ xml['soap'].Envelope('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
293
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
294
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/') do
295
+
296
+ xml['soap'].Body do
297
+ yield(xml)
298
+ end
299
+ end
300
+ end
301
+
302
+ builder.to_xml
303
+ end
304
+
305
+ def payment_account_type(payment)
306
+ if payment.is_a?(Check)
307
+ payment_account_type = payment.account_type
308
+ else
309
+ payment_account_type = "CreditCard"
310
+ end
311
+ payment_account_type
312
+ end
313
+
314
+ def url(action)
315
+ if action == "PaymentAccountCreate"
316
+ url = (test? ? SERVICE_TEST_URL : SERVICE_LIVE_URL)
317
+ else
318
+ url = (test? ? test_url : live_url)
319
+ end
320
+ end
321
+
322
+ def interface(action)
323
+ return "transaction" if action != "PaymentAccountCreate"
324
+ return "services" if action == "PaymentAccountCreate"
325
+ end
326
+
327
+ def headers(action)
328
+ {
329
+ "Content-Type" => "text/xml; charset=utf-8",
330
+ "SOAPAction" => "https://#{interface(action)}.elementexpress.com/#{action}"
331
+ }
332
+ end
333
+ end
334
+ end
335
+ end