activemerchant 1.104.0 → 1.105.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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +22 -1
  3. data/README.md +1 -1
  4. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  5. data/lib/active_merchant/billing/gateways/balanced.rb +4 -4
  6. data/lib/active_merchant/billing/gateways/bambora_apac.rb +6 -10
  7. data/lib/active_merchant/billing/gateways/bpoint.rb +6 -4
  8. data/lib/active_merchant/billing/gateways/credorax.rb +22 -3
  9. data/lib/active_merchant/billing/gateways/decidir.rb +17 -1
  10. data/lib/active_merchant/billing/gateways/ebanx.rb +3 -2
  11. data/lib/active_merchant/billing/gateways/efsnet.rb +9 -9
  12. data/lib/active_merchant/billing/gateways/global_collect.rb +8 -8
  13. data/lib/active_merchant/billing/gateways/hps.rb +75 -25
  14. data/lib/active_merchant/billing/gateways/litle.rb +15 -15
  15. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +15 -2
  16. data/lib/active_merchant/billing/gateways/monei.rb +18 -18
  17. data/lib/active_merchant/billing/gateways/moneris.rb +21 -21
  18. data/lib/active_merchant/billing/gateways/openpay.rb +3 -3
  19. data/lib/active_merchant/billing/gateways/orbital.rb +51 -51
  20. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +3 -3
  21. data/lib/active_merchant/billing/gateways/paymentez.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +5 -5
  23. data/lib/active_merchant/billing/gateways/redsys.rb +2 -0
  24. data/lib/active_merchant/billing/gateways/secure_net.rb +3 -3
  25. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +6 -6
  26. data/lib/active_merchant/billing/gateways/stripe.rb +13 -4
  27. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +7 -14
  28. data/lib/active_merchant/billing/gateways/worldpay.rb +158 -69
  29. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +1 -1
  30. data/lib/active_merchant/version.rb +1 -1
  31. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9ceb4b2da9006abdfcab980341c407f7b718ae35a424fc1e597c3cf2b189271
4
- data.tar.gz: 19fe8973c00605d460cd56bcc8d0148cfa8ad7af9a33d07c9f2759da56dc5684
3
+ metadata.gz: ecb10bc188ad1b7d0286f0122d7c3643ba8c8b83aa2b3903ba2f582b1f43cad4
4
+ data.tar.gz: 5e28f570774addd9001a555b861757b0bf41aecdaa8c918d3f2926e32d41a7a8
5
5
  SHA512:
6
- metadata.gz: 94d123473e989145c5d9a34294718cc8913d231c72b415bd0398e88cfefdc81b1cd9070eaf14648be6c723de201785920de8479b8ef997454df194cfaa4f7734
7
- data.tar.gz: 9567e118dd21f0779d5a8bd228ab385f2378c338f838fe027ed6ad6a245a86362fd786d91aa53cbaa65b31d3817efdc8ca299ff84f44f182140ff43018cd6f7c
6
+ metadata.gz: da6fcbbd82d25fc8563ee47ec292d2fe276b445fdfe0b1194fdff5c9dddd8c091774f9abb95427721891bac3646e60d6018c2cbf50895c41c1a7aff772792d9b
7
+ data.tar.gz: d312d2bbdf0dc874a72519e8d4784c52bf0e663328ac4404ff6a1f92bdea1a9e9a50a0ae9732909275c4a177afce05370474cdef3fc0b02c5aa91ca0096164ff
data/CHANGELOG CHANGED
@@ -1,6 +1,25 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
- == HEAD
3
+ == Version 1.105.0 (Feb 20, 2020)
4
+ * Credorax: Fix `3ds_transtype` setting in post [chinhle23] #3531
5
+ * Bambora Apac: Send void amount in options [leila-alderman] #3532
6
+ * RuboCop: Fix Layout/IndentHash [leila-alderman] #3529
7
+ * Stripe: Add connected account support [Carrigan] #3535
8
+ * Redsys: Update scrub method to account for 3DS error responses [britth] #3534
9
+ * Authorize.Net: Pass `account_type` to `check` payment types [chinhle23] #3530
10
+ * Merchant Warrior: Send void amount in options [leila-alderman] #3525
11
+ * Stripe: Add support for `statement_descriptor_suffix` field [Carrigan] #3528
12
+ * Decidir: Add support for fraud_detection, site_id, and establishment_name [fatcatt316] #3527
13
+ * HPS: support eCheck [therufs] #3500
14
+ * EBANX: Add metadata information in post [miguelxpn] #3522
15
+ * Paypal: Fix OrderTotal elements in `add_payment_details` [chinhle23] #3517
16
+ * Worldpay: Add `riskData` GSF [fatcatt316] #3514
17
+ * EBANX: Fix `scrub` [chinhle23] #3521
18
+ * Worldpay: Remove unnecessary .tag! methods [leila-alderman] #3519
19
+ * BPoint: Remove amount from void requests [leila-alderman] #3518
20
+ * Authorize.net: Trim supported countries to AU, CA, US [fatcatt316] #3516
21
+ * Credorax: Allow optional 3DS 2 fields [jeremywrowe] #3515
22
+ * Stripe: Remove outdated 'customer options' deprecation [alexdunae] #3401
4
23
 
5
24
  == Version 1.104.0 (Jan 29, 2020)
6
25
  * Adyen: add `recurring_contract_type` GSF [therufs] #3460
@@ -41,6 +60,8 @@
41
60
  * Mercado Pago: Add taxes and net_amount gateway specific fields [carrigan] #3512
42
61
  * Moneris: use dedicated card_verification methods [alexdunae] #3428
43
62
  * Authorize.net: Trim down supported countries [fatcatt316] #3511
63
+ * Stripe: Add support for `statement_descriptor_suffix` field [carrigan] #3528
64
+ * Stripe: Add connected account support [carrigan] #3535
44
65
 
45
66
  == Version 1.103.0 (Dec 2, 2019)
46
67
  * Quickbooks: Mark transactions that returned `AuthorizationFailed` as failures [britth] #3447
data/README.md CHANGED
@@ -92,7 +92,7 @@ guide and [Standardized 3DS Fields](https://github.com/activemerchant/active_mer
92
92
  The [ActiveMerchant Wiki](https://github.com/activemerchant/active_merchant/wikis) contains a [table of features supported by each gateway](https://github.com/activemerchant/active_merchant/wiki/Gateway-Feature-Matrix).
93
93
 
94
94
  * [Authorize.Net CIM](http://www.authorize.net/) - US
95
- * [Authorize.Net](http://www.authorize.net/) - AD, AT, AU, BE, BG, CA, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GB, GI, GR, HU, IE, IT, LI, LU, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, TR, US, VA
95
+ * [Authorize.Net](http://www.authorize.net/) - AU, CA, US
96
96
  * [Axcess MS](http://www.axcessms.com/) - AD, AT, BE, BG, BR, CA, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HR, HU, IE, IL, IM, IS, IT, LI, LT, LU, LV, MC, MT, MX, NL, NO, PL, PT, RO, RU, SE, SI, SK, TR, US, VA
97
97
  * [Balanced](https://www.balancedpayments.com/) - US
98
98
  * [Bambora Asia-Pacific](http://www.bambora.com/) - AU, NZ
@@ -85,8 +85,8 @@ module ActiveMerchant
85
85
  AVS_REASON_CODES = %w(27 45)
86
86
 
87
87
  TRACKS = {
88
- 1 => /^%(?<format_code>.)(?<pan>[\d]{1,19}+)\^(?<name>.{2,26})\^(?<expiration>[\d]{0,4}|\^)(?<service_code>[\d]{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
89
- 2 => /\A;(?<pan>[\d]{1,19}+)=(?<expiration>[\d]{0,4}|=)(?<service_code>[\d]{0,3}|=)(?<discretionary_data>.*)\?\Z/
88
+ 1 => /^%(?<format_code>.)(?<pan>[\d]{1,19}+)\^(?<name>.{2,26})\^(?<expiration>[\d]{0,4}|\^)(?<service_code>[\d]{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
89
+ 2 => /\A;(?<pan>[\d]{1,19}+)=(?<expiration>[\d]{0,4}|=)(?<service_code>[\d]{0,3}|=)(?<discretionary_data>.*)\?\Z/
90
90
  }.freeze
91
91
 
92
92
  APPLE_PAY_DATA_DESCRIPTOR = 'COMMON.APPLE.INAPP.PAYMENT'
@@ -544,6 +544,7 @@ module ActiveMerchant
544
544
  def add_check(xml, check)
545
545
  xml.payment do
546
546
  xml.bankAccount do
547
+ xml.accountType(check.account_type)
547
548
  xml.routingNumber(check.routing_number)
548
549
  xml.accountNumber(check.account_number)
549
550
  xml.nameOnAccount(truncate(check.name, 22))
@@ -251,10 +251,10 @@ module ActiveMerchant #:nodoc:
251
251
  )
252
252
 
253
253
  {
254
- 'Authorization' => 'Basic ' + Base64.encode64(@options[:login].to_s + ':').strip,
255
- 'User-Agent' => "Balanced/v1.1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
256
- 'Accept' => 'application/vnd.api+json;revision=1.1',
257
- 'X-Balanced-User-Agent' => @@ua,
254
+ 'Authorization' => 'Basic ' + Base64.encode64(@options[:login].to_s + ':').strip,
255
+ 'User-Agent' => "Balanced/v1.1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
256
+ 'Accept' => 'application/vnd.api+json;revision=1.1',
257
+ 'X-Balanced-User-Agent' => @@ua,
258
258
  }
259
259
  end
260
260
  end
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
30
30
  commit('SubmitSinglePayment') do |xml|
31
31
  xml.Transaction do
32
32
  xml.CustRef options[:order_id]
33
- add_amount(xml, money)
33
+ xml.Amount amount(money)
34
34
  xml.TrnType '1'
35
35
  add_payment(xml, payment)
36
36
  add_credentials(xml, options)
@@ -43,7 +43,7 @@ module ActiveMerchant #:nodoc:
43
43
  commit('SubmitSinglePayment') do |xml|
44
44
  xml.Transaction do
45
45
  xml.CustRef options[:order_id]
46
- add_amount(xml, money)
46
+ xml.Amount amount(money)
47
47
  xml.TrnType '2'
48
48
  add_payment(xml, payment)
49
49
  add_credentials(xml, options)
@@ -56,7 +56,7 @@ module ActiveMerchant #:nodoc:
56
56
  commit('SubmitSingleCapture') do |xml|
57
57
  xml.Capture do
58
58
  xml.Receipt authorization
59
- add_amount(xml, money)
59
+ xml.Amount amount(money)
60
60
  add_credentials(xml, options)
61
61
  end
62
62
  end
@@ -66,17 +66,17 @@ module ActiveMerchant #:nodoc:
66
66
  commit('SubmitSingleRefund') do |xml|
67
67
  xml.Refund do
68
68
  xml.Receipt authorization
69
- add_amount(xml, money)
69
+ xml.Amount amount(money)
70
70
  add_credentials(xml, options)
71
71
  end
72
72
  end
73
73
  end
74
74
 
75
- def void(money, authorization, options={})
75
+ def void(authorization, options={})
76
76
  commit('SubmitSingleVoid') do |xml|
77
77
  xml.Void do
78
78
  xml.Receipt authorization
79
- add_amount(xml, money)
79
+ xml.Amount amount(options[:amount])
80
80
  add_credentials(xml, options)
81
81
  end
82
82
  end
@@ -116,10 +116,6 @@ module ActiveMerchant #:nodoc:
116
116
  end
117
117
  end
118
118
 
119
- def add_amount(xml, money)
120
- xml.Amount amount(money)
121
- end
122
-
123
119
  def add_payment(xml, payment)
124
120
  if payment.is_a?(String)
125
121
  add_token(xml, payment)
@@ -61,10 +61,10 @@ module ActiveMerchant #:nodoc:
61
61
  commit(request_body)
62
62
  end
63
63
 
64
- def void(amount, authorization, options={})
64
+ def void(authorization, options={})
65
65
  request_body = soap_request do |xml|
66
66
  process_payment(xml) do |payment_xml|
67
- add_void(payment_xml, amount, authorization, options)
67
+ add_void(payment_xml, authorization, options)
68
68
  end
69
69
  end
70
70
  commit(request_body)
@@ -73,7 +73,7 @@ module ActiveMerchant #:nodoc:
73
73
  def verify(credit_card, options={})
74
74
  MultiResponse.run(:use_first_response) do |r|
75
75
  r.process { authorize(100, credit_card, options) }
76
- r.process(:ignore_result) { void(100, r.authorization, options) }
76
+ r.process(:ignore_result) { void(r.authorization, options.merge(amount: 100)) }
77
77
  end
78
78
  end
79
79
 
@@ -154,7 +154,9 @@ module ActiveMerchant #:nodoc:
154
154
  transaction_number_xml(xml, transaction_number)
155
155
  end
156
156
 
157
- def add_void(xml, amount, transaction_number, options)
157
+ def add_void(xml, transaction_number, options)
158
+ # The amount parameter is required for void requests on BPoint.
159
+ amount = options[:amount]
158
160
  payment_xml(xml, 'REVERSAL', amount, options)
159
161
  transaction_number_xml(xml, transaction_number)
160
162
  end
@@ -132,6 +132,7 @@ module ActiveMerchant #:nodoc:
132
132
  add_customer_data(post, options)
133
133
  add_email(post, options)
134
134
  add_3d_secure(post, options)
135
+ add_3ds_2_optional_fields(post, options)
135
136
  add_echo(post, options)
136
137
  add_submerchant_id(post, options)
137
138
  add_stored_credential(post, options)
@@ -147,6 +148,7 @@ module ActiveMerchant #:nodoc:
147
148
  add_customer_data(post, options)
148
149
  add_email(post, options)
149
150
  add_3d_secure(post, options)
151
+ add_3ds_2_optional_fields(post, options)
150
152
  add_echo(post, options)
151
153
  add_submerchant_id(post, options)
152
154
  add_stored_credential(post, options)
@@ -228,6 +230,21 @@ module ActiveMerchant #:nodoc:
228
230
  gsub(%r((b5=)\d+), '\1[FILTERED]')
229
231
  end
230
232
 
233
+ def add_3ds_2_optional_fields(post, options)
234
+ three_ds = options[:three_ds_2] || {}
235
+
236
+ if three_ds.has_key?(:optional)
237
+ three_ds[:optional].each do |key, value|
238
+ normalized_value = normalize(value)
239
+ next if normalized_value.nil?
240
+
241
+ post[key] = normalized_value unless post[key]
242
+ end
243
+ end
244
+
245
+ post
246
+ end
247
+
231
248
  private
232
249
 
233
250
  def add_invoice(post, money, options)
@@ -308,7 +325,7 @@ module ActiveMerchant #:nodoc:
308
325
  post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
309
326
  post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
310
327
  post[:d5] = browser_info[:user_agent]
311
- post[:'3ds_transtype'] = options[:transaction_type] || '01'
328
+ post[:'3ds_transtype'] = options[:three_ds_transtype] || '01'
312
329
  post[:'3ds_browsertz'] = browser_info[:timezone]
313
330
  post[:'3ds_browserscreenwidth'] = browser_info[:width]
314
331
  post[:'3ds_browserscreenheight'] = browser_info[:height]
@@ -405,8 +422,10 @@ module ActiveMerchant #:nodoc:
405
422
 
406
423
  def sign_request(params)
407
424
  params = params.sort
408
- params.each { |param| param[1].gsub!(/[<>()\\]/, ' ') }
409
- values = params.map { |param| param[1].strip }
425
+ values = params.map do |param|
426
+ value = param[1].gsub(/[<>()\\]/, ' ')
427
+ value.strip
428
+ end
410
429
  Digest::MD5.hexdigest(values.join + @options[:cipher_key])
411
430
  end
412
431
 
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
7
7
  self.supported_countries = ['AR']
8
8
  self.money_format = :cents
9
9
  self.default_currency = 'ARS'
10
- self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :naranja, :cabal]
10
+ self.supported_cardtypes = %i[visa master american_express diners_club naranja cabal]
11
11
 
12
12
  self.homepage_url = 'http://www.decidir.com'
13
13
  self.display_name = 'Decidir'
@@ -113,6 +113,9 @@ module ActiveMerchant #:nodoc:
113
113
  post[:installments] = options[:installments] ? options[:installments].to_i : 1
114
114
  post[:description] = options[:description] if options[:description]
115
115
  post[:email] = options[:email] if options[:email]
116
+ post[:establishment_name] = options[:establishment_name] if options[:establishment_name]
117
+ post[:fraud_detection] = add_fraud_detection(options[:fraud_detection]) if options[:fraud_detection].present?
118
+ post[:site_id] = options[:site_id] if options[:site_id]
116
119
  post[:sub_payments] = []
117
120
 
118
121
  add_invoice(post, money, options)
@@ -176,6 +179,19 @@ module ActiveMerchant #:nodoc:
176
179
  post[:card_data] = card_data
177
180
  end
178
181
 
182
+ def add_fraud_detection(options = {})
183
+ {}.tap do |hsh|
184
+ hsh[:send_to_cs] = options[:send_to_cs] if valid_fraud_detection_option?(options[:send_to_cs]) # true/false
185
+ hsh[:channel] = options[:channel] if valid_fraud_detection_option?(options[:channel])
186
+ hsh[:dispatch_method] = options[:dispatch_method] if valid_fraud_detection_option?(options[:dispatch_method])
187
+ end
188
+ end
189
+
190
+ # Avoid sending fields with empty or null when not populated.
191
+ def valid_fraud_detection_option?(val)
192
+ !val.nil? && val != ''
193
+ end
194
+
179
195
  def headers(options = {})
180
196
  {
181
197
  'apikey' => @options[:api_key],
@@ -120,7 +120,7 @@ module ActiveMerchant #:nodoc:
120
120
 
121
121
  def scrub(transcript)
122
122
  transcript.
123
- gsub(/(integration_key\\?":\\?")(\d*)/, '\1[FILTERED]').
123
+ gsub(/(integration_key\\?":\\?")(\w*)/, '\1[FILTERED]').
124
124
  gsub(/(card_number\\?":\\?")(\d*)/, '\1[FILTERED]').
125
125
  gsub(/(card_cvv\\?":\\?")(\d*)/, '\1[FILTERED]')
126
126
  end
@@ -201,6 +201,7 @@ module ActiveMerchant #:nodoc:
201
201
 
202
202
  def add_additional_data(post, options)
203
203
  post[:device_id] = options[:device_id] if options[:device_id]
204
+ post[:metadata] = options[:metadata] if options[:metadata]
204
205
  end
205
206
 
206
207
  def parse(body)
@@ -209,7 +210,7 @@ module ActiveMerchant #:nodoc:
209
210
 
210
211
  def commit(action, parameters)
211
212
  url = url_for((test? ? test_url : live_url), action, parameters)
212
- response = parse(ssl_request(HTTP_METHOD[action], url, post_data(action, parameters), {}))
213
+ response = parse(ssl_request(HTTP_METHOD[action], url, post_data(action, parameters), {'x-ebanx-client-user-agent': "ActiveMerchant/#{ActiveMerchant::VERSION}"}))
213
214
 
214
215
  success = success_from(action, response)
215
216
 
@@ -201,15 +201,15 @@ module ActiveMerchant #:nodoc:
201
201
  CREDIT_CARD_FIELDS = %w(AuthorizationNumber ClientIpAddress BillingAddress BillingCity BillingState BillingPostalCode BillingCountry BillingName CardVerificationValue ExpirationMonth ExpirationYear ReferenceNumber TransactionAmount AccountNumber)
202
202
 
203
203
  ACTIONS = {
204
- :credit_card_authorize => CREDIT_CARD_FIELDS,
205
- :credit_card_charge => CREDIT_CARD_FIELDS,
206
- :credit_card_voice_authorize => CREDIT_CARD_FIELDS,
207
- :credit_card_capture => CREDIT_CARD_FIELDS,
208
- :credit_card_credit => CREDIT_CARD_FIELDS + ['OriginalTransactionAmount'],
209
- :credit_card_refund => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
210
- :void_transaction => %w(ReferenceNumber TransactionID),
211
- :credit_card_settle => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
212
- :system_check => %w(SystemCheck),
204
+ :credit_card_authorize => CREDIT_CARD_FIELDS,
205
+ :credit_card_charge => CREDIT_CARD_FIELDS,
206
+ :credit_card_voice_authorize => CREDIT_CARD_FIELDS,
207
+ :credit_card_capture => CREDIT_CARD_FIELDS,
208
+ :credit_card_credit => CREDIT_CARD_FIELDS + ['OriginalTransactionAmount'],
209
+ :credit_card_refund => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
210
+ :void_transaction => %w(ReferenceNumber TransactionID),
211
+ :credit_card_settle => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
212
+ :system_check => %w(SystemCheck),
213
213
  }
214
214
  end
215
215
  end
@@ -156,16 +156,16 @@ module ActiveMerchant #:nodoc:
156
156
  pre_authorization = options[:pre_authorization] ? 'PRE_AUTHORIZATION' : 'FINAL_AUTHORIZATION'
157
157
 
158
158
  post['cardPaymentMethodSpecificInput'] = {
159
- 'paymentProductId' => BRAND_MAP[payment.brand],
160
- 'skipAuthentication' => 'true', # refers to 3DSecure
161
- 'skipFraudService' => 'true',
162
- 'authorizationMode' => pre_authorization
159
+ 'paymentProductId' => BRAND_MAP[payment.brand],
160
+ 'skipAuthentication' => 'true', # refers to 3DSecure
161
+ 'skipFraudService' => 'true',
162
+ 'authorizationMode' => pre_authorization
163
163
  }
164
164
  post['cardPaymentMethodSpecificInput']['card'] = {
165
- 'cvv' => payment.verification_value,
166
- 'cardNumber' => payment.number,
167
- 'expiryDate' => expirydate,
168
- 'cardholderName' => payment.name
165
+ 'cvv' => payment.verification_value,
166
+ 'cardNumber' => payment.number,
167
+ 'expiryDate' => expirydate,
168
+ 'cardholderName' => payment.name
169
169
  }
170
170
  end
171
171
 
@@ -32,10 +32,10 @@ module ActiveMerchant #:nodoc:
32
32
  commit('CreditAuth') do |xml|
33
33
  add_amount(xml, money)
34
34
  add_allow_dup(xml)
35
- add_customer_data(xml, card_or_token, options)
35
+ add_card_or_token_customer_data(xml, card_or_token, options)
36
36
  add_details(xml, options)
37
37
  add_descriptor_name(xml, options)
38
- add_payment(xml, card_or_token, options)
38
+ add_card_or_token_payment(xml, card_or_token, options)
39
39
  add_three_d_secure(xml, card_or_token, options)
40
40
  end
41
41
  end
@@ -47,15 +47,11 @@ module ActiveMerchant #:nodoc:
47
47
  end
48
48
  end
49
49
 
50
- def purchase(money, card_or_token, options={})
51
- commit('CreditSale') do |xml|
52
- add_amount(xml, money)
53
- add_allow_dup(xml)
54
- add_customer_data(xml, card_or_token, options)
55
- add_details(xml, options)
56
- add_descriptor_name(xml, options)
57
- add_payment(xml, card_or_token, options)
58
- add_three_d_secure(xml, card_or_token, options)
50
+ def purchase(money, payment_method, options={})
51
+ if payment_method.is_a?(Check)
52
+ commit_check_sale(money, payment_method, options)
53
+ else
54
+ commit_credit_sale(money, payment_method, options)
59
55
  end
60
56
  end
61
57
 
@@ -64,22 +60,28 @@ module ActiveMerchant #:nodoc:
64
60
  add_amount(xml, money)
65
61
  add_allow_dup(xml)
66
62
  add_reference(xml, transaction_id)
67
- add_customer_data(xml, transaction_id, options)
63
+ add_card_or_token_customer_data(xml, transaction_id, options)
68
64
  add_details(xml, options)
69
65
  end
70
66
  end
71
67
 
72
68
  def verify(card_or_token, options={})
73
69
  commit('CreditAccountVerify') do |xml|
74
- add_customer_data(xml, card_or_token, options)
70
+ add_card_or_token_customer_data(xml, card_or_token, options)
75
71
  add_descriptor_name(xml, options)
76
- add_payment(xml, card_or_token, options)
72
+ add_card_or_token_payment(xml, card_or_token, options)
77
73
  end
78
74
  end
79
75
 
80
76
  def void(transaction_id, options={})
81
- commit('CreditVoid') do |xml|
82
- add_reference(xml, transaction_id)
77
+ if options[:check_void]
78
+ commit('CheckVoid') do |xml|
79
+ add_reference(xml, transaction_id)
80
+ end
81
+ else
82
+ commit('CreditVoid') do |xml|
83
+ add_reference(xml, transaction_id)
84
+ end
83
85
  end
84
86
  end
85
87
 
@@ -92,11 +94,35 @@ module ActiveMerchant #:nodoc:
92
94
  gsub(%r((<hps:CardNbr>)[^<]*(<\/hps:CardNbr>))i, '\1[FILTERED]\2').
93
95
  gsub(%r((<hps:CVV2>)[^<]*(<\/hps:CVV2>))i, '\1[FILTERED]\2').
94
96
  gsub(%r((<hps:SecretAPIKey>)[^<]*(<\/hps:SecretAPIKey>))i, '\1[FILTERED]\2').
95
- gsub(%r((<hps:PaymentData>)[^<]*(<\/hps:PaymentData>))i, '\1[FILTERED]\2')
97
+ gsub(%r((<hps:PaymentData>)[^<]*(<\/hps:PaymentData>))i, '\1[FILTERED]\2').
98
+ gsub(%r((<hps:RoutingNumber>)[^<]*(<\/hps:RoutingNumber>))i, '\1[FILTERED]\2').
99
+ gsub(%r((<hps:AccountNumber>)[^<]*(<\/hps:AccountNumber>))i, '\1[FILTERED]\2')
96
100
  end
97
101
 
98
102
  private
99
103
 
104
+ def commit_check_sale(money, check, options)
105
+ commit('CheckSale') do |xml|
106
+ add_check_payment(xml, check, options)
107
+ add_amount(xml, money)
108
+ add_sec_code(xml, options)
109
+ add_check_customer_data(xml, check, options)
110
+ add_details(xml, options)
111
+ end
112
+ end
113
+
114
+ def commit_credit_sale(money, card_or_token, options)
115
+ commit('CreditSale') do |xml|
116
+ add_amount(xml, money)
117
+ add_allow_dup(xml)
118
+ add_card_or_token_customer_data(xml, card_or_token, options)
119
+ add_details(xml, options)
120
+ add_descriptor_name(xml, options)
121
+ add_card_or_token_payment(xml, card_or_token, options)
122
+ add_three_d_secure(xml, card_or_token, options)
123
+ end
124
+ end
125
+
100
126
  def add_reference(xml, transaction_id)
101
127
  xml.hps :GatewayTxnId, transaction_id
102
128
  end
@@ -105,7 +131,7 @@ module ActiveMerchant #:nodoc:
105
131
  xml.hps :Amt, amount(money) if money
106
132
  end
107
133
 
108
- def add_customer_data(xml, credit_card, options)
134
+ def add_card_or_token_customer_data(xml, credit_card, options)
109
135
  xml.hps :CardHolderData do
110
136
  if credit_card.respond_to?(:number)
111
137
  xml.hps :CardHolderFirstName, credit_card.first_name if credit_card.first_name
@@ -124,7 +150,15 @@ module ActiveMerchant #:nodoc:
124
150
  end
125
151
  end
126
152
 
127
- def add_payment(xml, card_or_token, options)
153
+ def add_check_customer_data(xml, check, options)
154
+ xml.hps :ConsumerInfo do
155
+ xml.hps :FirstName, check.first_name
156
+ xml.hps :LastName, check.last_name
157
+ xml.hps :CheckName, options[:company_name] if options[:company_name]
158
+ end
159
+ end
160
+
161
+ def add_card_or_token_payment(xml, card_or_token, options)
128
162
  xml.hps :CardData do
129
163
  if card_or_token.respond_to?(:number)
130
164
  if card_or_token.track_data
@@ -159,6 +193,17 @@ module ActiveMerchant #:nodoc:
159
193
  end
160
194
  end
161
195
 
196
+ def add_check_payment(xml, check, options)
197
+ xml.hps :CheckAction, 'SALE'
198
+ xml.hps :AccountInfo do
199
+ xml.hps :RoutingNumber, check.routing_number
200
+ xml.hps :AccountNumber, check.account_number
201
+ xml.hps :CheckNumber, check.number
202
+ xml.hps :AccountType, check.account_type.upcase
203
+ end
204
+ xml.hps :CheckType, check.account_holder_type.upcase
205
+ end
206
+
162
207
  def add_details(xml, options)
163
208
  xml.hps :AdditionalTxnFields do
164
209
  xml.hps :Description, options[:description] if options[:description]
@@ -167,6 +212,10 @@ module ActiveMerchant #:nodoc:
167
212
  end
168
213
  end
169
214
 
215
+ def add_sec_code(xml, options)
216
+ xml.hps :SECCode, options[:sec_code] || 'WEB'
217
+ end
218
+
170
219
  def add_allow_dup(xml)
171
220
  xml.hps :AllowDup, 'Y'
172
221
  end
@@ -214,8 +263,8 @@ module ActiveMerchant #:nodoc:
214
263
  xml = Builder::XmlMarkup.new(encoding: 'UTF-8')
215
264
  xml.instruct!(:xml, encoding: 'UTF-8')
216
265
  xml.SOAP :Envelope, {
217
- 'xmlns:SOAP' => 'http://schemas.xmlsoap.org/soap/envelope/',
218
- 'xmlns:hps' => 'http://Hps.Exchange.PosGateway'
266
+ 'xmlns:SOAP' => 'http://schemas.xmlsoap.org/soap/envelope/',
267
+ 'xmlns:hps' => 'http://Hps.Exchange.PosGateway'
219
268
  } do
220
269
  xml.SOAP :Body do
221
270
  xml.hps :PosRequest do
@@ -296,10 +345,11 @@ module ActiveMerchant #:nodoc:
296
345
  )
297
346
  end
298
347
 
348
+ SUCCESSFUL_RESPONSE_CODES = %w(0 00 85)
299
349
  def successful?(response)
300
350
  (
301
351
  (response['GatewayRspCode'] == '0') &&
302
- ((response['RspCode'] || '00') == '00' || response['RspCode'] == '85')
352
+ ((SUCCESSFUL_RESPONSE_CODES.include? response['RspCode']) || !response['RspCode'])
303
353
  )
304
354
  end
305
355
 
@@ -307,10 +357,10 @@ module ActiveMerchant #:nodoc:
307
357
  if response['Fault']
308
358
  response['Fault']
309
359
  elsif response['GatewayRspCode'] == '0'
310
- if response['RspCode'] != '00' && response['RspCode'] != '85'
311
- issuer_message(response['RspCode'])
312
- else
360
+ if SUCCESSFUL_RESPONSE_CODES.include? response['RspCode']
313
361
  response['GatewayRspMsg']
362
+ else
363
+ issuer_message(response['RspCode'])
314
364
  end
315
365
  else
316
366
  (GATEWAY_MESSAGES[response['GatewayRspCode']] || response['GatewayRspMsg'])