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