activemerchant 1.98.0 → 1.99.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.
- checksums.yaml +4 -4
- data/CHANGELOG +25 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +35 -6
- data/lib/active_merchant/billing/gateways/beanstream.rb +9 -6
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/credorax.rb +40 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +32 -8
- data/lib/active_merchant/billing/gateways/decidir.rb +13 -1
- data/lib/active_merchant/billing/gateways/mastercard.rb +30 -5
- data/lib/active_merchant/billing/gateways/mundipagg.rb +32 -5
- data/lib/active_merchant/billing/gateways/payflow.rb +24 -12
- data/lib/active_merchant/billing/gateways/redsys.rb +113 -30
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -1
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +6 -2
- data/lib/active_merchant/billing/gateways/tns.rb +10 -5
- data/lib/active_merchant/billing/gateways/worldpay.rb +13 -2
- data/lib/active_merchant/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbb76da56e87639a3f9129d70297b78a0edabe9faf2300e682e06e872e019419
|
4
|
+
data.tar.gz: 94cb0693e867b03071fe55a7e71b3cfbaf53a7c340d480f24108948822e9e1e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa96ed1337c57fa00d0405ff07a70b9423bac6a26ec69fde450d73bc9cabfc0ae27b75a46faddcdf3e79f2198db8214e8e6c5926468f0acb999bef43fc220a73
|
7
|
+
data.tar.gz: f672640992309d545629a41e4f89d505732d0bb88559648a96935ef01293bcff737de41c8a7b8992993dafdfdb71d29bcbf8b85133c3d9ae5311f7b720b7c9c7
|
data/CHANGELOG
CHANGED
@@ -1,6 +1,31 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
3
|
== HEAD
|
4
|
+
== Version 1.99.0 (Sep 26, 2019)
|
5
|
+
* Adyen: Add functionality to set 3DS exemptions via API [britth] #3331
|
6
|
+
* Adyen: Send "NA" instead of "N/A" [leila-alderman] #3339
|
7
|
+
* Stripe Payment Intents: Set application fee or transfer amount on capture [britth] #3340
|
8
|
+
* TNS: Support Europe endpoint [curiousepic] #3346
|
9
|
+
* Redsys: Add 3DS support to gateway [britth] #3336
|
10
|
+
* Worldpay: Allow multiple refunds per authorization [jknipp] #3349
|
11
|
+
* MercadoPago: Add remote and unit tests for Naranja card [hdeters] #3345
|
12
|
+
* CyberSource: Pass commerce indicator if present [curiousepic] #3350
|
13
|
+
* Worldpay: Add 3DS2 Support [nfarve] #3344
|
14
|
+
* Credorax: Add 3DS 2.0 [nfarve] #3342
|
15
|
+
* TNS: Update verison and support pay mode [curiousepic] #3355
|
16
|
+
* Stripe: Add supported countries [therufs] #3358
|
17
|
+
* Stripe Payment Intents: Add supported countries [therufs] #3359
|
18
|
+
* Mundipagg: Append error messages to the message response field [jasonxp] #3353
|
19
|
+
* Redsys: Add ability to pass sca_exemption and moto fields to request exemptions [britth] #3354
|
20
|
+
* Credorax: Add A Mandatory 3DS field [nfarve] #3360
|
21
|
+
* CyberSource: Support 3DS2 pass-through fields [curiousepic] #3363
|
22
|
+
* Credorax: Add support for MOTO flagging [britth] #3366
|
23
|
+
* Credorax: Enable selecting a processor [leila-alderman] #3302
|
24
|
+
* Adyen: Add Cabal card [leila-alderman] #3361
|
25
|
+
* Decidir: Add remote tests for Cabal and Naranja [leila-alderman] #3337
|
26
|
+
* Payflow: Pass correct field in Status for 3DS in Payflow [nebdil] #3362
|
27
|
+
* CyberSource: Use 3DS hash for enrolled field [curiousepic] #3371
|
28
|
+
|
4
29
|
== Version 1.98.0 (Sep 9, 2019)
|
5
30
|
* Stripe Payment Intents: Add new gateway [britth] #3290
|
6
31
|
* Stripe: Send cardholder name and address when creating sources for 3DS 1.0 [jknipp] #3300
|
@@ -10,7 +10,7 @@ module ActiveMerchant #:nodoc:
|
|
10
10
|
self.supported_countries = ['AT', 'AU', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HK', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SG', 'SK', 'SI', 'US']
|
11
11
|
self.default_currency = 'USD'
|
12
12
|
self.currencies_without_fractions = %w(CVE DJF GNF IDR JPY KMF KRW PYG RWF UGX VND VUV XAF XOF XPF)
|
13
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo, :naranja]
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo, :naranja, :cabal]
|
14
14
|
|
15
15
|
self.money_format = :cents
|
16
16
|
|
@@ -97,7 +97,14 @@ module ActiveMerchant #:nodoc:
|
|
97
97
|
add_stored_credentials(post, credit_card, options)
|
98
98
|
add_recurring_contract(post, options)
|
99
99
|
add_address(post, options)
|
100
|
-
|
100
|
+
|
101
|
+
initial_response = commit('authorise', post, options)
|
102
|
+
|
103
|
+
if initial_response.success? && card_not_stored?(initial_response)
|
104
|
+
unsupported_failure_response(initial_response)
|
105
|
+
else
|
106
|
+
initial_response
|
107
|
+
end
|
101
108
|
end
|
102
109
|
|
103
110
|
def verify(credit_card, options={})
|
@@ -229,17 +236,17 @@ module ActiveMerchant #:nodoc:
|
|
229
236
|
return unless post[:card]&.kind_of?(Hash)
|
230
237
|
if (address = options[:billing_address] || options[:address]) && address[:country]
|
231
238
|
post[:billingAddress] = {}
|
232
|
-
post[:billingAddress][:street] = address[:address1] || '
|
233
|
-
post[:billingAddress][:houseNumberOrName] = address[:address2] || '
|
239
|
+
post[:billingAddress][:street] = address[:address1] || 'NA'
|
240
|
+
post[:billingAddress][:houseNumberOrName] = address[:address2] || 'NA'
|
234
241
|
post[:billingAddress][:postalCode] = address[:zip] if address[:zip]
|
235
|
-
post[:billingAddress][:city] = address[:city] || '
|
242
|
+
post[:billingAddress][:city] = address[:city] || 'NA'
|
236
243
|
post[:billingAddress][:stateOrProvince] = get_state(address)
|
237
244
|
post[:billingAddress][:country] = address[:country] if address[:country]
|
238
245
|
end
|
239
246
|
end
|
240
247
|
|
241
248
|
def get_state(address)
|
242
|
-
address[:state] && !address[:state].blank? ? address[:state] : '
|
249
|
+
address[:state] && !address[:state].blank? ? address[:state] : 'NA'
|
243
250
|
end
|
244
251
|
|
245
252
|
def add_invoice(post, money, options)
|
@@ -336,6 +343,11 @@ module ActiveMerchant #:nodoc:
|
|
336
343
|
add_browser_info(three_ds_2_options[:browser_info], post)
|
337
344
|
post[:threeDS2RequestData] = { deviceChannel: device_channel, notificationURL: three_ds_2_options[:notification_url] }
|
338
345
|
end
|
346
|
+
|
347
|
+
if options.has_key?(:execute_threed)
|
348
|
+
post[:additionalData][:executeThreeD] = options[:execute_threed]
|
349
|
+
post[:additionalData][:scaExemption] = options[:sca_exemption] if options[:sca_exemption]
|
350
|
+
end
|
339
351
|
else
|
340
352
|
return unless options[:execute_threed] || options[:threed_dynamic]
|
341
353
|
post[:browserInfo] = { userAgent: options[:user_agent], acceptHeader: options[:accept_header] }
|
@@ -498,6 +510,23 @@ module ActiveMerchant #:nodoc:
|
|
498
510
|
userAgent: browser_info[:user_agent]
|
499
511
|
}
|
500
512
|
end
|
513
|
+
|
514
|
+
def unsupported_failure_response(initial_response)
|
515
|
+
Response.new(
|
516
|
+
false,
|
517
|
+
'Recurring transactions are not supported for this card type.',
|
518
|
+
initial_response.params,
|
519
|
+
authorization: initial_response.authorization,
|
520
|
+
test: initial_response.test,
|
521
|
+
error_code: initial_response.error_code,
|
522
|
+
avs_result: initial_response.avs_result,
|
523
|
+
cvv_result: initial_response.cvv_result[:code]
|
524
|
+
)
|
525
|
+
end
|
526
|
+
|
527
|
+
def card_not_stored?(response)
|
528
|
+
response.authorization ? response.authorization.split('#')[2].nil? : true
|
529
|
+
end
|
501
530
|
end
|
502
531
|
end
|
503
532
|
end
|
@@ -93,12 +93,15 @@ module ActiveMerchant #:nodoc:
|
|
93
93
|
|
94
94
|
def void(authorization, options = {})
|
95
95
|
reference, amount, type = split_auth(authorization)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
if type == TRANSACTIONS[:authorization]
|
97
|
+
capture(0, authorization, options)
|
98
|
+
else
|
99
|
+
post = {}
|
100
|
+
add_reference(post, reference)
|
101
|
+
add_original_amount(post, amount)
|
102
|
+
add_transaction_type(post, void_action(type))
|
103
|
+
commit(post)
|
104
|
+
end
|
102
105
|
end
|
103
106
|
|
104
107
|
def verify(source, options={})
|
@@ -317,7 +317,7 @@ module ActiveMerchant #:nodoc:
|
|
317
317
|
post[:status] = options[:status]
|
318
318
|
|
319
319
|
billing_address = options[:billing_address] || options[:address]
|
320
|
-
post[:trnCardOwner] = billing_address[:name]
|
320
|
+
post[:trnCardOwner] = billing_address ? billing_address[:name] : nil
|
321
321
|
end
|
322
322
|
|
323
323
|
def add_recurring_amount(post, money)
|
@@ -135,6 +135,7 @@ module ActiveMerchant #:nodoc:
|
|
135
135
|
add_echo(post, options)
|
136
136
|
add_submerchant_id(post, options)
|
137
137
|
add_transaction_type(post, options)
|
138
|
+
add_processor(post, options)
|
138
139
|
|
139
140
|
commit(:purchase, post)
|
140
141
|
end
|
@@ -149,6 +150,7 @@ module ActiveMerchant #:nodoc:
|
|
149
150
|
add_echo(post, options)
|
150
151
|
add_submerchant_id(post, options)
|
151
152
|
add_transaction_type(post, options)
|
153
|
+
add_processor(post, options)
|
152
154
|
|
153
155
|
commit(:authorize, post)
|
154
156
|
end
|
@@ -160,6 +162,7 @@ module ActiveMerchant #:nodoc:
|
|
160
162
|
add_customer_data(post, options)
|
161
163
|
add_echo(post, options)
|
162
164
|
add_submerchant_id(post, options)
|
165
|
+
add_processor(post, options)
|
163
166
|
|
164
167
|
commit(:capture, post)
|
165
168
|
end
|
@@ -171,6 +174,7 @@ module ActiveMerchant #:nodoc:
|
|
171
174
|
add_echo(post, options)
|
172
175
|
add_submerchant_id(post, options)
|
173
176
|
post[:a1] = generate_unique_id
|
177
|
+
add_processor(post, options)
|
174
178
|
|
175
179
|
commit(:void, post, reference_action)
|
176
180
|
end
|
@@ -182,6 +186,7 @@ module ActiveMerchant #:nodoc:
|
|
182
186
|
add_customer_data(post, options)
|
183
187
|
add_echo(post, options)
|
184
188
|
add_submerchant_id(post, options)
|
189
|
+
add_processor(post, options)
|
185
190
|
|
186
191
|
commit(:refund, post)
|
187
192
|
end
|
@@ -195,6 +200,7 @@ module ActiveMerchant #:nodoc:
|
|
195
200
|
add_echo(post, options)
|
196
201
|
add_submerchant_id(post, options)
|
197
202
|
add_transaction_type(post, options)
|
203
|
+
add_processor(post, options)
|
198
204
|
|
199
205
|
commit(:credit, post)
|
200
206
|
end
|
@@ -270,6 +276,32 @@ module ActiveMerchant #:nodoc:
|
|
270
276
|
def add_3d_secure(post, options)
|
271
277
|
if options[:eci] && options[:xid]
|
272
278
|
add_3d_secure_1_data(post, options)
|
279
|
+
elsif options[:execute_threed] && options[:three_ds_2]
|
280
|
+
three_ds_2_options = options[:three_ds_2]
|
281
|
+
browser_info = three_ds_2_options[:browser_info]
|
282
|
+
post[:'3ds_initiate'] = options[:three_ds_initiate] || '01'
|
283
|
+
post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
|
284
|
+
post[:'3ds_channel'] = '02'
|
285
|
+
post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
|
286
|
+
post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
|
287
|
+
post[:'3ds_version'] = options[:three_ds_version] if options[:three_ds_version]
|
288
|
+
post[:d5] = browser_info[:user_agent]
|
289
|
+
post[:'3ds_transtype'] = options[:transaction_type] || '01'
|
290
|
+
post[:'3ds_browsertz'] = browser_info[:timezone]
|
291
|
+
post[:'3ds_browserscreenwidth'] = browser_info[:width]
|
292
|
+
post[:'3ds_browserscreenheight'] = browser_info[:height]
|
293
|
+
post[:'3ds_browsercolordepth'] = browser_info[:depth]
|
294
|
+
post[:d6] = browser_info[:language]
|
295
|
+
post[:'3ds_browserjavaenabled'] = browser_info[:java]
|
296
|
+
post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
|
297
|
+
if (shipping_address = options[:shipping_address])
|
298
|
+
post[:'3ds_shipaddrstate'] = shipping_address[:state]
|
299
|
+
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
|
300
|
+
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
|
301
|
+
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
|
302
|
+
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
|
303
|
+
post[:'3ds_shipaddrcity'] = shipping_address[:city]
|
304
|
+
end
|
273
305
|
elsif options[:three_d_secure]
|
274
306
|
add_normalized_3d_secure_2_data(post, options)
|
275
307
|
end
|
@@ -306,6 +338,12 @@ module ActiveMerchant #:nodoc:
|
|
306
338
|
|
307
339
|
def add_transaction_type(post, options)
|
308
340
|
post[:a9] = options[:transaction_type] if options[:transaction_type]
|
341
|
+
post[:a2] = '3' if options.dig(:metadata, :manual_entry)
|
342
|
+
end
|
343
|
+
|
344
|
+
def add_processor(post, options)
|
345
|
+
post[:r1] = options[:processor] || 'CREDORAX'
|
346
|
+
post[:r2] = options[:processor_merchant_id] if options[:processor_merchant_id]
|
309
347
|
end
|
310
348
|
|
311
349
|
ACTIONS = {
|
@@ -317,7 +355,8 @@ module ActiveMerchant #:nodoc:
|
|
317
355
|
credit: '6',
|
318
356
|
purchase_void: '7',
|
319
357
|
refund_void: '8',
|
320
|
-
capture_void: '9'
|
358
|
+
capture_void: '9',
|
359
|
+
threeds_completion: '92'
|
321
360
|
}
|
322
361
|
|
323
362
|
def commit(action, params, reference_action = nil)
|
@@ -25,8 +25,8 @@ module ActiveMerchant #:nodoc:
|
|
25
25
|
self.live_url = 'https://ics2wsa.ic3.com/commerce/1.x/transactionProcessor'
|
26
26
|
|
27
27
|
# Schema files can be found here: https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/
|
28
|
-
TEST_XSD_VERSION = '1.
|
29
|
-
PRODUCTION_XSD_VERSION = '1.
|
28
|
+
TEST_XSD_VERSION = '1.159'
|
29
|
+
PRODUCTION_XSD_VERSION = '1.159'
|
30
30
|
|
31
31
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro, :elo]
|
32
32
|
self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
|
@@ -258,6 +258,7 @@ module ActiveMerchant #:nodoc:
|
|
258
258
|
def build_auth_request(money, creditcard_or_reference, options)
|
259
259
|
xml = Builder::XmlMarkup.new :indent => 2
|
260
260
|
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
261
|
+
add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
|
261
262
|
add_decision_manager_fields(xml, options)
|
262
263
|
add_mdd_fields(xml, options)
|
263
264
|
add_auth_service(xml, creditcard_or_reference, options)
|
@@ -295,6 +296,7 @@ module ActiveMerchant #:nodoc:
|
|
295
296
|
def build_purchase_request(money, payment_method_or_reference, options)
|
296
297
|
xml = Builder::XmlMarkup.new :indent => 2
|
297
298
|
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
299
|
+
add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
|
298
300
|
add_decision_manager_fields(xml, options)
|
299
301
|
add_mdd_fields(xml, options)
|
300
302
|
if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
|
@@ -530,19 +532,41 @@ module ActiveMerchant #:nodoc:
|
|
530
532
|
add_auth_network_tokenization(xml, payment_method, options)
|
531
533
|
else
|
532
534
|
xml.tag! 'ccAuthService', {'run' => 'true'} do
|
533
|
-
|
535
|
+
if options[:three_d_secure]
|
536
|
+
add_normalized_threeds_2_data(xml, payment_method, options)
|
537
|
+
else
|
538
|
+
indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options)
|
539
|
+
xml.tag!('commerceIndicator', indicator) if indicator
|
540
|
+
end
|
534
541
|
end
|
535
542
|
end
|
536
543
|
end
|
537
544
|
|
538
|
-
def
|
539
|
-
|
540
|
-
|
541
|
-
|
545
|
+
def add_normalized_threeds_2_data(xml, payment_method, options)
|
546
|
+
threeds_2_options = options[:three_d_secure]
|
547
|
+
|
548
|
+
xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && card_brand(payment_method).to_sym != :master
|
549
|
+
xml.tag!('cavvAlgorithm', threeds_2_options[:cavv_algorithm]) if threeds_2_options[:cavv_algorithm]
|
550
|
+
xml.tag!('paSpecificationVersion', threeds_2_options[:version]) if threeds_2_options[:version]
|
551
|
+
xml.tag!('directoryServerTransactionID', threeds_2_options[:ds_transaction_id]) if threeds_2_options[:ds_transaction_id]
|
552
|
+
xml.tag!('commerceIndicator', options[:commerce_indicator]) if options[:commerce_indicator]
|
553
|
+
xml.tag!('eciRaw', threeds_2_options[:eci]) if threeds_2_options[:eci]
|
554
|
+
xml.tag!('xid', threeds_2_options[:xid]) if threeds_2_options[:xid]
|
555
|
+
xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled]
|
556
|
+
xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status]
|
557
|
+
end
|
558
|
+
|
559
|
+
def add_threeds_2_ucaf_data(xml, payment_method, options)
|
560
|
+
return unless options[:three_d_secure] && card_brand(payment_method).to_sym == :master
|
561
|
+
|
562
|
+
xml.tag! 'ucaf' do
|
563
|
+
xml.tag!('authenticationData', options[:three_d_secure][:cavv])
|
564
|
+
xml.tag!('collectionIndicator', options[:collection_indicator]) if options[:collection_indicator]
|
542
565
|
end
|
543
566
|
end
|
544
567
|
|
545
|
-
def
|
568
|
+
def stored_credential_commerce_indicator(options)
|
569
|
+
return unless options[:stored_credential]
|
546
570
|
return if options[:stored_credential][:initial_transaction]
|
547
571
|
case options[:stored_credential][:reason_type]
|
548
572
|
when 'installment' then 'install'
|
@@ -106,7 +106,7 @@ module ActiveMerchant #:nodoc:
|
|
106
106
|
private
|
107
107
|
|
108
108
|
def add_auth_purchase_params(post, money, credit_card, options)
|
109
|
-
post[:payment_method_id] =
|
109
|
+
post[:payment_method_id] = add_payment_method_id(credit_card)
|
110
110
|
post[:site_transaction_id] = options[:order_id]
|
111
111
|
post[:bin] = credit_card.number[0..5]
|
112
112
|
post[:payment_type] = options[:payment_type] || 'single'
|
@@ -119,6 +119,18 @@ module ActiveMerchant #:nodoc:
|
|
119
119
|
add_payment(post, credit_card, options)
|
120
120
|
end
|
121
121
|
|
122
|
+
def add_payment_method_id(credit_card)
|
123
|
+
if options[:payment_method_id]
|
124
|
+
options[:payment_method_id].to_i
|
125
|
+
elsif CreditCard.brand?(credit_card.number) == 'cabal'
|
126
|
+
63
|
127
|
+
elsif CreditCard.brand?(credit_card.number) == 'naranja'
|
128
|
+
24
|
129
|
+
else
|
130
|
+
1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
122
134
|
def add_invoice(post, money, options)
|
123
135
|
add_amount(post, money, options)
|
124
136
|
post[:currency] = (options[:currency] || currency(money))
|
@@ -7,9 +7,20 @@ module ActiveMerchant
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def purchase(amount, payment_method, options={})
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
if options[:pay_mode]
|
11
|
+
post = new_post
|
12
|
+
add_invoice(post, amount, options)
|
13
|
+
add_reference(post, *new_authorization)
|
14
|
+
add_payment_method(post, payment_method)
|
15
|
+
add_customer_data(post, payment_method, options)
|
16
|
+
add_3dsecure_id(post, options)
|
17
|
+
|
18
|
+
commit('pay', post)
|
19
|
+
else
|
20
|
+
MultiResponse.run do |r|
|
21
|
+
r.process { authorize(amount, payment_method, options) }
|
22
|
+
r.process { capture(amount, r.authorization, options) }
|
23
|
+
end
|
13
24
|
end
|
14
25
|
end
|
15
26
|
|
@@ -206,9 +217,23 @@ module ActiveMerchant
|
|
206
217
|
|
207
218
|
def base_url
|
208
219
|
if test?
|
209
|
-
@options[:region]
|
220
|
+
case @options[:region]
|
221
|
+
when 'asia_pacific'
|
222
|
+
test_ap_url
|
223
|
+
when 'europe'
|
224
|
+
test_eu_url
|
225
|
+
when 'north_america', nil
|
226
|
+
test_na_url
|
227
|
+
end
|
210
228
|
else
|
211
|
-
@options[:region]
|
229
|
+
case @options[:region]
|
230
|
+
when 'asia_pacific'
|
231
|
+
live_ap_url
|
232
|
+
when 'europe'
|
233
|
+
live_eu_url
|
234
|
+
when 'north_america', nil
|
235
|
+
live_na_url
|
236
|
+
end
|
212
237
|
end
|
213
238
|
end
|
214
239
|
|
@@ -249,7 +249,8 @@ module ActiveMerchant #:nodoc:
|
|
249
249
|
error_code: error_code_from(response)
|
250
250
|
)
|
251
251
|
rescue ResponseError => e
|
252
|
-
message =
|
252
|
+
message = get_error_messages(e)
|
253
|
+
|
253
254
|
return Response.new(
|
254
255
|
false,
|
255
256
|
"#{STANDARD_ERROR_MESSAGE_MAPPING[e.response.code]} #{message}",
|
@@ -263,15 +264,41 @@ module ActiveMerchant #:nodoc:
|
|
263
264
|
%w[pending paid processing canceled active].include? response['status']
|
264
265
|
end
|
265
266
|
|
266
|
-
def get_error_message(error)
|
267
|
-
JSON.parse(error.response.body)['message']
|
268
|
-
end
|
269
|
-
|
270
267
|
def message_from(response)
|
268
|
+
return gateway_response_errors(response) if gateway_response_errors?(response)
|
271
269
|
return response['message'] if response['message']
|
272
270
|
return response['last_transaction']['acquirer_message'] if response['last_transaction']
|
273
271
|
end
|
274
272
|
|
273
|
+
def get_error_messages(error)
|
274
|
+
parsed_response_body = parse(error.response.body)
|
275
|
+
message = parsed_response_body['message']
|
276
|
+
|
277
|
+
parsed_response_body['errors']&.each do |type, descriptions|
|
278
|
+
message += ' | '
|
279
|
+
message += descriptions.join(', ')
|
280
|
+
end
|
281
|
+
|
282
|
+
message
|
283
|
+
end
|
284
|
+
|
285
|
+
def gateway_response_errors?(response)
|
286
|
+
response.try(:[], 'last_transaction').try(:[], 'gateway_response').try(:[], 'errors').present?
|
287
|
+
end
|
288
|
+
|
289
|
+
def gateway_response_errors(response)
|
290
|
+
error_string = ''
|
291
|
+
|
292
|
+
response['last_transaction']['gateway_response']['errors']&.each do |error|
|
293
|
+
error.each do |key, value|
|
294
|
+
error_string += ' | ' unless error_string.blank?
|
295
|
+
error_string += value
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
error_string
|
300
|
+
end
|
301
|
+
|
275
302
|
def authorization_from(response, action)
|
276
303
|
return "#{response['customer']['id']}|#{response['id']}" if action == 'store'
|
277
304
|
response['id']
|
@@ -262,23 +262,35 @@ module ActiveMerchant #:nodoc:
|
|
262
262
|
xml.tag! 'NameOnCard', credit_card.first_name
|
263
263
|
xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
|
264
264
|
|
265
|
-
|
266
|
-
three_d_secure = options[:three_d_secure]
|
267
|
-
xml.tag! 'BuyerAuthResult' do
|
268
|
-
xml.tag! 'Status', three_d_secure[:status] unless three_d_secure[:status].blank?
|
269
|
-
xml.tag! 'AuthenticationId', three_d_secure[:authentication_id] unless three_d_secure[:authentication_id].blank?
|
270
|
-
xml.tag! 'PAReq', three_d_secure[:pareq] unless three_d_secure[:pareq].blank?
|
271
|
-
xml.tag! 'ACSUrl', three_d_secure[:acs_url] unless three_d_secure[:acs_url].blank?
|
272
|
-
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
273
|
-
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
274
|
-
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
275
|
-
end
|
276
|
-
end
|
265
|
+
add_three_d_secure(options, xml)
|
277
266
|
|
278
267
|
xml.tag! 'ExtData', 'Name' => 'LASTNAME', 'Value' => credit_card.last_name
|
279
268
|
end
|
280
269
|
end
|
281
270
|
|
271
|
+
def add_three_d_secure(options, xml)
|
272
|
+
if options[:three_d_secure]
|
273
|
+
three_d_secure = options[:three_d_secure]
|
274
|
+
xml.tag! 'BuyerAuthResult' do
|
275
|
+
authentication_status(three_d_secure, xml)
|
276
|
+
xml.tag! 'AuthenticationId', three_d_secure[:authentication_id] unless three_d_secure[:authentication_id].blank?
|
277
|
+
xml.tag! 'PAReq', three_d_secure[:pareq] unless three_d_secure[:pareq].blank?
|
278
|
+
xml.tag! 'ACSUrl', three_d_secure[:acs_url] unless three_d_secure[:acs_url].blank?
|
279
|
+
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
280
|
+
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
281
|
+
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def authentication_status(three_d_secure, xml)
|
287
|
+
if three_d_secure[:authentication_response_status].present?
|
288
|
+
xml.tag! 'Status', three_d_secure[:authentication_response_status]
|
289
|
+
elsif three_d_secure[:directory_response_status].present?
|
290
|
+
xml.tag! 'Status', three_d_secure[:directory_response_status]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
282
294
|
def credit_card_type(credit_card)
|
283
295
|
return '' if card_brand(credit_card).blank?
|
284
296
|
|
@@ -193,28 +193,32 @@ module ActiveMerchant #:nodoc:
|
|
193
193
|
requires!(options, :order_id)
|
194
194
|
|
195
195
|
data = {}
|
196
|
-
add_action(data, :purchase)
|
196
|
+
add_action(data, :purchase, options)
|
197
197
|
add_amount(data, money, options)
|
198
198
|
add_order(data, options[:order_id])
|
199
199
|
add_payment(data, payment)
|
200
|
+
add_threeds(data, options) if options[:execute_threed]
|
200
201
|
data[:description] = options[:description]
|
201
202
|
data[:store_in_vault] = options[:store]
|
203
|
+
data[:sca_exemption] = options[:sca_exemption]
|
202
204
|
|
203
|
-
commit data
|
205
|
+
commit data, options
|
204
206
|
end
|
205
207
|
|
206
208
|
def authorize(money, payment, options = {})
|
207
209
|
requires!(options, :order_id)
|
208
210
|
|
209
211
|
data = {}
|
210
|
-
add_action(data, :authorize)
|
212
|
+
add_action(data, :authorize, options)
|
211
213
|
add_amount(data, money, options)
|
212
214
|
add_order(data, options[:order_id])
|
213
215
|
add_payment(data, payment)
|
216
|
+
add_threeds(data, options) if options[:execute_threed]
|
214
217
|
data[:description] = options[:description]
|
215
218
|
data[:store_in_vault] = options[:store]
|
219
|
+
data[:sca_exemption] = options[:sca_exemption]
|
216
220
|
|
217
|
-
commit data
|
221
|
+
commit data, options
|
218
222
|
end
|
219
223
|
|
220
224
|
def capture(money, authorization, options = {})
|
@@ -225,7 +229,7 @@ module ActiveMerchant #:nodoc:
|
|
225
229
|
add_order(data, order_id)
|
226
230
|
data[:description] = options[:description]
|
227
231
|
|
228
|
-
commit data
|
232
|
+
commit data, options
|
229
233
|
end
|
230
234
|
|
231
235
|
def void(authorization, options = {})
|
@@ -236,7 +240,7 @@ module ActiveMerchant #:nodoc:
|
|
236
240
|
add_order(data, order_id)
|
237
241
|
data[:description] = options[:description]
|
238
242
|
|
239
|
-
commit data
|
243
|
+
commit data, options
|
240
244
|
end
|
241
245
|
|
242
246
|
def refund(money, authorization, options = {})
|
@@ -247,7 +251,7 @@ module ActiveMerchant #:nodoc:
|
|
247
251
|
add_order(data, order_id)
|
248
252
|
data[:description] = options[:description]
|
249
253
|
|
250
|
-
commit data
|
254
|
+
commit data, options
|
251
255
|
end
|
252
256
|
|
253
257
|
def verify(creditcard, options = {})
|
@@ -278,8 +282,8 @@ module ActiveMerchant #:nodoc:
|
|
278
282
|
|
279
283
|
private
|
280
284
|
|
281
|
-
def add_action(data, action)
|
282
|
-
data[:action] = transaction_code(action)
|
285
|
+
def add_action(data, action, options = {})
|
286
|
+
data[:action] = options[:execute_threed].present? ? '0' : transaction_code(action)
|
283
287
|
end
|
284
288
|
|
285
289
|
def add_amount(data, money, options)
|
@@ -295,6 +299,10 @@ module ActiveMerchant #:nodoc:
|
|
295
299
|
test? ? test_url : live_url
|
296
300
|
end
|
297
301
|
|
302
|
+
def threeds_url
|
303
|
+
test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2': 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
|
304
|
+
end
|
305
|
+
|
298
306
|
def add_payment(data, card)
|
299
307
|
if card.is_a?(String)
|
300
308
|
data[:credit_card_token] = card
|
@@ -311,21 +319,57 @@ module ActiveMerchant #:nodoc:
|
|
311
319
|
end
|
312
320
|
end
|
313
321
|
|
314
|
-
def
|
315
|
-
|
322
|
+
def add_threeds(data, options)
|
323
|
+
if options[:execute_threed] == true
|
324
|
+
data[:threeds] = {threeDSInfo: 'CardData'}
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def determine_3ds_action(threeds_hash)
|
329
|
+
return 'iniciaPeticion' if threeds_hash[:threeDSInfo] == 'CardData'
|
330
|
+
return 'trataPeticion' if threeds_hash[:threeDSInfo] == 'AuthenticationData' ||
|
331
|
+
threeds_hash[:threeDSInfo] == 'ChallengeResponse'
|
332
|
+
end
|
333
|
+
|
334
|
+
def commit(data, options = {})
|
335
|
+
if data[:threeds]
|
336
|
+
action = determine_3ds_action(data[:threeds])
|
337
|
+
request = <<-EOS
|
338
|
+
<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" >
|
339
|
+
<soapenv:Header/>
|
340
|
+
<soapenv:Body>
|
341
|
+
<intf:#{action} xmlns:intf="http://webservice.sis.sermepa.es">
|
342
|
+
<intf:datoEntrada>
|
343
|
+
<![CDATA[#{xml_request_from(data, options)}]]>
|
344
|
+
</intf:datoEntrada>
|
345
|
+
</intf:#{action}>
|
346
|
+
</soapenv:Body>
|
347
|
+
</soapenv:Envelope>
|
348
|
+
EOS
|
349
|
+
parse(ssl_post(threeds_url, request, headers(action)), action)
|
350
|
+
else
|
351
|
+
parse(ssl_post(url, "entrada=#{CGI.escape(xml_request_from(data, options))}", headers), action)
|
352
|
+
end
|
316
353
|
end
|
317
354
|
|
318
|
-
def headers
|
319
|
-
|
320
|
-
|
321
|
-
|
355
|
+
def headers(action=nil)
|
356
|
+
if action
|
357
|
+
{
|
358
|
+
'Content-Type' => 'text/xml',
|
359
|
+
'SOAPAction' => action
|
360
|
+
}
|
361
|
+
else
|
362
|
+
{
|
363
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
364
|
+
}
|
365
|
+
end
|
322
366
|
end
|
323
367
|
|
324
|
-
def xml_request_from(data)
|
368
|
+
def xml_request_from(data, options = {})
|
325
369
|
if sha256_authentication?
|
326
|
-
build_sha256_xml_request(data)
|
370
|
+
build_sha256_xml_request(data, options)
|
327
371
|
else
|
328
|
-
build_sha1_xml_request(data)
|
372
|
+
build_sha1_xml_request(data, options)
|
329
373
|
end
|
330
374
|
end
|
331
375
|
|
@@ -351,30 +395,30 @@ module ActiveMerchant #:nodoc:
|
|
351
395
|
Digest::SHA1.hexdigest(str)
|
352
396
|
end
|
353
397
|
|
354
|
-
def build_sha256_xml_request(data)
|
398
|
+
def build_sha256_xml_request(data, options = {})
|
355
399
|
xml = Builder::XmlMarkup.new
|
356
400
|
xml.instruct!
|
357
401
|
xml.REQUEST do
|
358
|
-
build_merchant_data(xml, data)
|
402
|
+
build_merchant_data(xml, data, options)
|
359
403
|
xml.DS_SIGNATUREVERSION 'HMAC_SHA256_V1'
|
360
|
-
xml.DS_SIGNATURE sign_request(merchant_data_xml(data), data[:order_id])
|
404
|
+
xml.DS_SIGNATURE sign_request(merchant_data_xml(data, options), data[:order_id])
|
361
405
|
end
|
362
406
|
xml.target!
|
363
407
|
end
|
364
408
|
|
365
|
-
def build_sha1_xml_request(data)
|
409
|
+
def build_sha1_xml_request(data, options = {})
|
366
410
|
xml = Builder::XmlMarkup.new :indent => 2
|
367
|
-
build_merchant_data(xml, data)
|
411
|
+
build_merchant_data(xml, data, options)
|
368
412
|
xml.target!
|
369
413
|
end
|
370
414
|
|
371
|
-
def merchant_data_xml(data)
|
415
|
+
def merchant_data_xml(data, options = {})
|
372
416
|
xml = Builder::XmlMarkup.new
|
373
|
-
build_merchant_data(xml, data)
|
417
|
+
build_merchant_data(xml, data, options)
|
374
418
|
xml.target!
|
375
419
|
end
|
376
420
|
|
377
|
-
def build_merchant_data(xml, data)
|
421
|
+
def build_merchant_data(xml, data, options = {})
|
378
422
|
xml.DATOSENTRADA do
|
379
423
|
# Basic elements
|
380
424
|
xml.DS_Version 0.1
|
@@ -383,9 +427,10 @@ module ActiveMerchant #:nodoc:
|
|
383
427
|
xml.DS_MERCHANT_ORDER data[:order_id]
|
384
428
|
xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
|
385
429
|
xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
|
386
|
-
xml.DS_MERCHANT_TERMINAL @options[:terminal]
|
430
|
+
xml.DS_MERCHANT_TERMINAL options[:terminal] || @options[:terminal]
|
387
431
|
xml.DS_MERCHANT_MERCHANTCODE @options[:login]
|
388
432
|
xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
|
433
|
+
xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
|
389
434
|
|
390
435
|
# Only when card is present
|
391
436
|
if data[:card]
|
@@ -398,22 +443,42 @@ module ActiveMerchant #:nodoc:
|
|
398
443
|
xml.DS_MERCHANT_IDENTIFIER data[:credit_card_token]
|
399
444
|
xml.DS_MERCHANT_DIRECTPAYMENT 'true'
|
400
445
|
end
|
446
|
+
|
447
|
+
# Set moto flag only if explicitly requested via moto field
|
448
|
+
# Requires account configuration to be able to use
|
449
|
+
if options.dig(:moto) && options.dig(:metadata, :manual_entry)
|
450
|
+
xml.DS_MERCHANT_DIRECTPAYMENT 'moto'
|
451
|
+
end
|
452
|
+
|
453
|
+
if data[:threeds]
|
454
|
+
xml.DS_MERCHANT_EMV3DS data[:threeds].to_json
|
455
|
+
end
|
401
456
|
end
|
402
457
|
end
|
403
458
|
|
404
|
-
def parse(data)
|
459
|
+
def parse(data, action)
|
405
460
|
params = {}
|
406
461
|
success = false
|
407
462
|
message = ''
|
408
463
|
options = @options.merge(:test => test?)
|
409
464
|
xml = Nokogiri::XML(data)
|
410
465
|
code = xml.xpath('//RETORNOXML/CODIGO').text
|
411
|
-
|
466
|
+
|
467
|
+
if ['iniciaPeticion', 'trataPeticion'].include?(action)
|
468
|
+
vxml = Nokogiri::XML(data).remove_namespaces!.xpath("//Envelope/Body/#{action}Response/#{action}Return").inner_text
|
469
|
+
xml = Nokogiri::XML(vxml)
|
470
|
+
node = (action == 'iniciaPeticion' ? 'INFOTARJETA' : 'OPERACION')
|
471
|
+
op = xml.xpath("//RETORNOXML/#{node}")
|
472
|
+
op.children.each do |element|
|
473
|
+
params[element.name.downcase.to_sym] = element.text
|
474
|
+
end
|
475
|
+
message = response_text_3ds(xml, params)
|
476
|
+
success = params.size > 0 && is_success_response?(params[:ds_response])
|
477
|
+
elsif code == '0'
|
412
478
|
op = xml.xpath('//RETORNOXML/OPERACION')
|
413
479
|
op.children.each do |element|
|
414
480
|
params[element.name.downcase.to_sym] = element.text
|
415
481
|
end
|
416
|
-
|
417
482
|
if validate_signature(params)
|
418
483
|
message = response_text(params[:ds_response])
|
419
484
|
options[:authorization] = build_authorization(params)
|
@@ -474,6 +539,20 @@ module ActiveMerchant #:nodoc:
|
|
474
539
|
RESPONSE_TEXTS[code] || 'Unkown code, please check in manual'
|
475
540
|
end
|
476
541
|
|
542
|
+
def response_text_3ds(xml, params)
|
543
|
+
code = xml.xpath('//RETORNOXML/CODIGO').text
|
544
|
+
message = ''
|
545
|
+
if code != '0'
|
546
|
+
message = "#{code} ERROR"
|
547
|
+
elsif params[:ds_emv3ds]
|
548
|
+
three_ds_data = JSON.parse(params[:ds_emv3ds])
|
549
|
+
message = three_ds_data['threeDSInfo']
|
550
|
+
elsif params[:ds_response]
|
551
|
+
message = response_text(params[:ds_response])
|
552
|
+
end
|
553
|
+
message
|
554
|
+
end
|
555
|
+
|
477
556
|
def is_success_response?(code)
|
478
557
|
(code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i)
|
479
558
|
end
|
@@ -523,6 +602,10 @@ module ActiveMerchant #:nodoc:
|
|
523
602
|
xml_signed_fields += data[:ds_cardnumber]
|
524
603
|
end
|
525
604
|
|
605
|
+
if data[:ds_emv3ds]
|
606
|
+
xml_signed_fields += data[:ds_emv3ds]
|
607
|
+
end
|
608
|
+
|
526
609
|
xml_signed_fields + data[:ds_transactiontype] + data[:ds_securepayment]
|
527
610
|
end
|
528
611
|
|
@@ -25,7 +25,7 @@ module ActiveMerchant #:nodoc:
|
|
25
25
|
|
26
26
|
DEFAULT_API_VERSION = '2015-04-07'
|
27
27
|
|
28
|
-
self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
|
28
|
+
self.supported_countries = %w(AT AU BE BR CA CH DE DK EE ES FI FR GB GR HK IE IT JP LT LU LV MX NL NO NZ PL PT SE SG SI SK US)
|
29
29
|
self.default_currency = 'USD'
|
30
30
|
self.money_format = :cents
|
31
31
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
# For the legacy API, see the Stripe gateway
|
7
7
|
class StripePaymentIntentsGateway < StripeGateway
|
8
8
|
|
9
|
-
self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
|
9
|
+
self.supported_countries = %w(AT AU BE BR CA CH DE DK EE ES FI FR GB GR HK IE IT JP LT LU LV MX NL NO NZ PL PT SE SG SI SK US)
|
10
10
|
|
11
11
|
ALLOWED_METHOD_STATES = %w[automatic manual].freeze
|
12
12
|
ALLOWED_CANCELLATION_REASONS = %w[duplicate fraudulent requested_by_customer abandoned].freeze
|
@@ -92,7 +92,11 @@ module ActiveMerchant #:nodoc:
|
|
92
92
|
def capture(money, intent_id, options = {})
|
93
93
|
post = {}
|
94
94
|
post[:amount_to_capture] = money
|
95
|
-
|
95
|
+
if options[:transfer_amount]
|
96
|
+
post[:transfer_data] = {}
|
97
|
+
post[:transfer_data][:amount] = options[:transfer_amount]
|
98
|
+
end
|
99
|
+
post[:application_fee_amount] = options[:application_fee] if options[:application_fee]
|
96
100
|
commit(:post, "payment_intents/#{intent_id}/capture", post, options)
|
97
101
|
end
|
98
102
|
|
@@ -3,13 +3,18 @@ module ActiveMerchant
|
|
3
3
|
class TnsGateway < Gateway
|
4
4
|
include MastercardGateway
|
5
5
|
|
6
|
-
class_attribute :live_na_url, :live_ap_url, :test_na_url, :test_ap_url
|
6
|
+
class_attribute :live_na_url, :live_ap_url, :live_eu_url, :test_na_url, :test_ap_url, :test_eu_url
|
7
7
|
|
8
|
-
|
9
|
-
self.test_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
|
8
|
+
VERSION = '52'
|
10
9
|
|
11
|
-
self.
|
12
|
-
self.
|
10
|
+
self.live_na_url = "https://secure.na.tnspayments.com/api/rest/version/#{VERSION}/"
|
11
|
+
self.test_na_url = "https://secure.na.tnspayments.com/api/rest/version/#{VERSION}/"
|
12
|
+
|
13
|
+
self.live_ap_url = "https://secure.ap.tnspayments.com/api/rest/version/#{VERSION}/"
|
14
|
+
self.test_ap_url = "https://secure.ap.tnspayments.com/api/rest/version/#{VERSION}/"
|
15
|
+
|
16
|
+
self.live_eu_url = "https://secure.eu.tnspayments.com/api/rest/version/#{VERSION}/"
|
17
|
+
self.test_eu_url = "https://secure.eu.tnspayments.com/api/rest/version/#{VERSION}/"
|
13
18
|
|
14
19
|
self.display_name = 'TNS'
|
15
20
|
self.homepage_url = 'http://www.tnsi.com/'
|
@@ -88,7 +88,7 @@ module ActiveMerchant #:nodoc:
|
|
88
88
|
def refund(money, authorization, options = {})
|
89
89
|
authorization = order_id_from_authorization(authorization.to_s)
|
90
90
|
response = MultiResponse.run do |r|
|
91
|
-
r.process { inquire_request(authorization, options, 'CAPTURED', 'SETTLED', 'SETTLED_BY_MERCHANT') }
|
91
|
+
r.process { inquire_request(authorization, options, 'CAPTURED', 'SETTLED', 'SETTLED_BY_MERCHANT') } unless options[:authorization_validated]
|
92
92
|
r.process { refund_request(money, authorization, options) }
|
93
93
|
end
|
94
94
|
|
@@ -208,6 +208,8 @@ module ActiveMerchant #:nodoc:
|
|
208
208
|
add_instalments_data(xml, options)
|
209
209
|
end
|
210
210
|
add_moto_flag(xml, options) if options.dig(:metadata, :manual_entry)
|
211
|
+
add_additional_3ds_data(xml, options) if options[:execute_threed] && options[:three_ds_version] && options[:three_ds_version] =~ /^2/
|
212
|
+
add_3ds_exemption(xml, options) if options[:exemption_type]
|
211
213
|
end
|
212
214
|
end
|
213
215
|
end
|
@@ -257,6 +259,14 @@ module ActiveMerchant #:nodoc:
|
|
257
259
|
end
|
258
260
|
end
|
259
261
|
|
262
|
+
def add_additional_3ds_data(xml, options)
|
263
|
+
xml.tag! 'additional3DSData', 'dfReferenceId' => options[:session_id]
|
264
|
+
end
|
265
|
+
|
266
|
+
def add_3ds_exemption(xml, options)
|
267
|
+
xml.tag! 'exemption', 'type' => options[:exemption_type], 'placement' => options[:exemption_placement] || 'AUTHORISATION'
|
268
|
+
end
|
269
|
+
|
260
270
|
def add_amount(xml, money, options)
|
261
271
|
currency = options[:currency] || currency(money)
|
262
272
|
|
@@ -329,7 +339,7 @@ module ActiveMerchant #:nodoc:
|
|
329
339
|
xml.tag! 'date', 'month' => format(payment_method.month, :two_digits), 'year' => format(payment_method.year, :four_digits)
|
330
340
|
end
|
331
341
|
|
332
|
-
xml.tag! 'cardHolderName', options[:execute_threed] ? '3D' : payment_method.name
|
342
|
+
xml.tag! 'cardHolderName', options[:execute_threed] && (options[:three_ds_version] =~ /[^2]/).nil? ? '3D' : payment_method.name
|
333
343
|
xml.tag! 'cvc', payment_method.verification_value
|
334
344
|
|
335
345
|
add_address(xml, (options[:billing_address] || options[:address]))
|
@@ -481,6 +491,7 @@ module ActiveMerchant #:nodoc:
|
|
481
491
|
if options[:execute_threed]
|
482
492
|
raw[:cookie] = @cookie
|
483
493
|
raw[:session_id] = options[:session_id]
|
494
|
+
raw[:is3DSOrder] = true
|
484
495
|
end
|
485
496
|
success = success_from(action, raw, success_criteria)
|
486
497
|
message = message_from(success, raw, success_criteria)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activemerchant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.99.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|