activemerchant 1.121.0 → 1.123.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +86 -0
  3. data/README.md +1 -1
  4. data/lib/active_merchant/billing/check.rb +13 -16
  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 +21 -12
  8. data/lib/active_merchant/billing/gateways/adyen.rb +15 -19
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
  10. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  11. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  12. data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
  13. data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
  14. data/lib/active_merchant/billing/gateways/cyber_source.rb +30 -3
  15. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  16. data/lib/active_merchant/billing/gateways/elavon.rb +60 -28
  17. data/lib/active_merchant/billing/gateways/element.rb +2 -0
  18. data/lib/active_merchant/billing/gateways/global_collect.rb +19 -10
  19. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  20. data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -2
  21. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  22. data/lib/active_merchant/billing/gateways/moka.rb +277 -0
  23. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  24. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  25. data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
  26. data/lib/active_merchant/billing/gateways/orbital.rb +28 -6
  27. data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
  28. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  29. data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
  30. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  31. data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
  32. data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
  33. data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
  34. data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
  35. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  36. data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
  37. data/lib/active_merchant/billing/gateways/safe_charge.rb +2 -0
  38. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  39. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +19 -1
  40. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  41. data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
  42. data/lib/active_merchant/billing/gateways/worldpay.rb +39 -7
  43. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  44. data/lib/active_merchant/billing.rb +1 -0
  45. data/lib/active_merchant/version.rb +1 -1
  46. metadata +8 -3
@@ -86,8 +86,8 @@ module ActiveMerchant #:nodoc:
86
86
  refund(money, identification, options)
87
87
  end
88
88
 
89
- def verify(money, payment_source, options = {})
90
- request = build_purchase_or_authorization_request(money, payment_source, options)
89
+ def verify(payment_source, options = {})
90
+ request = build_purchase_or_authorization_request(100, payment_source, options)
91
91
  commit(:validate, request)
92
92
  end
93
93
 
@@ -82,6 +82,7 @@ module ActiveMerchant #:nodoc:
82
82
  def refund(money, authorization, options = {})
83
83
  post = { transaction: { id: authorization } }
84
84
  post[:order] = { amount: amount(money).to_f } if money
85
+ add_more_info(post, options)
85
86
 
86
87
  commit_transaction('refund', post)
87
88
  end
@@ -198,6 +199,10 @@ module ActiveMerchant #:nodoc:
198
199
  extra_params[:auth_data] = auth_data
199
200
  end
200
201
 
202
+ def add_more_info(post, options)
203
+ post[:more_info] = options[:more_info] if options[:more_info]
204
+ end
205
+
201
206
  def parse(body)
202
207
  JSON.parse(body)
203
208
  end
@@ -0,0 +1,291 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaysafeGateway < Gateway
4
+ self.test_url = 'https://api.test.paysafe.com'
5
+ self.live_url = 'https://api.paysafe.com'
6
+
7
+ self.supported_countries = %w(FR)
8
+ self.default_currency = 'EUR'
9
+ self.supported_cardtypes = %i[visa master american_express discover]
10
+
11
+ self.homepage_url = 'https://www.paysafe.com/'
12
+ self.display_name = 'Paysafe'
13
+
14
+ def initialize(options = {})
15
+ requires!(options, :username, :password, :account_id)
16
+ super
17
+ end
18
+
19
+ def purchase(money, payment, options = {})
20
+ post = {}
21
+ add_invoice(post, money, options)
22
+ add_payment(post, payment)
23
+ add_billing_address(post, options)
24
+ add_merchant_details(post, options)
25
+ add_customer_data(post, payment, options) unless payment.is_a?(String)
26
+ add_three_d_secure(post, payment, options) if options[:three_d_secure]
27
+ post[:settleWithAuth] = true
28
+
29
+ commit(:post, 'auths', post, options)
30
+ end
31
+
32
+ def authorize(money, payment, options = {})
33
+ post = {}
34
+ add_invoice(post, money, options)
35
+ add_payment(post, payment)
36
+ add_billing_address(post, options)
37
+ add_merchant_details(post, options)
38
+ add_customer_data(post, payment, options) unless payment.is_a?(String)
39
+ add_three_d_secure(post, payment, options) if options[:three_d_secure]
40
+
41
+ commit(:post, 'auths', post, options)
42
+ end
43
+
44
+ def capture(money, authorization, options = {})
45
+ post = {}
46
+ add_invoice(post, money, options)
47
+
48
+ commit(:post, "auths/#{authorization}/settlements", post, options)
49
+ end
50
+
51
+ def refund(money, authorization, options = {})
52
+ post = {}
53
+ add_invoice(post, money, options)
54
+
55
+ commit(:post, "settlements/#{authorization}/refunds", post, options)
56
+ end
57
+
58
+ def void(authorization, options = {})
59
+ post = {}
60
+ money = options[:amount]
61
+ add_invoice(post, money, options)
62
+
63
+ commit(:post, "auths/#{authorization}/voidauths", post, options)
64
+ end
65
+
66
+ def credit(money, payment, options = {})
67
+ post = {}
68
+ add_invoice(post, money, options)
69
+ add_payment(post, payment)
70
+
71
+ commit(:post, 'standalonecredits', post, options)
72
+ end
73
+
74
+ # This is a '$0 auth' done at a specific verification endpoint at the gateway
75
+ def verify(payment, options = {})
76
+ post = {}
77
+ add_payment(post, payment)
78
+ add_billing_address(post, options)
79
+ add_customer_data(post, payment, options) unless payment.is_a?(String)
80
+
81
+ commit(:post, 'verifications', post, options)
82
+ end
83
+
84
+ def store(payment, options = {})
85
+ post = {}
86
+ add_payment(post, payment)
87
+ add_address_for_vaulting(post, options)
88
+ add_profile_data(post, payment, options)
89
+ add_store_data(post, payment, options)
90
+
91
+ commit(:post, 'profiles', post, options)
92
+ end
93
+
94
+ def redact(pm_profile_id)
95
+ commit_for_redact(:delete, "profiles/#{pm_profile_id}", nil, nil)
96
+ end
97
+
98
+ def supports_scrubbing?
99
+ true
100
+ end
101
+
102
+ def scrub(transcript)
103
+ transcript.
104
+ gsub(%r((Authorization: Basic )[a-zA-Z0-9:_]+), '\1[FILTERED]').
105
+ gsub(%r(("cardNum\\?":\\?")\d+), '\1[FILTERED]').
106
+ gsub(%r(("cvv\\?":\\?")\d+), '\1[FILTERED]')
107
+ end
108
+
109
+ private
110
+
111
+ # Customer data can be included in transactions where the payment method is a credit card
112
+ # but should not be sent when the payment method is a token
113
+ def add_customer_data(post, creditcard, options)
114
+ post[:profile] = {}
115
+ post[:profile][:firstName] = creditcard.first_name
116
+ post[:profile][:lastName] = creditcard.last_name
117
+ post[:profile][:email] = options[:email] if options[:email]
118
+ post[:customerIp] = options[:ip] if options[:ip]
119
+ end
120
+
121
+ def add_billing_address(post, options)
122
+ return unless options[:billing_address] || options[:address]
123
+
124
+ address = options[:billing_address] || options[:address]
125
+ post[:billingDetails] = {}
126
+ post[:billingDetails][:street] = address[:address1]
127
+ post[:billingDetails][:city] = address[:city]
128
+ post[:billingDetails][:state] = address[:state]
129
+ post[:billingDetails][:country] = address[:country]
130
+ post[:billingDetails][:zip] = address[:zip]
131
+ post[:billingDetails][:phone] = address[:phone]
132
+ end
133
+
134
+ # The add_address_for_vaulting method is applicable to the store method, as the APIs address
135
+ # object is formatted differently from the standard transaction billing address
136
+ def add_address_for_vaulting(post, options)
137
+ return unless options[:billing_address || options[:address]]
138
+
139
+ address = options[:billing_address] || options[:address]
140
+ post[:billingAddress] = {}
141
+ post[:billingAddress][:street] = address[:address1]
142
+ post[:billingAddress][:city] = address[:city]
143
+ post[:billingAddress][:zip] = address[:zip]
144
+ post[:billingAddress][:country] = address[:country]
145
+ post[:billingAddress][:state] = address[:state] if address[:state]
146
+ end
147
+
148
+ # This data is specific to creating a profile at the gateway's vault level
149
+ def add_profile_data(post, payment, options)
150
+ address = options[:billing_address] || options[:address]
151
+
152
+ post[:firstName] = payment.first_name
153
+ post[:lastName] = payment.last_name
154
+ post[:dateOfBirth] = {}
155
+ post[:dateOfBirth][:year] = options[:date_of_birth][:year]
156
+ post[:dateOfBirth][:month] = options[:date_of_birth][:month]
157
+ post[:dateOfBirth][:day] = options[:date_of_birth][:day]
158
+ post[:email] = options[:email] if options[:email]
159
+ post[:phone] = (address[:phone] || options[:phone]) if address[:phone] || options[:phone]
160
+ post[:ip] = options[:ip] if options[:ip]
161
+ end
162
+
163
+ def add_store_data(post, payment, options)
164
+ post[:merchantCustomerId] = options[:customer_id] || SecureRandom.hex(12)
165
+ post[:locale] = options[:locale] || 'en_US'
166
+ post[:card][:holderName] = payment.name
167
+ end
168
+
169
+ # Paysafe expects minor units so we are not calling amount method on money parameter
170
+ def add_invoice(post, money, options)
171
+ post[:amount] = money
172
+ end
173
+
174
+ def add_payment(post, payment)
175
+ if payment.is_a?(String)
176
+ post[:card] = {}
177
+ post[:card][:paymentToken] = payment
178
+ else
179
+ post[:card] = { cardExpiry: {} }
180
+ post[:card][:cardNum] = payment.number
181
+ post[:card][:cardExpiry][:month] = payment.month
182
+ post[:card][:cardExpiry][:year] = payment.year
183
+ post[:card][:cvv] = payment.verification_value
184
+ end
185
+ end
186
+
187
+ def add_merchant_details(post, options)
188
+ return unless options[:merchant_descriptor]
189
+
190
+ post[:merchantDescriptor] = {}
191
+ post[:merchantDescriptor][:dynamicDescriptor] = options[:merchant_descriptor][:dynamic_descriptor] if options[:merchant_descriptor][:dynamic_descriptor]
192
+ post[:merchantDescriptor][:phone] = options[:merchant_descriptor][:phone] if options[:merchant_descriptor][:phone]
193
+ end
194
+
195
+ def add_three_d_secure(post, payment, options)
196
+ three_d_secure = options[:three_d_secure]
197
+
198
+ post[:authentication] = {}
199
+ post[:authentication][:eci] = three_d_secure[:eci]
200
+ post[:authentication][:cavv] = three_d_secure[:cavv]
201
+ post[:authentication][:xid] = three_d_secure[:xid] if three_d_secure[:xid]
202
+ post[:authentication][:threeDSecureVersion] = three_d_secure[:version]
203
+ post[:authentication][:directoryServerTransactionId] = three_d_secure[:ds_transaction_id] unless payment.is_a?(String) || payment.brand != 'mastercard'
204
+ end
205
+
206
+ def parse(body)
207
+ JSON.parse(body)
208
+ end
209
+
210
+ def commit(method, action, parameters, options)
211
+ url = url(action)
212
+ raw_response = ssl_request(method, url, post_data(parameters, options), headers)
213
+ response = parse(raw_response)
214
+ success = success_from(response)
215
+
216
+ Response.new(
217
+ success,
218
+ message_from(success, response),
219
+ response,
220
+ authorization: authorization_from(response),
221
+ avs_result: AVSResult.new(code: response['avsResponse']),
222
+ cvv_result: CVVResult.new(response['cvvVerification']),
223
+ test: test?,
224
+ error_code: success ? nil : error_code_from(response)
225
+ )
226
+ end
227
+
228
+ def commit_for_redact(method, action, parameters, options)
229
+ url = url(action)
230
+ response = raw_ssl_request(method, url, post_data(parameters, options), headers)
231
+ success = true if response.code == '200'
232
+
233
+ Response.new(
234
+ success,
235
+ message: response.message
236
+ )
237
+ end
238
+
239
+ def headers
240
+ {
241
+ 'Content-Type' => 'application/json',
242
+ 'Authorization' => "Basic #{Base64.strict_encode64(@options[:api_key].to_s)}"
243
+ }
244
+ end
245
+
246
+ def url(action, options = {})
247
+ base_url = (test? ? test_url : live_url)
248
+
249
+ if action.include? 'profiles'
250
+ "#{base_url}/customervault/v1/#{action}"
251
+ else
252
+ "#{base_url}/cardpayments/v1/accounts/#{@options[:account_id]}/#{action}"
253
+ end
254
+ end
255
+
256
+ def success_from(response)
257
+ return false if response['status'] == 'FAILED' || response['error']
258
+
259
+ true
260
+ end
261
+
262
+ def message_from(success, response)
263
+ return response['status'] unless response['error']
264
+
265
+ "Error(s)- code:#{response['error']['code']}, message:#{response['error']['message']}"
266
+ end
267
+
268
+ def authorization_from(response)
269
+ response['id']
270
+ end
271
+
272
+ def post_data(parameters = {}, options = {})
273
+ return unless parameters.present?
274
+
275
+ parameters[:merchantRefNum] = options[:merchant_ref_num] || SecureRandom.hex(16).to_s
276
+
277
+ parameters.to_json
278
+ end
279
+
280
+ def error_code_from(response)
281
+ return unless response['error']
282
+
283
+ response['error']['code']
284
+ end
285
+
286
+ def handle_response(response)
287
+ response.body
288
+ end
289
+ end
290
+ end
291
+ end
@@ -208,7 +208,7 @@ module ActiveMerchant #:nodoc:
208
208
  buyer[:merchantBuyerId] = buyer_hash[:merchant_buyer_id]
209
209
  buyer[:cnpj] = buyer_hash[:cnpj] if @options[:payment_country] == 'BR'
210
210
  buyer[:emailAddress] = buyer_hash[:email]
211
- buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone] if options[:shipping_address]) || ''
211
+ buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
212
212
  buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
213
213
  else
214
214
  buyer[:fullName] = payment_method.name.strip
@@ -217,7 +217,7 @@ module ActiveMerchant #:nodoc:
217
217
  buyer[:merchantBuyerId] = options[:merchant_buyer_id]
218
218
  buyer[:cnpj] = options[:cnpj] if @options[:payment_country] == 'BR'
219
219
  buyer[:emailAddress] = options[:email]
220
- buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone] if options[:shipping_address]) || ''
220
+ buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
221
221
  buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
222
222
  end
223
223
  post[:transaction][:order][:buyer] = buyer
@@ -233,7 +233,7 @@ module ActiveMerchant #:nodoc:
233
233
  shipping_address[:state] = address[:state]
234
234
  shipping_address[:country] = address[:country]
235
235
  shipping_address[:postalCode] = address[:zip]
236
- shipping_address[:phone] = address[:phone]
236
+ shipping_address[:phone] = address[:phone_number]
237
237
  shipping_address
238
238
  end
239
239
 
@@ -203,7 +203,7 @@ 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]
@@ -222,7 +222,7 @@ module ActiveMerchant #:nodoc:
222
222
  add_order(data, options[:order_id])
223
223
  add_payment(data, payment)
224
224
  add_external_mpi_fields(data, options)
225
- add_threeds(data, options) if options[:execute_threed]
225
+ add_three_ds_data(data, options) if options[:execute_threed]
226
226
  add_stored_credential_options(data, options)
227
227
  data[:description] = options[:description]
228
228
  data[:store_in_vault] = options[:store]
@@ -312,7 +312,7 @@ module ActiveMerchant #:nodoc:
312
312
  test? ? test_url : live_url
313
313
  end
314
314
 
315
- def threeds_url
315
+ def webservice_url
316
316
  test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2' : 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
317
317
  end
318
318
 
@@ -372,43 +372,51 @@ module ActiveMerchant #:nodoc:
372
372
  end
373
373
  end
374
374
 
375
- def add_threeds(data, options)
376
- 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
377
377
  end
378
378
 
379
- def determine_3ds_action(threeds_hash)
380
- return 'iniciaPeticion' if threeds_hash[:threeDSInfo] == 'CardData'
381
- return 'trataPeticion' if threeds_hash[:threeDSInfo] == 'AuthenticationData' ||
382
- 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'
383
389
  end
384
390
 
385
391
  def commit(data, options = {})
386
- if data[:threeds]
387
- 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
+
388
397
  request = <<-REQUEST
389
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" >
390
399
  <soapenv:Header/>
391
400
  <soapenv:Body>
392
- <intf:#{action} xmlns:intf="http://webservice.sis.sermepa.es">
401
+ <intf:#{peticion_type} xmlns:intf="http://webservice.sis.sermepa.es">
393
402
  <intf:datoEntrada>
394
- <![CDATA[#{xml_request_from(data, options)}]]>
403
+ <![CDATA[#{xmlreq}]]>
395
404
  </intf:datoEntrada>
396
- </intf:#{action}>
405
+ </intf:#{peticion_type}>
397
406
  </soapenv:Body>
398
407
  </soapenv:Envelope>
399
408
  REQUEST
400
- parse(ssl_post(threeds_url, request, headers(action)), action)
409
+ parse(ssl_post(webservice_url, request, headers(peticion_type)), peticion_type)
401
410
  else
402
- xmlreq = xml_request_from(data, options)
403
- parse(ssl_post(url, "entrada=#{CGI.escape(xmlreq)}", headers), action)
411
+ parse(ssl_post(url, "entrada=#{CGI.escape(xmlreq)}", headers), peticion_type)
404
412
  end
405
413
  end
406
414
 
407
- def headers(action = nil)
408
- if action
415
+ def headers(peticion_type = nil)
416
+ if peticion_type
409
417
  {
410
418
  'Content-Type' => 'text/xml',
411
- 'SOAPAction' => action
419
+ 'SOAPAction' => peticion_type
412
420
  }
413
421
  else
414
422
  {
@@ -470,14 +478,9 @@ module ActiveMerchant #:nodoc:
470
478
  xml.target!
471
479
  end
472
480
 
473
- # Template Method to allow AM API clients to override decision to escape, based on their own criteria.
474
- def escape_special_chars?(data, options = {})
475
- data[:threeds]
476
- end
477
-
478
481
  def build_merchant_data(xml, data, options = {})
479
482
  # See https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2/wsdl/SerClsWSEntradaV2.wsdl
480
- # (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)
481
484
  xml.DATOSENTRADA do
482
485
  # Basic elements
483
486
  xml.DS_Version 0.1
@@ -485,7 +488,7 @@ module ActiveMerchant #:nodoc:
485
488
  xml.DS_MERCHANT_AMOUNT data[:amount]
486
489
  xml.DS_MERCHANT_ORDER data[:order_id]
487
490
  xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
488
- if data[:description] && escape_special_chars?(data, options)
491
+ if data[:description] && use_webservice_endpoint?(data, options)
489
492
  xml.DS_MERCHANT_PRODUCTDESCRIPTION CGI.escape(data[:description])
490
493
  else
491
494
  xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
@@ -494,17 +497,17 @@ module ActiveMerchant #:nodoc:
494
497
  xml.DS_MERCHANT_MERCHANTCODE @options[:login]
495
498
  xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
496
499
 
497
- action = determine_3ds_action(data[:threeds]) if data[:threeds]
498
- if action == 'iniciaPeticion' && data[:sca_exemption]
500
+ peticion_type = determine_peticion_type(data) if data[:three_ds_data]
501
+ if peticion_type == 'iniciaPeticion' && data[:sca_exemption]
499
502
  xml.DS_MERCHANT_EXCEP_SCA 'Y'
500
503
  else
501
504
  xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
502
- xml.DS_MERCHANT_DIRECTPAYMENT data[:sca_exemption_direct_payment_enabled] if data[:sca_exemption_direct_payment_enabled]
505
+ xml.DS_MERCHANT_DIRECTPAYMENT data[:sca_exemption_direct_payment_enabled] || 'true' if data[:sca_exemption] == 'MIT'
503
506
  end
504
507
 
505
508
  # Only when card is present
506
509
  if data[:card]
507
- if data[:card][:name] && escape_special_chars?(data, options)
510
+ if data[:card][:name] && use_webservice_endpoint?(data, options)
508
511
  xml.DS_MERCHANT_TITULAR CGI.escape(data[:card][:name])
509
512
  else
510
513
  xml.DS_MERCHANT_TITULAR data[:card][:name]
@@ -525,7 +528,7 @@ module ActiveMerchant #:nodoc:
525
528
  # Requires account configuration to be able to use
526
529
  xml.DS_MERCHANT_DIRECTPAYMENT 'moto' if options.dig(:moto) && options.dig(:metadata, :manual_entry)
527
530
 
528
- 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]
529
532
 
530
533
  if options[:stored_credential]
531
534
  xml.DS_MERCHANT_COF_INI data[:DS_MERCHANT_COF_INI]