activemerchant 1.104.0 → 1.105.0

Sign up to get free protection for your applications and to get access to all the features.
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'])