activemerchant 1.121.0 → 1.123.0

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