activemerchant 1.119.0 → 1.124.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +216 -1
  3. data/README.md +4 -2
  4. data/lib/active_merchant/billing/check.rb +19 -12
  5. data/lib/active_merchant/billing/credit_card.rb +3 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +32 -14
  8. data/lib/active_merchant/billing/gateways/adyen.rb +94 -25
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +52 -8
  14. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  15. data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
  16. data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
  17. data/lib/active_merchant/billing/gateways/credorax.rb +15 -9
  18. data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -6
  19. data/lib/active_merchant/billing/gateways/d_local.rb +9 -2
  20. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  21. data/lib/active_merchant/billing/gateways/elavon.rb +70 -28
  22. data/lib/active_merchant/billing/gateways/element.rb +2 -0
  23. data/lib/active_merchant/billing/gateways/forte.rb +12 -0
  24. data/lib/active_merchant/billing/gateways/global_collect.rb +24 -10
  25. data/lib/active_merchant/billing/gateways/hps.rb +55 -1
  26. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  27. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  34. data/lib/active_merchant/billing/gateways/netbanx.rb +26 -2
  35. data/lib/active_merchant/billing/gateways/nmi.rb +27 -9
  36. data/lib/active_merchant/billing/gateways/orbital.rb +99 -59
  37. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  38. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  39. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  40. data/lib/active_merchant/billing/gateways/payeezy.rb +34 -6
  41. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  42. data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
  43. data/lib/active_merchant/billing/gateways/payment_express.rb +5 -5
  44. data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
  45. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  46. data/lib/active_merchant/billing/gateways/paysafe.rb +376 -0
  47. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  49. data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
  50. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +42 -24
  52. data/lib/active_merchant/billing/gateways/safe_charge.rb +25 -13
  53. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  54. data/lib/active_merchant/billing/gateways/stripe.rb +18 -8
  55. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +126 -48
  56. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  58. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  59. data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
  60. data/lib/active_merchant/billing/gateways/worldpay.rb +78 -18
  61. data/lib/active_merchant/billing/response.rb +4 -0
  62. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  63. data/lib/active_merchant/billing.rb +1 -0
  64. data/lib/active_merchant/version.rb +1 -1
  65. data/lib/certs/cacert.pem +1582 -2431
  66. metadata +11 -3
@@ -17,7 +17,7 @@ module ActiveMerchant #:nodoc:
17
17
  }
18
18
 
19
19
  def initialize(options = {})
20
- requires!(options, :username, :password, :merchant, :pem, :pem_password)
20
+ requires!(options, :username, :password, :merchant, :pem)
21
21
  super
22
22
  end
23
23
 
@@ -30,6 +30,7 @@ module ActiveMerchant #:nodoc:
30
30
  add_stored_credential_data(post, payment_method, options)
31
31
  add_customer_data(post, options)
32
32
  add_soft_descriptors(post, options)
33
+ add_customer_reference(post, options)
33
34
 
34
35
  commit('capture', post)
35
36
  end
@@ -43,6 +44,7 @@ module ActiveMerchant #:nodoc:
43
44
  add_stored_credential_data(post, payment_method, options)
44
45
  add_customer_data(post, options)
45
46
  add_soft_descriptors(post, options)
47
+ add_customer_reference(post, options)
46
48
 
47
49
  commit('preauth', post)
48
50
  end
@@ -53,6 +55,7 @@ module ActiveMerchant #:nodoc:
53
55
  add_reference(post, authorization, options)
54
56
  add_customer_data(post, options)
55
57
  add_soft_descriptors(post, options)
58
+ add_customer_reference(post, options)
56
59
 
57
60
  commit('captureWithoutAuth', post)
58
61
  end
@@ -64,6 +67,7 @@ module ActiveMerchant #:nodoc:
64
67
  add_customer_data(post, options)
65
68
  add_soft_descriptors(post, options)
66
69
  post['order.ECI'] = options[:eci] || 'SSL'
70
+ add_customer_reference(post, options)
67
71
 
68
72
  commit('refund', post)
69
73
  end
@@ -76,6 +80,7 @@ module ActiveMerchant #:nodoc:
76
80
  add_payment_method(post, payment_method)
77
81
  add_customer_data(post, options)
78
82
  add_soft_descriptors(post, options)
83
+ add_customer_reference(post, options)
79
84
 
80
85
  commit('refund', post)
81
86
  end
@@ -85,6 +90,7 @@ module ActiveMerchant #:nodoc:
85
90
  add_reference(post, authorization, options)
86
91
  add_customer_data(post, options)
87
92
  add_soft_descriptors(post, options)
93
+ add_customer_reference(post, options)
88
94
 
89
95
  commit('reversal', post)
90
96
  end
@@ -92,7 +98,7 @@ module ActiveMerchant #:nodoc:
92
98
  def store(payment_method, options = {})
93
99
  post = {}
94
100
  add_payment_method(post, payment_method)
95
- add_card_reference(post)
101
+ add_card_reference(post, options)
96
102
 
97
103
  commit('registerAccount', post)
98
104
  end
@@ -149,12 +155,16 @@ module ActiveMerchant #:nodoc:
149
155
  return unless payment_method.brand == 'visa'
150
156
 
151
157
  stored_credential = options[:stored_credential]
152
- if stored_credential[:initial_transaction]
153
- post['card.storedCredentialUsage'] = 'INITIAL_STORAGE'
154
- elsif stored_credential[:reason_type] == ('recurring' || 'installment')
158
+ if stored_credential[:reason_type] == 'unscheduled'
159
+ if stored_credential[:initiator] == 'merchant'
160
+ post['card.storedCredentialUsage'] = 'UNSCHEDULED_MIT'
161
+ elsif stored_credential[:initiator] == 'customer'
162
+ post['card.storedCredentialUsage'] = 'UNSCHEDULED_CIT'
163
+ end
164
+ elsif stored_credential[:reason_type] == 'recurring'
155
165
  post['card.storedCredentialUsage'] = 'RECURRING'
156
- elsif stored_credential[:reason_type] == 'unscheduled'
157
- post['card.storedCredentialUsage'] = 'UNSCHEDULED'
166
+ elsif stored_credential[:reason_type] == 'installment'
167
+ post['card.storedCredentialUsage'] = 'INSTALLMENT'
158
168
  end
159
169
  end
160
170
 
@@ -181,8 +191,12 @@ module ActiveMerchant #:nodoc:
181
191
  post['card.CVN'] = payment_method.verification_value
182
192
  end
183
193
 
184
- def add_card_reference(post)
185
- post['customer.customerReferenceNumber'] = options[:order_id]
194
+ def add_card_reference(post, options)
195
+ post['customer.customerReferenceNumber'] = options[:customer_reference_number] || options[:order_id]
196
+ end
197
+
198
+ def add_customer_reference(post, options)
199
+ post['customer.customerReferenceNumber'] = options[:customer_reference_number] if options[:customer_reference_number]
186
200
  end
187
201
 
188
202
  def add_reference(post, authorization, options)
@@ -151,6 +151,7 @@ module ActiveMerchant
151
151
  else
152
152
  add_three_d_secure(xml, options)
153
153
  end
154
+ add_stored_credential(xml, options)
154
155
  add_comments(xml, options)
155
156
  add_address_and_customer_info(xml, options)
156
157
  end
@@ -323,6 +324,23 @@ module ActiveMerchant
323
324
  end
324
325
  end
325
326
 
327
+ def add_stored_credential(xml, options)
328
+ return unless stored_credential = options[:stored_credential]
329
+
330
+ xml.tag! 'storedcredential' do
331
+ xml.tag! 'type', stored_credential_type(stored_credential[:reason_type])
332
+ xml.tag! 'initiator', stored_credential[:initiator]
333
+ xml.tag! 'sequence', stored_credential[:initial_transaction] ? 'first' : 'subsequent'
334
+ xml.tag! 'srd', stored_credential[:network_transaction_id]
335
+ end
336
+ end
337
+
338
+ def stored_credential_type(reason)
339
+ return 'oneoff' if reason == 'unscheduled'
340
+
341
+ reason
342
+ end
343
+
326
344
  def format_address_code(address)
327
345
  code = [address[:zip].to_s, address[:address1].to_s + address[:address2].to_s]
328
346
  code.collect { |e| e.gsub(/\D/, '') }.reject(&:empty?).join('|')
@@ -203,11 +203,12 @@ module ActiveMerchant #:nodoc:
203
203
  add_order(data, options[:order_id])
204
204
  add_payment(data, payment)
205
205
  add_external_mpi_fields(data, options)
206
- add_threeds(data, options) if options[:execute_threed]
206
+ add_three_ds_data(data, options) if options[:execute_threed]
207
207
  add_stored_credential_options(data, options)
208
208
  data[:description] = options[:description]
209
209
  data[:store_in_vault] = options[:store]
210
210
  data[:sca_exemption] = options[:sca_exemption]
211
+ data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
211
212
 
212
213
  commit data, options
213
214
  end
@@ -221,11 +222,12 @@ module ActiveMerchant #:nodoc:
221
222
  add_order(data, options[:order_id])
222
223
  add_payment(data, payment)
223
224
  add_external_mpi_fields(data, options)
224
- add_threeds(data, options) if options[:execute_threed]
225
+ add_three_ds_data(data, options) if options[:execute_threed]
225
226
  add_stored_credential_options(data, options)
226
227
  data[:description] = options[:description]
227
228
  data[:store_in_vault] = options[:store]
228
229
  data[:sca_exemption] = options[:sca_exemption]
230
+ data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
229
231
 
230
232
  commit data, options
231
233
  end
@@ -310,7 +312,7 @@ module ActiveMerchant #:nodoc:
310
312
  test? ? test_url : live_url
311
313
  end
312
314
 
313
- def threeds_url
315
+ def webservice_url
314
316
  test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2' : 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
315
317
  end
316
318
 
@@ -370,42 +372,51 @@ module ActiveMerchant #:nodoc:
370
372
  end
371
373
  end
372
374
 
373
- def add_threeds(data, options)
374
- data[:threeds] = { threeDSInfo: 'CardData' } if options[:execute_threed] == true
375
+ def add_three_ds_data(data, options)
376
+ data[:three_ds_data] = { threeDSInfo: 'CardData' } if options[:execute_threed] == true
375
377
  end
376
378
 
377
- def determine_3ds_action(threeds_hash)
378
- return 'iniciaPeticion' if threeds_hash[:threeDSInfo] == 'CardData'
379
- return 'trataPeticion' if threeds_hash[:threeDSInfo] == 'AuthenticationData' ||
380
- threeds_hash[:threeDSInfo] == 'ChallengeResponse'
379
+ def determine_peticion_type(data)
380
+ three_ds_info = data.dig(:three_ds_data, :threeDSInfo)
381
+ return 'iniciaPeticion' if three_ds_info == 'CardData'
382
+ return 'trataPeticion' if three_ds_info == 'AuthenticationData' ||
383
+ three_ds_info == 'ChallengeResponse' ||
384
+ data[:sca_exemption] == 'MIT'
385
+ end
386
+
387
+ def use_webservice_endpoint?(data, options)
388
+ options[:use_webservice_endpoint].to_s == 'true' || data[:three_ds_data] || data[:sca_exemption] == 'MIT'
381
389
  end
382
390
 
383
391
  def commit(data, options = {})
384
- if data[:threeds]
385
- action = determine_3ds_action(data[:threeds])
392
+ xmlreq = xml_request_from(data, options)
393
+
394
+ if use_webservice_endpoint?(data, options)
395
+ peticion_type = determine_peticion_type(data)
396
+
386
397
  request = <<-REQUEST
387
398
  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservice.sis.sermepa.es" xmlns:intf="http://webservice.sis.sermepa.es" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
388
399
  <soapenv:Header/>
389
400
  <soapenv:Body>
390
- <intf:#{action} xmlns:intf="http://webservice.sis.sermepa.es">
401
+ <intf:#{peticion_type} xmlns:intf="http://webservice.sis.sermepa.es">
391
402
  <intf:datoEntrada>
392
- <![CDATA[#{xml_request_from(data, options)}]]>
403
+ <![CDATA[#{xmlreq}]]>
393
404
  </intf:datoEntrada>
394
- </intf:#{action}>
405
+ </intf:#{peticion_type}>
395
406
  </soapenv:Body>
396
407
  </soapenv:Envelope>
397
408
  REQUEST
398
- parse(ssl_post(threeds_url, request, headers(action)), action)
409
+ parse(ssl_post(webservice_url, request, headers(peticion_type)), peticion_type)
399
410
  else
400
- parse(ssl_post(url, "entrada=#{CGI.escape(xml_request_from(data, options))}", headers), action)
411
+ parse(ssl_post(url, "entrada=#{CGI.escape(xmlreq)}", headers), peticion_type)
401
412
  end
402
413
  end
403
414
 
404
- def headers(action = nil)
405
- if action
415
+ def headers(peticion_type = nil)
416
+ if peticion_type
406
417
  {
407
418
  'Content-Type' => 'text/xml',
408
- 'SOAPAction' => action
419
+ 'SOAPAction' => peticion_type
409
420
  }
410
421
  else
411
422
  {
@@ -469,7 +480,7 @@ module ActiveMerchant #:nodoc:
469
480
 
470
481
  def build_merchant_data(xml, data, options = {})
471
482
  # See https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2/wsdl/SerClsWSEntradaV2.wsdl
472
- # (which results from calling #threeds_url + '?WSDL', https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2?WSDL)
483
+ # (which results from calling #webservice_url + '?WSDL', https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2?WSDL)
473
484
  xml.DATOSENTRADA do
474
485
  # Basic elements
475
486
  xml.DS_Version 0.1
@@ -477,7 +488,7 @@ module ActiveMerchant #:nodoc:
477
488
  xml.DS_MERCHANT_AMOUNT data[:amount]
478
489
  xml.DS_MERCHANT_ORDER data[:order_id]
479
490
  xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
480
- if data[:description] && data[:threeds]
491
+ if data[:description] && use_webservice_endpoint?(data, options)
481
492
  xml.DS_MERCHANT_PRODUCTDESCRIPTION CGI.escape(data[:description])
482
493
  else
483
494
  xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
@@ -485,11 +496,18 @@ module ActiveMerchant #:nodoc:
485
496
  xml.DS_MERCHANT_TERMINAL options[:terminal] || @options[:terminal]
486
497
  xml.DS_MERCHANT_MERCHANTCODE @options[:login]
487
498
  xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
488
- xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
499
+
500
+ peticion_type = determine_peticion_type(data) if data[:three_ds_data]
501
+ if peticion_type == 'iniciaPeticion' && data[:sca_exemption]
502
+ xml.DS_MERCHANT_EXCEP_SCA 'Y'
503
+ else
504
+ xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
505
+ xml.DS_MERCHANT_DIRECTPAYMENT data[:sca_exemption_direct_payment_enabled] || 'true' if data[:sca_exemption] == 'MIT'
506
+ end
489
507
 
490
508
  # Only when card is present
491
509
  if data[:card]
492
- if data[:card][:name] && data[:threeds]
510
+ if data[:card][:name] && use_webservice_endpoint?(data, options)
493
511
  xml.DS_MERCHANT_TITULAR CGI.escape(data[:card][:name])
494
512
  else
495
513
  xml.DS_MERCHANT_TITULAR data[:card][:name]
@@ -510,7 +528,7 @@ module ActiveMerchant #:nodoc:
510
528
  # Requires account configuration to be able to use
511
529
  xml.DS_MERCHANT_DIRECTPAYMENT 'moto' if options.dig(:moto) && options.dig(:metadata, :manual_entry)
512
530
 
513
- xml.DS_MERCHANT_EMV3DS data[:threeds].to_json if data[:threeds]
531
+ xml.DS_MERCHANT_EMV3DS data[:three_ds_data].to_json if data[:three_ds_data]
514
532
 
515
533
  if options[:stored_credential]
516
534
  xml.DS_MERCHANT_COF_INI data[:DS_MERCHANT_COF_INI]
@@ -62,6 +62,7 @@ module ActiveMerchant #:nodoc:
62
62
  post[:sg_CCToken] = token
63
63
  post[:sg_ExpMonth] = exp_month
64
64
  post[:sg_ExpYear] = exp_year
65
+ post[:sg_Email] = options[:email]
65
66
 
66
67
  commit(post)
67
68
  end
@@ -126,9 +127,11 @@ module ActiveMerchant #:nodoc:
126
127
  private
127
128
 
128
129
  def add_transaction_data(trans_type, post, money, options)
130
+ currency = options[:currency] || currency(money)
131
+
129
132
  post[:sg_TransType] = trans_type
130
- post[:sg_Currency] = (options[:currency] || currency(money))
131
- post[:sg_Amount] = amount(money)
133
+ post[:sg_Currency] = currency
134
+ post[:sg_Amount] = localized_amount(money, currency)
132
135
  post[:sg_ClientLoginID] = @options[:client_login_id]
133
136
  post[:sg_ClientPassword] = @options[:client_password]
134
137
  post[:sg_ResponseFormat] = '4'
@@ -143,15 +146,24 @@ module ActiveMerchant #:nodoc:
143
146
  post[:sg_Descriptor] = options[:merchant_descriptor] if options[:merchant_descriptor]
144
147
  post[:sg_MerchantPhoneNumber] = options[:merchant_phone_number] if options[:merchant_phone_number]
145
148
  post[:sg_MerchantName] = options[:merchant_name] if options[:merchant_name]
149
+ post[:sg_ProductID] = options[:product_id] if options[:product_id]
146
150
  end
147
151
 
148
152
  def add_payment(post, payment, options = {})
149
- post[:sg_NameOnCard] = payment.name
150
- post[:sg_CardNumber] = payment.number
151
153
  post[:sg_ExpMonth] = format(payment.month, :two_digits)
152
154
  post[:sg_ExpYear] = format(payment.year, :two_digits)
153
- post[:sg_CVV2] = payment.verification_value
154
- post[:sg_StoredCredentialMode] = (options[:stored_credential_mode] == true ? 1 : 0)
155
+ post[:sg_CardNumber] = payment.number
156
+
157
+ if payment.is_a?(NetworkTokenizationCreditCard) && payment.source == :network_token
158
+ post[:sg_CAVV] = payment.payment_cryptogram
159
+ post[:sg_ECI] = options[:three_d_secure] && options[:three_d_secure][:eci] || '05'
160
+ post[:sg_IsExternalMPI] = 1
161
+ post[:sg_ExternalTokenProvider] = 5
162
+ else
163
+ post[:sg_CVV2] = payment.verification_value
164
+ post[:sg_NameOnCard] = payment.name
165
+ post[:sg_StoredCredentialMode] = (options[:stored_credential_mode] == true ? 1 : 0)
166
+ end
155
167
  end
156
168
 
157
169
  def add_customer_details(post, payment, options)
@@ -170,14 +182,14 @@ module ActiveMerchant #:nodoc:
170
182
  end
171
183
 
172
184
  def add_external_mpi_data(post, options)
173
- version = options[:three_d_secure][:ds_transaction_id] ? '2' : '1'
174
-
175
- post[:sg_eci] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
176
- post[:sg_cavv] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
177
- post[:sg_dsTransID] = options[:three_d_secure][:ds_transaction_id] if version == '2'
178
- post[:sg_threeDSProtocolVersion] = version
179
- post[:sg_xid] = options[:three_d_secure][:xid] if version == '1'
185
+ post[:sg_ECI] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
186
+ post[:sg_CAVV] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
187
+ post[:sg_dsTransID] = options[:three_d_secure][:ds_transaction_id] if options[:three_d_secure][:ds_transaction_id]
188
+ post[:sg_threeDSProtocolVersion] = options[:three_d_secure][:ds_transaction_id] ? '2' : '1'
189
+ post[:sg_Xid] = options[:three_d_secure][:xid]
180
190
  post[:sg_IsExternalMPI] = 1
191
+ post[:sg_EnablePartialApproval] = options[:is_partial_approval]
192
+ post[:sg_challengePreference] = options[:three_d_secure][:challenge_preference] if options[:three_d_secure][:challenge_preference]
181
193
  end
182
194
 
183
195
  def parse(xml)
@@ -254,11 +254,20 @@ module ActiveMerchant #:nodoc:
254
254
  end
255
255
 
256
256
  def childnode_to_response(response, node, childnode)
257
- name = "#{node.name.downcase}_#{childnode.name.downcase}"
258
- if name == 'payment_method_data' && !childnode.elements.empty?
259
- response[name.to_sym] = Hash.from_xml(childnode.to_s).values.first
257
+ node_name = node.name.downcase
258
+ childnode_name = childnode.name.downcase
259
+ composed_name = "#{node_name}_#{childnode_name}"
260
+
261
+ childnodes_present = !childnode.elements.empty?
262
+
263
+ if childnodes_present && composed_name == 'payment_method_data'
264
+ response[composed_name.to_sym] = Hash.from_xml(childnode.to_s).values.first
265
+ elsif childnodes_present && node_name == 'gateway_specific_response_fields'
266
+ response[node_name.to_sym] = {
267
+ childnode_name => Hash.from_xml(childnode.to_s).values.first
268
+ }
260
269
  else
261
- response[name.to_sym] = childnode.text
270
+ response[composed_name.to_sym] = childnode.text
262
271
  end
263
272
  end
264
273
 
@@ -279,14 +279,15 @@ module ActiveMerchant #:nodoc:
279
279
  transcript.
280
280
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
281
281
  gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2').
282
- gsub(%r((card\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\2').
283
- gsub(%r((card\[cvc\]=)\d+), '\1[FILTERED]').
284
- gsub(%r((card\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
285
- gsub(%r((card\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\2').
286
- gsub(%r((card\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\2').
287
- gsub(%r((card\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\2').
288
- gsub(%r((card\[number\]=)\d+), '\1[FILTERED]').
289
- gsub(%r((card\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\2')
282
+ gsub(%r(((\[card\]|card)\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\3').
283
+ gsub(%r(((\[card\]|card)\[cvc\]=)\d+), '\1[FILTERED]').
284
+ gsub(%r(((\[card\]|card)\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
285
+ gsub(%r(((\[card\]|card)\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
286
+ gsub(%r(((\[card\]|card)\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\3').
287
+ gsub(%r(((\[card\]|card)\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\3').
288
+ gsub(%r(((\[card\]|card)\[number\]=)\d+), '\1[FILTERED]').
289
+ gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
290
+ gsub(%r(((\[bank_account\]|bank_account)\[account_number\]=)\d+), '\1[FILTERED]')
290
291
  end
291
292
 
292
293
  def supports_network_tokenization?
@@ -379,6 +380,7 @@ module ActiveMerchant #:nodoc:
379
380
  add_destination(post, options)
380
381
  add_level_three(post, options)
381
382
  add_connected_account(post, options)
383
+ add_radar_data(post, options)
382
384
  post
383
385
  end
384
386
 
@@ -570,6 +572,14 @@ module ActiveMerchant #:nodoc:
570
572
  post[:application_fee_amount] = options[:application_fee_amount] if options[:application_fee_amount]
571
573
  end
572
574
 
575
+ def add_radar_data(post, options = {})
576
+ return unless options[:radar_session_id]
577
+
578
+ post[:radar_options] = {
579
+ session: options[:radar_session_id]
580
+ }
581
+ end
582
+
573
583
  def parse(body)
574
584
  JSON.parse(body)
575
585
  end