activemerchant 1.119.0 → 1.124.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 (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