activemerchant 1.125.0 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +316 -0
  3. data/lib/active_merchant/billing/check.rb +40 -8
  4. data/lib/active_merchant/billing/credit_card.rb +28 -1
  5. data/lib/active_merchant/billing/credit_card_methods.rb +91 -23
  6. data/lib/active_merchant/billing/gateway.rb +2 -1
  7. data/lib/active_merchant/billing/gateways/adyen.rb +74 -12
  8. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  9. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
  12. data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +53 -22
  15. data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
  16. data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
  17. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
  18. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  19. data/lib/active_merchant/billing/gateways/braintree_blue.rb +151 -32
  20. data/lib/active_merchant/billing/gateways/card_connect.rb +28 -10
  21. data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
  22. data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
  23. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  24. data/lib/active_merchant/billing/gateways/credorax.rb +56 -26
  25. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  26. data/lib/active_merchant/billing/gateways/cyber_source.rb +112 -58
  27. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  28. data/lib/active_merchant/billing/gateways/d_local.rb +93 -5
  29. data/lib/active_merchant/billing/gateways/decidir.rb +32 -5
  30. data/lib/active_merchant/billing/gateways/decidir_plus.rb +185 -14
  31. data/lib/active_merchant/billing/gateways/ebanx.rb +39 -26
  32. data/lib/active_merchant/billing/gateways/element.rb +21 -1
  33. data/lib/active_merchant/billing/gateways/global_collect.rb +98 -37
  34. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  35. data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
  36. data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
  37. data/lib/active_merchant/billing/gateways/litle.rb +118 -6
  38. data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
  39. data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
  40. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
  41. data/lib/active_merchant/billing/gateways/monei.rb +2 -0
  42. data/lib/active_merchant/billing/gateways/moneris.rb +55 -13
  43. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
  44. data/lib/active_merchant/billing/gateways/nmi.rb +12 -7
  45. data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
  46. data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
  47. data/lib/active_merchant/billing/gateways/orbital.rb +378 -335
  48. data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
  49. data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
  50. data/lib/active_merchant/billing/gateways/payflow.rb +62 -0
  51. data/lib/active_merchant/billing/gateways/paymentez.rb +44 -13
  52. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  53. data/lib/active_merchant/billing/gateways/paysafe.rb +37 -29
  54. data/lib/active_merchant/billing/gateways/payu_latam.rb +28 -15
  55. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  56. data/lib/active_merchant/billing/gateways/priority.rb +185 -140
  57. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  58. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  59. data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
  60. data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -4
  61. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  62. data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
  63. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  64. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  65. data/lib/active_merchant/billing/gateways/stripe.rb +25 -3
  66. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +155 -70
  67. data/lib/active_merchant/billing/gateways/tns.rb +2 -5
  68. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  69. data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
  70. data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
  71. data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
  72. data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
  73. data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
  74. data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
  75. data/lib/active_merchant/billing/response.rb +15 -1
  76. data/lib/active_merchant/connection.rb +0 -2
  77. data/lib/active_merchant/country.rb +1 -0
  78. data/lib/active_merchant/errors.rb +4 -1
  79. data/lib/active_merchant/version.rb +1 -1
  80. metadata +28 -3
@@ -218,14 +218,7 @@ module ActiveMerchant
218
218
 
219
219
  def base_url
220
220
  if test?
221
- case @options[:region]
222
- when 'asia_pacific'
223
- test_ap_url
224
- when 'europe'
225
- test_eu_url
226
- when 'north_america', nil
227
- test_na_url
228
- end
221
+ test_url
229
222
  else
230
223
  case @options[:region]
231
224
  when 'asia_pacific'
@@ -61,6 +61,10 @@ module ActiveMerchant #:nodoc:
61
61
  end
62
62
  end
63
63
 
64
+ def inquire(authorization, options = {})
65
+ commit('inquire', inquire_path(authorization, options), {})
66
+ end
67
+
64
68
  def supports_scrubbing?
65
69
  true
66
70
  end
@@ -261,6 +265,10 @@ module ActiveMerchant #:nodoc:
261
265
  def commit(action, path, parameters)
262
266
  if %w[capture void].include?(action)
263
267
  response = parse(ssl_request(:put, url(path), post_data(parameters), headers))
268
+ elsif action == 'inquire'
269
+ response = parse(ssl_get(url(path), headers))
270
+
271
+ response = response[0]['results'][0] if response.is_a?(Array)
264
272
  else
265
273
  response = parse(ssl_post(url(path), post_data(parameters), headers(parameters)))
266
274
  end
@@ -295,6 +303,15 @@ module ActiveMerchant #:nodoc:
295
303
  parameters.clone.tap { |p| p.delete(:device_id) }.to_json
296
304
  end
297
305
 
306
+ def inquire_path(authorization, options)
307
+ if authorization
308
+ authorization, = authorization.split('|')
309
+ "payments/#{authorization}"
310
+ else
311
+ "payments/search?external_reference=#{options[:order_id] || options[:external_reference]}"
312
+ end
313
+ end
314
+
298
315
  def error_code_from(action, response)
299
316
  unless success_from(action, response)
300
317
  if cause = response['cause']
@@ -18,6 +18,8 @@ module ActiveMerchant #:nodoc:
18
18
  # The name of the gateway
19
19
  self.display_name = 'Merchant e-Solutions'
20
20
 
21
+ SUCCESS_RESPONSE_CODES = %w(000 085)
22
+
21
23
  def initialize(options = {})
22
24
  requires!(options, :login, :password)
23
25
  super
@@ -25,23 +27,21 @@ module ActiveMerchant #:nodoc:
25
27
 
26
28
  def authorize(money, creditcard_or_card_id, options = {})
27
29
  post = {}
28
- post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
29
- post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind)
30
30
  add_invoice(post, options)
31
31
  add_payment_source(post, creditcard_or_card_id, options)
32
32
  add_address(post, options)
33
33
  add_3dsecure_params(post, options)
34
+ add_stored_credentials(post, options)
34
35
  commit('P', money, post)
35
36
  end
36
37
 
37
38
  def purchase(money, creditcard_or_card_id, options = {})
38
39
  post = {}
39
- post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
40
- post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind)
41
40
  add_invoice(post, options)
42
41
  add_payment_source(post, creditcard_or_card_id, options)
43
42
  add_address(post, options)
44
43
  add_3dsecure_params(post, options)
44
+ add_stored_credentials(post, options)
45
45
  commit('D', money, post)
46
46
  end
47
47
 
@@ -55,10 +55,10 @@ module ActiveMerchant #:nodoc:
55
55
  end
56
56
 
57
57
  def store(creditcard, options = {})
58
- post = {}
59
- post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
60
- add_creditcard(post, creditcard, options)
61
- commit('T', nil, post)
58
+ MultiResponse.run do |r|
59
+ r.process { temporary_store(creditcard, options) }
60
+ r.process { verify(r.authorization, { store_card: 'y' }) }
61
+ end
62
62
  end
63
63
 
64
64
  def unstore(card_id, options = {})
@@ -94,6 +94,13 @@ module ActiveMerchant #:nodoc:
94
94
  commit('V', nil, options.merge(post))
95
95
  end
96
96
 
97
+ def verify(credit_card, options = {})
98
+ post = {}
99
+ post[:store_card] = options[:store_card] if options[:store_card]
100
+ add_payment_source(post, credit_card, options)
101
+ commit('A', 0, post)
102
+ end
103
+
97
104
  def supports_scrubbing?
98
105
  true
99
106
  end
@@ -107,6 +114,13 @@ module ActiveMerchant #:nodoc:
107
114
 
108
115
  private
109
116
 
117
+ def temporary_store(creditcard, options = {})
118
+ post = {}
119
+ post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
120
+ add_creditcard(post, creditcard, options)
121
+ commit('T', nil, post)
122
+ end
123
+
110
124
  def add_address(post, options)
111
125
  if address = options[:billing_address] || options[:address]
112
126
  post[:cardholder_street_address] = address[:address1].to_s.gsub(/[^\w.]/, '+')
@@ -145,6 +159,16 @@ module ActiveMerchant #:nodoc:
145
159
  post[:ucaf_auth_data] = options[:ucaf_auth_data] unless empty?(options[:ucaf_auth_data])
146
160
  end
147
161
 
162
+ def add_stored_credentials(post, options)
163
+ post[:client_reference_number] = options[:client_reference_number] if options[:client_reference_number]
164
+ post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options[:moto_ecommerce_ind]
165
+ post[:recurring_pmt_num] = options[:recurring_pmt_num] if options[:recurring_pmt_num]
166
+ post[:recurring_pmt_count] = options[:recurring_pmt_count] if options[:recurring_pmt_count]
167
+ post[:card_on_file] = options[:card_on_file] if options[:card_on_file]
168
+ post[:cit_mit_indicator] = options[:cit_mit_indicator] if options[:cit_mit_indicator]
169
+ post[:account_data_source] = options[:account_data_source] if options[:account_data_source]
170
+ end
171
+
148
172
  def parse(body)
149
173
  results = {}
150
174
  body.split(/&/).each do |pair|
@@ -165,13 +189,23 @@ module ActiveMerchant #:nodoc:
165
189
  { 'error_code' => '404', 'auth_response_text' => e.to_s }
166
190
  end
167
191
 
168
- Response.new(response['error_code'] == '000', message_from(response), response,
169
- authorization: response['transaction_id'],
192
+ Response.new(success_from(response), message_from(response), response,
193
+ authorization: authorization_from(response),
170
194
  test: test?,
171
195
  cvv_result: response['cvv2_result'],
172
196
  avs_result: { code: response['avs_result'] })
173
197
  end
174
198
 
199
+ def authorization_from(response)
200
+ return response['card_id'] if response['card_id']
201
+
202
+ response['transaction_id']
203
+ end
204
+
205
+ def success_from(response)
206
+ SUCCESS_RESPONSE_CODES.include?(response['error_code'])
207
+ end
208
+
175
209
  def message_from(response)
176
210
  if response['error_code'] == '000'
177
211
  'This transaction has been approved'
@@ -201,6 +201,7 @@ module ActiveMerchant #:nodoc:
201
201
  request[:paymentMethod][:card][:expMonth] = format(payment_method.month, :two_digits)
202
202
  request[:paymentMethod][:card][:expYear] = format(payment_method.year, :two_digits)
203
203
  request[:paymentMethod][:card][:cvc] = payment_method.verification_value.to_s
204
+ request[:paymentMethod][:card][:cardholderName] = payment_method.name
204
205
  end
205
206
  end
206
207
 
@@ -293,6 +294,7 @@ module ActiveMerchant #:nodoc:
293
294
  def add_browser_info(request, options)
294
295
  request[:sessionDetails][:ip] = options[:ip] if options[:ip]
295
296
  request[:sessionDetails][:userAgent] = options[:user_agent] if options[:user_agent]
297
+ request[:sessionDetails][:lang] = options[:lang] if options[:lang]
296
298
  end
297
299
 
298
300
  # Private: Parse JSON response from Monei servers
@@ -9,6 +9,8 @@ module ActiveMerchant #:nodoc:
9
9
  # Response Values", available at Moneris' {eSelect Plus Documentation
10
10
  # Centre}[https://www3.moneris.com/connect/en/documents/index.html].
11
11
  class MonerisGateway < Gateway
12
+ WALLETS = %w(APP GPP)
13
+
12
14
  self.test_url = 'https://esqa.moneris.com/gateway2/servlet/MpgRequest'
13
15
  self.live_url = 'https://www3.moneris.com/gateway2/servlet/MpgRequest'
14
16
 
@@ -47,18 +49,19 @@ module ActiveMerchant #:nodoc:
47
49
  post = {}
48
50
  add_payment_source(post, creditcard_or_datakey, options)
49
51
  post[:amount] = amount(money)
50
- post[:order_id] = options[:order_id]
52
+ post[:order_id] = format_order_id(post[:wallet_indicator], options[:order_id])
51
53
  post[:address] = options[:billing_address] || options[:address]
52
54
  post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
55
+ add_external_mpi_fields(post, options)
53
56
  add_stored_credential(post, options)
54
- action = if post[:cavv]
57
+ action = if post[:cavv] || options[:three_d_secure]
55
58
  'cavv_preauth'
56
59
  elsif post[:data_key].blank?
57
60
  'preauth'
58
61
  else
59
62
  'res_preauth_cc'
60
63
  end
61
- commit(action, post)
64
+ commit(action, post, options)
62
65
  end
63
66
 
64
67
  # This action verifies funding on a customer's card and readies them for
@@ -70,18 +73,19 @@ module ActiveMerchant #:nodoc:
70
73
  post = {}
71
74
  add_payment_source(post, creditcard_or_datakey, options)
72
75
  post[:amount] = amount(money)
73
- post[:order_id] = options[:order_id]
76
+ post[:order_id] = format_order_id(post[:wallet_indicator], options[:order_id])
74
77
  post[:address] = options[:billing_address] || options[:address]
75
78
  post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
79
+ add_external_mpi_fields(post, options)
76
80
  add_stored_credential(post, options)
77
- action = if post[:cavv]
81
+ action = if post[:cavv] || options[:three_d_secure]
78
82
  'cavv_purchase'
79
83
  elsif post[:data_key].blank?
80
84
  'purchase'
81
85
  else
82
86
  'res_purchase_cc'
83
87
  end
84
- commit(action, post)
88
+ commit(action, post, options)
85
89
  end
86
90
 
87
91
  # This method retrieves locked funds from a customer's account (from a
@@ -203,6 +207,21 @@ module ActiveMerchant #:nodoc:
203
207
  sprintf('%.4i', creditcard.year)[-2..-1] + sprintf('%.2i', creditcard.month)
204
208
  end
205
209
 
210
+ def add_external_mpi_fields(post, options)
211
+ # See these pages:
212
+ # https://developer.moneris.com/livedemo/3ds2/cavv_purchase/tool/php
213
+ # https://developer.moneris.com/livedemo/3ds2/cavv_preauth/guide/php
214
+ return unless options[:three_d_secure]
215
+
216
+ three_d_secure_options = options[:three_d_secure]
217
+
218
+ post[:threeds_version] = three_d_secure_options[:version]
219
+ post[:crypt_type] = three_d_secure_options[:eci]
220
+ post[:cavv] = three_d_secure_options[:cavv]
221
+ post[:threeds_server_trans_id] = three_d_secure_options[:three_ds_server_trans_id]
222
+ post[:ds_trans_id] = three_d_secure_options[:ds_transaction_id]
223
+ end
224
+
206
225
  def add_payment_source(post, payment_method, options)
207
226
  if payment_method.is_a?(String)
208
227
  post[:data_key] = payment_method
@@ -291,14 +310,16 @@ module ActiveMerchant #:nodoc:
291
310
  end
292
311
  end
293
312
 
294
- def commit(action, parameters = {})
313
+ def commit(action, parameters = {}, options = {})
314
+ threed_ds_transaction = options[:three_d_secure].present?
315
+
295
316
  data = post_data(action, parameters)
296
317
  url = test? ? self.test_url : self.live_url
297
318
  raw = ssl_post(url, data)
298
319
  response = parse(raw)
299
320
 
300
321
  Response.new(
301
- successful?(response),
322
+ successful?(action, response, threed_ds_transaction),
302
323
  message_from(response[:message]),
303
324
  response,
304
325
  test: test?,
@@ -314,8 +335,16 @@ module ActiveMerchant #:nodoc:
314
335
  end
315
336
 
316
337
  # Tests for a successful response from Moneris' servers
317
- def successful?(response)
318
- response[:response_code] &&
338
+ def successful?(action, response, threed_ds_transaction = false)
339
+ # See 9.4 CAVV Result Codes in https://developer.moneris.com/livedemo/3ds2/reference/guide/php
340
+ cavv_accepted = if threed_ds_transaction
341
+ response[:cavv_result_code] && response[:cavv_result_code] == '2'
342
+ else
343
+ true
344
+ end
345
+
346
+ cavv_accepted &&
347
+ response[:response_code] &&
319
348
  response[:complete] &&
320
349
  (0..49).cover?(response[:response_code].to_i)
321
350
  end
@@ -404,10 +433,23 @@ module ActiveMerchant #:nodoc:
404
433
  end
405
434
 
406
435
  def wallet_indicator(token_source)
407
- return 'APP' if token_source == 'apple_pay'
408
- return 'ANP' if token_source == 'android_pay'
436
+ return {
437
+ 'apple_pay' => 'APP',
438
+ 'google_pay' => 'GPP',
439
+ 'android_pay' => 'ANP'
440
+ }[token_source]
441
+ end
442
+
443
+ def format_order_id(wallet_indicator_code, order_id = nil)
444
+ # Truncate (max 100 characters) order id for
445
+ # google pay and apple pay (specific wallets / token sources)
446
+ return truncate_order_id(order_id) if WALLETS.include?(wallet_indicator_code)
447
+
448
+ order_id
449
+ end
409
450
 
410
- nil
451
+ def truncate_order_id(order_id = nil)
452
+ order_id.present? ? order_id[0, 100] : SecureRandom.alphanumeric(100)
411
453
  end
412
454
 
413
455
  def message_from(message)
@@ -60,11 +60,13 @@ module ActiveMerchant #:nodoc:
60
60
  post = {}
61
61
  post[:code] = authorization
62
62
  add_invoice(post, money, options)
63
+ add_auth_key(post, options)
63
64
  commit('capture', post, authorization)
64
65
  end
65
66
 
66
67
  def refund(money, authorization, options = {})
67
68
  add_invoice(post = {}, money, options)
69
+ add_auth_key(post, options)
68
70
  commit('refund', post, authorization)
69
71
  end
70
72
 
@@ -77,6 +79,7 @@ module ActiveMerchant #:nodoc:
77
79
  options.update(name: payment.name)
78
80
  options = add_customer(options) unless options[:customer_id]
79
81
  add_payment(post, payment, options)
82
+ add_auth_key(post, options)
80
83
  commit('store', post, options[:customer_id])
81
84
  end
82
85
 
@@ -5,7 +5,7 @@ module ActiveMerchant #:nodoc:
5
5
 
6
6
  DUP_WINDOW_DEPRECATION_MESSAGE = 'The class-level duplicate_window variable is deprecated. Please use the :dup_seconds transaction option instead.'
7
7
 
8
- self.test_url = self.live_url = 'https://secure.nmi.com/api/transact.php'
8
+ self.test_url = self.live_url = 'https://secure.networkmerchants.com/api/transact.php'
9
9
  self.default_currency = 'USD'
10
10
  self.money_format = :dollars
11
11
  self.supported_countries = ['US']
@@ -23,7 +23,11 @@ module ActiveMerchant #:nodoc:
23
23
  end
24
24
 
25
25
  def initialize(options = {})
26
- requires!(options, :login, :password)
26
+ if options.has_key?(:security_key)
27
+ requires!(options, :security_key)
28
+ else
29
+ requires!(options, :login, :password)
30
+ end
27
31
  super
28
32
  end
29
33
 
@@ -51,7 +55,6 @@ module ActiveMerchant #:nodoc:
51
55
  add_merchant_defined_fields(post, options)
52
56
  add_level3_fields(post, options)
53
57
  add_three_d_secure(post, options)
54
-
55
58
  commit('auth', post)
56
59
  end
57
60
 
@@ -126,6 +129,7 @@ module ActiveMerchant #:nodoc:
126
129
  def scrub(transcript)
127
130
  transcript.
128
131
  gsub(%r((password=)[^&\n]*), '\1[FILTERED]').
132
+ gsub(%r((security_key=)[^&\n]*), '\1[FILTERED]').
129
133
  gsub(%r((ccnumber=)\d+), '\1[FILTERED]').
130
134
  gsub(%r((cvv=)\d+), '\1[FILTERED]').
131
135
  gsub(%r((checkaba=)\d+), '\1[FILTERED]').
@@ -297,9 +301,9 @@ module ActiveMerchant #:nodoc:
297
301
 
298
302
  def commit(action, params)
299
303
  params[action == 'add_customer' ? :customer_vault : :type] = action
300
- params[:username] = @options[:login]
301
- params[:password] = @options[:password]
302
-
304
+ params[:username] = @options[:login] unless @options[:login].nil?
305
+ params[:password] = @options[:password] unless @options[:password].nil?
306
+ params[:security_key] = @options[:security_key] unless @options[:security_key].nil?
303
307
  raw_response = ssl_post(url, post_data(action, params), headers)
304
308
  response = parse(raw_response)
305
309
  succeeded = success_from(response)
@@ -325,7 +329,8 @@ module ActiveMerchant #:nodoc:
325
329
  end
326
330
 
327
331
  def headers
328
- { 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' }
332
+ headers = { 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' }
333
+ headers
329
334
  end
330
335
 
331
336
  def post_data(action, params)
@@ -136,7 +136,7 @@ module ActiveMerchant #:nodoc:
136
136
  self.supported_countries = %w[BE DE FR NL AT CH]
137
137
  # also supports Airplus and UATP
138
138
  self.supported_cardtypes = %i[visa master american_express diners_club discover jcb maestro]
139
- self.homepage_url = 'http://www.ogone.com/'
139
+ self.homepage_url = 'https://www.ingenico.com/login/ogone/'
140
140
  self.display_name = 'Ogone'
141
141
  self.default_currency = 'EUR'
142
142
  self.money_format = :cents
@@ -264,7 +264,6 @@ module ActiveMerchant #:nodoc:
264
264
 
265
265
  def add_payment_source(post, payment_source, options)
266
266
  add_d3d(post, options) if options[:d3d]
267
-
268
267
  if payment_source.is_a?(String)
269
268
  add_alias(post, payment_source, options[:alias_operation])
270
269
  add_eci(post, options[:eci] || '9')
@@ -285,8 +284,6 @@ module ActiveMerchant #:nodoc:
285
284
  THREE_D_SECURE_DISPLAY_WAYS[options[:win_3ds]] :
286
285
  THREE_D_SECURE_DISPLAY_WAYS[:main_window]
287
286
  add_pair post, 'WIN3DS', win_3ds
288
-
289
- add_pair post, 'HTTP_ACCEPT', options[:http_accept] || '*/*'
290
287
  add_pair post, 'HTTP_USER_AGENT', options[:http_user_agent] if options[:http_user_agent]
291
288
  add_pair post, 'ACCEPTURL', options[:accept_url] if options[:accept_url]
292
289
  add_pair post, 'DECLINEURL', options[:decline_url] if options[:decline_url]
@@ -296,6 +293,37 @@ module ActiveMerchant #:nodoc:
296
293
  add_pair post, 'PARAMPLUS', options[:paramplus] if options[:paramplus]
297
294
  add_pair post, 'COMPLUS', options[:complus] if options[:complus]
298
295
  add_pair post, 'LANGUAGE', options[:language] if options[:language]
296
+ if options[:three_ds_2]
297
+ browser_info = options[:three_ds_2][:browser_info]
298
+ ecom_postal = options[:billing_address]
299
+ if browser_info
300
+ add_pair post, 'BROWSERACCEPTHEADER', browser_info[:accept_header]
301
+ add_pair post, 'BROWSERCOLORDEPTH', browser_info[:depth]
302
+
303
+ # for 3ds v2.1 to v2.2 add BROWSERJAVASCRIPTENABLED: This boolean indicates whether your customers have enabled JavaScript in their browsers when making a purchase.
304
+ # the following BROWSER<tag> parameters will remain mandatory unless browser_info[:javascript] = false
305
+ # her documentation https://epayments-support.ingenico.com/en/integration-solutions/integrations/directlink#directlink_integration_guides_secure_payment_with_3_d_secure
306
+ add_pair post, 'BROWSERJAVASCRIPTENABLED', browser_info[:javascript]
307
+ add_pair post, 'BROWSERJAVAENABLED', browser_info[:java]
308
+ add_pair post, 'BROWSERLANGUAGE', browser_info[:language]
309
+ add_pair post, 'BROWSERSCREENHEIGHT', browser_info[:height]
310
+ add_pair post, 'BROWSERSCREENWIDTH', browser_info[:width]
311
+ add_pair post, 'BROWSERTIMEZONE', browser_info[:timezone]
312
+ add_pair post, 'BROWSERUSERAGENT', browser_info[:user_agent]
313
+ end
314
+ # recommended
315
+ if ecom_postal
316
+ add_pair post, 'ECOM_BILLTO_POSTAL_CITY', ecom_postal[:city]
317
+ add_pair post, 'ECOM_BILLTO_POSTAL_COUNTRYCODE', ecom_postal[:country]
318
+ add_pair post, 'ECOM_BILLTO_POSTAL_STREET_LINE1', ecom_postal[:address1]
319
+ add_pair post, 'ECOM_BILLTO_POSTAL_STREET_LINE2', ecom_postal[:address2]
320
+ add_pair post, 'ECOM_BILLTO_POSTAL_POSTALCODE', ecom_postal[:zip]
321
+ end
322
+ # optional
323
+ add_pair post, 'Mpi.threeDSRequestorChallengeIndicator', options[:three_ds_reqchallengeind]
324
+ else
325
+ add_pair post, 'HTTP_ACCEPT', options[:http_accept] || '*/*'
326
+ end
299
327
  end
300
328
 
301
329
  def add_eci(post, eci)
@@ -414,7 +442,7 @@ module ActiveMerchant #:nodoc:
414
442
  return
415
443
  end
416
444
 
417
- add_pair parameters, 'SHASign', calculate_signature(parameters, @options[:signature_encryptor], @options[:signature])
445
+ add_pair parameters, 'SHASIGN', calculate_signature(parameters, @options[:signature_encryptor], @options[:signature])
418
446
  end
419
447
 
420
448
  def calculate_signature(signed_parameters, algorithm, secret)
@@ -432,7 +460,7 @@ module ActiveMerchant #:nodoc:
432
460
  raise "Unknown signature algorithm #{algorithm}"
433
461
  end
434
462
 
435
- filtered_params = signed_parameters.select { |_k, v| !v.blank? }
463
+ filtered_params = signed_parameters.compact
436
464
  sha_encryptor.hexdigest(
437
465
  filtered_params.sort_by { |k, _v| k.upcase }.map { |k, v| "#{k.upcase}=#{v}#{secret}" }.join('')
438
466
  ).upcase
@@ -456,7 +484,7 @@ module ActiveMerchant #:nodoc:
456
484
  end
457
485
 
458
486
  def add_pair(post, key, value)
459
- post[key] = value if !value.blank?
487
+ post[key] = value unless value.nil?
460
488
  end
461
489
 
462
490
  def convert_attributes_to_hash(rexml_attributes)
@@ -1,8 +1,15 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class OpenpayGateway < Gateway
4
- self.live_url = 'https://api.openpay.mx/v1/'
5
- self.test_url = 'https://sandbox-api.openpay.mx/v1/'
4
+ class_attribute :mx_live_url, :mx_test_url
5
+ class_attribute :co_live_url, :co_test_url
6
+
7
+ self.co_live_url = 'https://api.openpay.co/v1/'
8
+ self.co_test_url = 'https://sandbox-api.openpay.co/v1/'
9
+ self.mx_live_url = 'https://api.openpay.mx/v1/'
10
+ self.mx_test_url = 'https://sandbox-api.openpay.mx/v1/'
11
+ self.live_url = self.co_live_url
12
+ self.test_url = self.co_test_url
6
13
 
7
14
  self.supported_countries = %w(CO MX)
8
15
  self.supported_cardtypes = %i[visa master american_express carnet]
@@ -24,6 +31,16 @@ module ActiveMerchant #:nodoc:
24
31
  super
25
32
  end
26
33
 
34
+ def gateway_url(options = {})
35
+ country = options[:merchant_country] || @options[:merchant_country]
36
+
37
+ if country == 'MX'
38
+ test? ? mx_test_url : mx_live_url
39
+ else
40
+ test? ? co_test_url : co_live_url
41
+ end
42
+ end
43
+
27
44
  def purchase(money, creditcard, options = {})
28
45
  post = create_post_for_auth_or_purchase(money, creditcard, options)
29
46
  commit(:post, 'charges', post, options)
@@ -192,7 +209,7 @@ module ActiveMerchant #:nodoc:
192
209
  end
193
210
 
194
211
  def http_request(method, resource, parameters = {}, options = {})
195
- url = (test? ? self.test_url : self.live_url) + @merchant_id + '/' + resource
212
+ url = gateway_url(options) + @merchant_id + '/' + resource
196
213
  raw_response = nil
197
214
  begin
198
215
  raw_response = ssl_request(method, url, (parameters ? parameters.to_json : nil), headers(options))