activemerchant 1.117.0 → 1.123.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +217 -0
- data/README.md +5 -3
- data/lib/active_merchant/billing/check.rb +19 -12
- data/lib/active_merchant/billing/credit_card.rb +6 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +96 -22
- data/lib/active_merchant/billing/gateways/adyen.rb +38 -21
- data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -3
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -8
- data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +16 -9
- data/lib/active_merchant/billing/gateways/cyber_source.rb +67 -9
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +29 -3
- data/lib/active_merchant/billing/gateways/elavon.rb +110 -26
- data/lib/active_merchant/billing/gateways/element.rb +2 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +13 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +17 -6
- data/lib/active_merchant/billing/gateways/forte.rb +12 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +25 -16
- data/lib/active_merchant/billing/gateways/hps.rb +65 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
- data/lib/active_merchant/billing/gateways/litle.rb +9 -4
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/moka.rb +277 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
- data/lib/active_merchant/billing/gateways/netbanx.rb +37 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
- data/lib/active_merchant/billing/gateways/orbital.rb +202 -47
- data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +57 -11
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +10 -5
- data/lib/active_merchant/billing/gateways/paymentez.rb +26 -1
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
- data/lib/active_merchant/billing/gateways/pin.rb +11 -0
- data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
- data/lib/active_merchant/billing/gateways/redsys.rb +78 -30
- data/lib/active_merchant/billing/gateways/safe_charge.rb +19 -8
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +86 -25
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
- data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +68 -20
- data/lib/active_merchant/billing/response.rb +2 -1
- data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/certs/cacert.pem +1582 -2431
- metadata +10 -3
@@ -17,7 +17,7 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
}
|
18
18
|
|
19
19
|
def initialize(options = {})
|
20
|
-
requires!(options, :username, :password, :merchant, :pem
|
20
|
+
requires!(options, :username, :password, :merchant, :pem)
|
21
21
|
super
|
22
22
|
end
|
23
23
|
|
@@ -30,6 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
add_stored_credential_data(post, payment_method, options)
|
31
31
|
add_customer_data(post, options)
|
32
32
|
add_soft_descriptors(post, options)
|
33
|
+
add_customer_reference(post, options)
|
33
34
|
|
34
35
|
commit('capture', post)
|
35
36
|
end
|
@@ -43,6 +44,7 @@ module ActiveMerchant #:nodoc:
|
|
43
44
|
add_stored_credential_data(post, payment_method, options)
|
44
45
|
add_customer_data(post, options)
|
45
46
|
add_soft_descriptors(post, options)
|
47
|
+
add_customer_reference(post, options)
|
46
48
|
|
47
49
|
commit('preauth', post)
|
48
50
|
end
|
@@ -53,6 +55,7 @@ module ActiveMerchant #:nodoc:
|
|
53
55
|
add_reference(post, authorization, options)
|
54
56
|
add_customer_data(post, options)
|
55
57
|
add_soft_descriptors(post, options)
|
58
|
+
add_customer_reference(post, options)
|
56
59
|
|
57
60
|
commit('captureWithoutAuth', post)
|
58
61
|
end
|
@@ -64,6 +67,7 @@ module ActiveMerchant #:nodoc:
|
|
64
67
|
add_customer_data(post, options)
|
65
68
|
add_soft_descriptors(post, options)
|
66
69
|
post['order.ECI'] = options[:eci] || 'SSL'
|
70
|
+
add_customer_reference(post, options)
|
67
71
|
|
68
72
|
commit('refund', post)
|
69
73
|
end
|
@@ -76,6 +80,7 @@ module ActiveMerchant #:nodoc:
|
|
76
80
|
add_payment_method(post, payment_method)
|
77
81
|
add_customer_data(post, options)
|
78
82
|
add_soft_descriptors(post, options)
|
83
|
+
add_customer_reference(post, options)
|
79
84
|
|
80
85
|
commit('refund', post)
|
81
86
|
end
|
@@ -85,6 +90,7 @@ module ActiveMerchant #:nodoc:
|
|
85
90
|
add_reference(post, authorization, options)
|
86
91
|
add_customer_data(post, options)
|
87
92
|
add_soft_descriptors(post, options)
|
93
|
+
add_customer_reference(post, options)
|
88
94
|
|
89
95
|
commit('reversal', post)
|
90
96
|
end
|
@@ -92,7 +98,7 @@ module ActiveMerchant #:nodoc:
|
|
92
98
|
def store(payment_method, options = {})
|
93
99
|
post = {}
|
94
100
|
add_payment_method(post, payment_method)
|
95
|
-
add_card_reference(post)
|
101
|
+
add_card_reference(post, options)
|
96
102
|
|
97
103
|
commit('registerAccount', post)
|
98
104
|
end
|
@@ -149,12 +155,16 @@ module ActiveMerchant #:nodoc:
|
|
149
155
|
return unless payment_method.brand == 'visa'
|
150
156
|
|
151
157
|
stored_credential = options[:stored_credential]
|
152
|
-
if stored_credential[:
|
153
|
-
|
154
|
-
|
158
|
+
if stored_credential[:reason_type] == 'unscheduled'
|
159
|
+
if stored_credential[:initiator] == 'merchant'
|
160
|
+
post['card.storedCredentialUsage'] = 'UNSCHEDULED_MIT'
|
161
|
+
elsif stored_credential[:initiator] == 'customer'
|
162
|
+
post['card.storedCredentialUsage'] = 'UNSCHEDULED_CIT'
|
163
|
+
end
|
164
|
+
elsif stored_credential[:reason_type] == 'recurring'
|
155
165
|
post['card.storedCredentialUsage'] = 'RECURRING'
|
156
|
-
elsif stored_credential[:reason_type] == '
|
157
|
-
post['card.storedCredentialUsage'] = '
|
166
|
+
elsif stored_credential[:reason_type] == 'installment'
|
167
|
+
post['card.storedCredentialUsage'] = 'INSTALLMENT'
|
158
168
|
end
|
159
169
|
end
|
160
170
|
|
@@ -181,8 +191,12 @@ module ActiveMerchant #:nodoc:
|
|
181
191
|
post['card.CVN'] = payment_method.verification_value
|
182
192
|
end
|
183
193
|
|
184
|
-
def add_card_reference(post)
|
185
|
-
post['customer.customerReferenceNumber'] = options[:order_id]
|
194
|
+
def add_card_reference(post, options)
|
195
|
+
post['customer.customerReferenceNumber'] = options[:customer_reference_number] || options[:order_id]
|
196
|
+
end
|
197
|
+
|
198
|
+
def add_customer_reference(post, options)
|
199
|
+
post['customer.customerReferenceNumber'] = options[:customer_reference_number] if options[:customer_reference_number]
|
186
200
|
end
|
187
201
|
|
188
202
|
def add_reference(post, authorization, options)
|
@@ -126,6 +126,7 @@ module ActiveMerchant #:nodoc:
|
|
126
126
|
184 => 'Authentication error',
|
127
127
|
190 => 'Refusal with no specific reason',
|
128
128
|
191 => 'Expiry date incorrect',
|
129
|
+
195 => 'Requires SCA authentication',
|
129
130
|
|
130
131
|
201 => 'Card expired',
|
131
132
|
202 => 'Card blocked temporarily or under suspicion of fraud',
|
@@ -202,10 +203,12 @@ module ActiveMerchant #:nodoc:
|
|
202
203
|
add_order(data, options[:order_id])
|
203
204
|
add_payment(data, payment)
|
204
205
|
add_external_mpi_fields(data, options)
|
205
|
-
|
206
|
+
add_three_ds_data(data, options) if options[:execute_threed]
|
207
|
+
add_stored_credential_options(data, options)
|
206
208
|
data[:description] = options[:description]
|
207
209
|
data[:store_in_vault] = options[:store]
|
208
210
|
data[:sca_exemption] = options[:sca_exemption]
|
211
|
+
data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
|
209
212
|
|
210
213
|
commit data, options
|
211
214
|
end
|
@@ -219,10 +222,12 @@ module ActiveMerchant #:nodoc:
|
|
219
222
|
add_order(data, options[:order_id])
|
220
223
|
add_payment(data, payment)
|
221
224
|
add_external_mpi_fields(data, options)
|
222
|
-
|
225
|
+
add_three_ds_data(data, options) if options[:execute_threed]
|
226
|
+
add_stored_credential_options(data, options)
|
223
227
|
data[:description] = options[:description]
|
224
228
|
data[:store_in_vault] = options[:store]
|
225
229
|
data[:sca_exemption] = options[:sca_exemption]
|
230
|
+
data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
|
226
231
|
|
227
232
|
commit data, options
|
228
233
|
end
|
@@ -307,7 +312,7 @@ module ActiveMerchant #:nodoc:
|
|
307
312
|
test? ? test_url : live_url
|
308
313
|
end
|
309
314
|
|
310
|
-
def
|
315
|
+
def webservice_url
|
311
316
|
test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2' : 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
|
312
317
|
end
|
313
318
|
|
@@ -331,57 +336,87 @@ module ActiveMerchant #:nodoc:
|
|
331
336
|
return unless options[:three_d_secure]
|
332
337
|
|
333
338
|
if options[:three_d_secure][:version] == THREE_DS_V2
|
334
|
-
data[:threeDSServerTransID] = options[:three_d_secure][:
|
339
|
+
data[:threeDSServerTransID] = options[:three_d_secure][:three_ds_server_trans_id] if options[:three_d_secure][:three_ds_server_trans_id]
|
335
340
|
data[:dsTransID] = options[:three_d_secure][:ds_transaction_id] if options[:three_d_secure][:ds_transaction_id]
|
336
341
|
data[:authenticacionValue] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
|
337
342
|
data[:protocolVersion] = options[:three_d_secure][:version] if options[:three_d_secure][:version]
|
338
|
-
|
339
343
|
data[:authenticacionMethod] = options[:authentication_method] if options[:authentication_method]
|
340
344
|
data[:authenticacionType] = options[:authentication_type] if options[:authentication_type]
|
341
345
|
data[:authenticacionFlow] = options[:authentication_flow] if options[:authentication_flow]
|
346
|
+
data[:eci_v2] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
|
342
347
|
elsif options[:three_d_secure][:version] == THREE_DS_V1
|
343
348
|
data[:txid] = options[:three_d_secure][:xid] if options[:three_d_secure][:xid]
|
344
349
|
data[:cavv] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
|
345
|
-
data[:
|
350
|
+
data[:eci_v1] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def add_stored_credential_options(data, options)
|
355
|
+
return unless options[:stored_credential]
|
356
|
+
|
357
|
+
case options[:stored_credential][:initial_transaction]
|
358
|
+
when true
|
359
|
+
data[:DS_MERCHANT_COF_INI] = 'S'
|
360
|
+
when false
|
361
|
+
data[:DS_MERCHANT_COF_INI] = 'N'
|
362
|
+
data[:DS_MERCHANT_COF_TXNID] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
|
346
363
|
end
|
364
|
+
|
365
|
+
case options[:stored_credential][:reason_type]
|
366
|
+
when 'recurring'
|
367
|
+
data[:DS_MERCHANT_COF_TYPE] = 'R'
|
368
|
+
when 'installment'
|
369
|
+
data[:DS_MERCHANT_COF_TYPE] = 'I'
|
370
|
+
when 'unscheduled'
|
371
|
+
return
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def add_three_ds_data(data, options)
|
376
|
+
data[:three_ds_data] = { threeDSInfo: 'CardData' } if options[:execute_threed] == true
|
347
377
|
end
|
348
378
|
|
349
|
-
def
|
350
|
-
|
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'
|
351
385
|
end
|
352
386
|
|
353
|
-
def
|
354
|
-
|
355
|
-
return 'trataPeticion' if threeds_hash[:threeDSInfo] == 'AuthenticationData' ||
|
356
|
-
threeds_hash[:threeDSInfo] == 'ChallengeResponse'
|
387
|
+
def use_webservice_endpoint?(data, options)
|
388
|
+
options[:use_webservice_endpoint].to_s == 'true' || data[:three_ds_data] || data[:sca_exemption] == 'MIT'
|
357
389
|
end
|
358
390
|
|
359
391
|
def commit(data, options = {})
|
360
|
-
|
361
|
-
|
392
|
+
xmlreq = xml_request_from(data, options)
|
393
|
+
|
394
|
+
if use_webservice_endpoint?(data, options)
|
395
|
+
peticion_type = determine_peticion_type(data)
|
396
|
+
|
362
397
|
request = <<-REQUEST
|
363
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" >
|
364
399
|
<soapenv:Header/>
|
365
400
|
<soapenv:Body>
|
366
|
-
<intf:#{
|
401
|
+
<intf:#{peticion_type} xmlns:intf="http://webservice.sis.sermepa.es">
|
367
402
|
<intf:datoEntrada>
|
368
|
-
<![CDATA[#{
|
403
|
+
<![CDATA[#{xmlreq}]]>
|
369
404
|
</intf:datoEntrada>
|
370
|
-
</intf:#{
|
405
|
+
</intf:#{peticion_type}>
|
371
406
|
</soapenv:Body>
|
372
407
|
</soapenv:Envelope>
|
373
408
|
REQUEST
|
374
|
-
parse(ssl_post(
|
409
|
+
parse(ssl_post(webservice_url, request, headers(peticion_type)), peticion_type)
|
375
410
|
else
|
376
|
-
parse(ssl_post(url, "entrada=#{CGI.escape(
|
411
|
+
parse(ssl_post(url, "entrada=#{CGI.escape(xmlreq)}", headers), peticion_type)
|
377
412
|
end
|
378
413
|
end
|
379
414
|
|
380
|
-
def headers(
|
381
|
-
if
|
415
|
+
def headers(peticion_type = nil)
|
416
|
+
if peticion_type
|
382
417
|
{
|
383
418
|
'Content-Type' => 'text/xml',
|
384
|
-
'SOAPAction' =>
|
419
|
+
'SOAPAction' => peticion_type
|
385
420
|
}
|
386
421
|
else
|
387
422
|
{
|
@@ -445,7 +480,7 @@ module ActiveMerchant #:nodoc:
|
|
445
480
|
|
446
481
|
def build_merchant_data(xml, data, options = {})
|
447
482
|
# See https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2/wsdl/SerClsWSEntradaV2.wsdl
|
448
|
-
# (which results from calling #
|
483
|
+
# (which results from calling #webservice_url + '?WSDL', https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2?WSDL)
|
449
484
|
xml.DATOSENTRADA do
|
450
485
|
# Basic elements
|
451
486
|
xml.DS_Version 0.1
|
@@ -453,7 +488,7 @@ module ActiveMerchant #:nodoc:
|
|
453
488
|
xml.DS_MERCHANT_AMOUNT data[:amount]
|
454
489
|
xml.DS_MERCHANT_ORDER data[:order_id]
|
455
490
|
xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
|
456
|
-
if data[:description] && data
|
491
|
+
if data[:description] && use_webservice_endpoint?(data, options)
|
457
492
|
xml.DS_MERCHANT_PRODUCTDESCRIPTION CGI.escape(data[:description])
|
458
493
|
else
|
459
494
|
xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
|
@@ -461,11 +496,18 @@ module ActiveMerchant #:nodoc:
|
|
461
496
|
xml.DS_MERCHANT_TERMINAL options[:terminal] || @options[:terminal]
|
462
497
|
xml.DS_MERCHANT_MERCHANTCODE @options[:login]
|
463
498
|
xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
|
464
|
-
|
499
|
+
|
500
|
+
peticion_type = determine_peticion_type(data) if data[:three_ds_data]
|
501
|
+
if peticion_type == 'iniciaPeticion' && data[:sca_exemption]
|
502
|
+
xml.DS_MERCHANT_EXCEP_SCA 'Y'
|
503
|
+
else
|
504
|
+
xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
|
505
|
+
xml.DS_MERCHANT_DIRECTPAYMENT data[:sca_exemption_direct_payment_enabled] || 'true' if data[:sca_exemption] == 'MIT'
|
506
|
+
end
|
465
507
|
|
466
508
|
# Only when card is present
|
467
509
|
if data[:card]
|
468
|
-
if data[:card][:name] && data
|
510
|
+
if data[:card][:name] && use_webservice_endpoint?(data, options)
|
469
511
|
xml.DS_MERCHANT_TITULAR CGI.escape(data[:card][:name])
|
470
512
|
else
|
471
513
|
xml.DS_MERCHANT_TITULAR data[:card][:name]
|
@@ -486,7 +528,13 @@ module ActiveMerchant #:nodoc:
|
|
486
528
|
# Requires account configuration to be able to use
|
487
529
|
xml.DS_MERCHANT_DIRECTPAYMENT 'moto' if options.dig(:moto) && options.dig(:metadata, :manual_entry)
|
488
530
|
|
489
|
-
xml.DS_MERCHANT_EMV3DS data[:
|
531
|
+
xml.DS_MERCHANT_EMV3DS data[:three_ds_data].to_json if data[:three_ds_data]
|
532
|
+
|
533
|
+
if options[:stored_credential]
|
534
|
+
xml.DS_MERCHANT_COF_INI data[:DS_MERCHANT_COF_INI]
|
535
|
+
xml.DS_MERCHANT_COF_TYPE data[:DS_MERCHANT_COF_TYPE]
|
536
|
+
xml.DS_MERCHANT_COF_TXNID data[:DS_MERCHANT_COF_TXNID] if data[:DS_MERCHANT_COF_TXNID]
|
537
|
+
end
|
490
538
|
end
|
491
539
|
end
|
492
540
|
|
@@ -496,13 +544,13 @@ module ActiveMerchant #:nodoc:
|
|
496
544
|
ds_merchant_mpi_external = {}
|
497
545
|
ds_merchant_mpi_external[:TXID] = data[:txid] if data[:txid]
|
498
546
|
ds_merchant_mpi_external[:CAVV] = data[:cavv] if data[:cavv]
|
499
|
-
ds_merchant_mpi_external[:ECI] = data[:
|
547
|
+
ds_merchant_mpi_external[:ECI] = data[:eci_v1] if data[:eci_v1]
|
500
548
|
|
501
549
|
ds_merchant_mpi_external[:threeDSServerTransID] = data[:threeDSServerTransID] if data[:threeDSServerTransID]
|
502
550
|
ds_merchant_mpi_external[:dsTransID] = data[:dsTransID] if data[:dsTransID]
|
503
551
|
ds_merchant_mpi_external[:authenticacionValue] = data[:authenticacionValue] if data[:authenticacionValue]
|
504
552
|
ds_merchant_mpi_external[:protocolVersion] = data[:protocolVersion] if data[:protocolVersion]
|
505
|
-
|
553
|
+
ds_merchant_mpi_external[:Eci] = data[:eci_v2] if data[:eci_v2]
|
506
554
|
ds_merchant_mpi_external[:authenticacionMethod] = data[:authenticacionMethod] if data[:authenticacionMethod]
|
507
555
|
ds_merchant_mpi_external[:authenticacionType] = data[:authenticacionType] if data[:authenticacionType]
|
508
556
|
ds_merchant_mpi_external[:authenticacionFlow] = data[:authenticacionFlow] if data[:authenticacionFlow]
|
@@ -593,7 +641,7 @@ module ActiveMerchant #:nodoc:
|
|
593
641
|
def response_text(code)
|
594
642
|
code = code.to_i
|
595
643
|
code = 0 if code < 100
|
596
|
-
RESPONSE_TEXTS[code] || '
|
644
|
+
RESPONSE_TEXTS[code] || 'Unknown code, please check in manual'
|
597
645
|
end
|
598
646
|
|
599
647
|
def response_text_3ds(xml, params)
|
@@ -143,15 +143,24 @@ module ActiveMerchant #:nodoc:
|
|
143
143
|
post[:sg_Descriptor] = options[:merchant_descriptor] if options[:merchant_descriptor]
|
144
144
|
post[:sg_MerchantPhoneNumber] = options[:merchant_phone_number] if options[:merchant_phone_number]
|
145
145
|
post[:sg_MerchantName] = options[:merchant_name] if options[:merchant_name]
|
146
|
+
post[:sg_ProductID] = options[:product_id] if options[:product_id]
|
146
147
|
end
|
147
148
|
|
148
149
|
def add_payment(post, payment, options = {})
|
149
|
-
post[:sg_NameOnCard] = payment.name
|
150
|
-
post[:sg_CardNumber] = payment.number
|
151
150
|
post[:sg_ExpMonth] = format(payment.month, :two_digits)
|
152
151
|
post[:sg_ExpYear] = format(payment.year, :two_digits)
|
153
|
-
post[:
|
154
|
-
|
152
|
+
post[:sg_CardNumber] = payment.number
|
153
|
+
|
154
|
+
if payment.is_a?(NetworkTokenizationCreditCard) && payment.source == :network_token
|
155
|
+
post[:sg_CAVV] = payment.payment_cryptogram
|
156
|
+
post[:sg_ECI] = options[:three_d_secure] && options[:three_d_secure][:eci] || '05'
|
157
|
+
post[:sg_IsExternalMPI] = 1
|
158
|
+
post[:sg_ExternalTokenProvider] = 5
|
159
|
+
else
|
160
|
+
post[:sg_CVV2] = payment.verification_value
|
161
|
+
post[:sg_NameOnCard] = payment.name
|
162
|
+
post[:sg_StoredCredentialMode] = (options[:stored_credential_mode] == true ? 1 : 0)
|
163
|
+
end
|
155
164
|
end
|
156
165
|
|
157
166
|
def add_customer_details(post, payment, options)
|
@@ -170,12 +179,14 @@ module ActiveMerchant #:nodoc:
|
|
170
179
|
end
|
171
180
|
|
172
181
|
def add_external_mpi_data(post, options)
|
173
|
-
post[:
|
174
|
-
post[:
|
182
|
+
post[:sg_ECI] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
|
183
|
+
post[:sg_CAVV] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
|
175
184
|
post[:sg_dsTransID] = options[:three_d_secure][:ds_transaction_id] if options[:three_d_secure][:ds_transaction_id]
|
176
|
-
post[:sg_threeDSProtocolVersion] = options[:three_d_secure][:
|
177
|
-
post[:
|
185
|
+
post[:sg_threeDSProtocolVersion] = options[:three_d_secure][:ds_transaction_id] ? '2' : '1'
|
186
|
+
post[:sg_Xid] = options[:three_d_secure][:xid]
|
178
187
|
post[:sg_IsExternalMPI] = 1
|
188
|
+
post[:sg_EnablePartialApproval] = options[:is_partial_approval]
|
189
|
+
post[:sg_challengePreference] = options[:three_d_secure][:challenge_preference] if options[:three_d_secure][:challenge_preference]
|
179
190
|
end
|
180
191
|
|
181
192
|
def parse(xml)
|
@@ -254,11 +254,20 @@ module ActiveMerchant #:nodoc:
|
|
254
254
|
end
|
255
255
|
|
256
256
|
def childnode_to_response(response, node, childnode)
|
257
|
-
|
258
|
-
|
259
|
-
|
257
|
+
node_name = node.name.downcase
|
258
|
+
childnode_name = childnode.name.downcase
|
259
|
+
composed_name = "#{node_name}_#{childnode_name}"
|
260
|
+
|
261
|
+
childnodes_present = !childnode.elements.empty?
|
262
|
+
|
263
|
+
if childnodes_present && composed_name == 'payment_method_data'
|
264
|
+
response[composed_name.to_sym] = Hash.from_xml(childnode.to_s).values.first
|
265
|
+
elsif childnodes_present && node_name == 'gateway_specific_response_fields'
|
266
|
+
response[node_name.to_sym] = {
|
267
|
+
childnode_name => Hash.from_xml(childnode.to_s).values.first
|
268
|
+
}
|
260
269
|
else
|
261
|
-
response[
|
270
|
+
response[composed_name.to_sym] = childnode.text
|
262
271
|
end
|
263
272
|
end
|
264
273
|
|
@@ -279,14 +279,14 @@ module ActiveMerchant #:nodoc:
|
|
279
279
|
transcript.
|
280
280
|
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
281
281
|
gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2').
|
282
|
-
gsub(%r((card\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\
|
283
|
-
gsub(%r((card\[cvc\]=)\d+), '\1[FILTERED]').
|
284
|
-
gsub(%r((card\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\
|
285
|
-
gsub(%r((card\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\
|
286
|
-
gsub(%r((card\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\
|
287
|
-
gsub(%r((card\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\
|
288
|
-
gsub(%r((card\[number\]=)\d+), '\1[FILTERED]').
|
289
|
-
gsub(%r((card\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\
|
282
|
+
gsub(%r(((\[card\]|card)\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
283
|
+
gsub(%r(((\[card\]|card)\[cvc\]=)\d+), '\1[FILTERED]').
|
284
|
+
gsub(%r(((\[card\]|card)\[emv_approval_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
285
|
+
gsub(%r(((\[card\]|card)\[emv_auth_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
286
|
+
gsub(%r(((\[card\]|card)\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
287
|
+
gsub(%r(((\[card\]|card)\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\3').
|
288
|
+
gsub(%r(((\[card\]|card)\[number\]=)\d+), '\1[FILTERED]').
|
289
|
+
gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3')
|
290
290
|
end
|
291
291
|
|
292
292
|
def supports_network_tokenization?
|
@@ -30,6 +30,9 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
add_shipping_address(post, options)
|
31
31
|
setup_future_usage(post, options)
|
32
32
|
add_exemption(post, options)
|
33
|
+
add_stored_credentials(post, options)
|
34
|
+
add_ntid(post, options)
|
35
|
+
add_error_on_requires_action(post, options)
|
33
36
|
request_three_d_secure(post, options)
|
34
37
|
|
35
38
|
CREATE_INTENT_ATTRIBUTES.each do |attribute|
|
@@ -55,16 +58,22 @@ module ActiveMerchant #:nodoc:
|
|
55
58
|
end
|
56
59
|
|
57
60
|
def create_payment_method(payment_method, options = {})
|
58
|
-
|
59
|
-
|
60
|
-
post[:card] = {}
|
61
|
-
post[:card][:number] = payment_method.number
|
62
|
-
post[:card][:exp_month] = payment_method.month
|
63
|
-
post[:card][:exp_year] = payment_method.year
|
64
|
-
post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
|
65
|
-
add_billing_address(post, options)
|
61
|
+
post_data = create_payment_method_data(payment_method, options)
|
62
|
+
|
66
63
|
options = format_idempotency_key(options, 'pm')
|
67
|
-
commit(:post, 'payment_methods',
|
64
|
+
commit(:post, 'payment_methods', post_data, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_payment_method_data(payment_method, options = {})
|
68
|
+
post_data = {}
|
69
|
+
post_data[:type] = 'card'
|
70
|
+
post_data[:card] = {}
|
71
|
+
post_data[:card][:number] = payment_method.number
|
72
|
+
post_data[:card][:exp_month] = payment_method.month
|
73
|
+
post_data[:card][:exp_year] = payment_method.year
|
74
|
+
post_data[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
|
75
|
+
add_billing_address(post_data, options)
|
76
|
+
post_data
|
68
77
|
end
|
69
78
|
|
70
79
|
def update_intent(money, intent_id, payment_method, options = {})
|
@@ -101,6 +110,17 @@ module ActiveMerchant #:nodoc:
|
|
101
110
|
commit(:post, 'setup_intents', post, options)
|
102
111
|
end
|
103
112
|
|
113
|
+
def retrieve_setup_intent(setup_intent_id)
|
114
|
+
# Retrieving a setup_intent passing 'expand[]=latest_attempt' allows the caller to
|
115
|
+
# check for a network_transaction_id and ds_transaction_id
|
116
|
+
# eg (latest_attempt -> payment_method_details -> card -> network_transaction_id)
|
117
|
+
#
|
118
|
+
# Being able to retrieve these fields enables payment flows that rely on MIT exemptions, e.g: off_session
|
119
|
+
commit(:post, "setup_intents/#{setup_intent_id}", {
|
120
|
+
'expand[]': 'latest_attempt'
|
121
|
+
}, {})
|
122
|
+
end
|
123
|
+
|
104
124
|
def authorize(money, payment_method, options = {})
|
105
125
|
create_intent(money, payment_method, options.merge!(confirm: true, capture_method: 'manual'))
|
106
126
|
end
|
@@ -164,7 +184,6 @@ module ActiveMerchant #:nodoc:
|
|
164
184
|
if options[:customer]
|
165
185
|
customer_id = options[:customer]
|
166
186
|
else
|
167
|
-
post[:validate] = options[:validate] unless options[:validate].nil?
|
168
187
|
post[:description] = options[:description] if options[:description]
|
169
188
|
post[:email] = options[:email] if options[:email]
|
170
189
|
options = format_idempotency_key(options, 'customer')
|
@@ -172,7 +191,9 @@ module ActiveMerchant #:nodoc:
|
|
172
191
|
customer_id = customer.params['id']
|
173
192
|
end
|
174
193
|
options = format_idempotency_key(options, 'attach')
|
175
|
-
|
194
|
+
attach_parameters = { customer: customer_id }
|
195
|
+
attach_parameters[:validate] = options[:validate] unless options[:validate].nil?
|
196
|
+
commit(:post, "payment_methods/#{params[:payment_method]}/attach", attach_parameters, options)
|
176
197
|
else
|
177
198
|
super(payment_method, options)
|
178
199
|
end
|
@@ -193,6 +214,10 @@ module ActiveMerchant #:nodoc:
|
|
193
214
|
|
194
215
|
private
|
195
216
|
|
217
|
+
def off_session_request?(options = {})
|
218
|
+
(options[:off_session] || options[:setup_future_usage]) && options[:confirm] == true
|
219
|
+
end
|
220
|
+
|
196
221
|
def add_connected_account(post, options = {})
|
197
222
|
super(post, options)
|
198
223
|
post[:application_fee_amount] = options[:application_fee] if options[:application_fee]
|
@@ -200,25 +225,21 @@ module ActiveMerchant #:nodoc:
|
|
200
225
|
|
201
226
|
def add_whitelisted_attribute(post, options, attribute)
|
202
227
|
post[attribute] = options[attribute] if options[attribute]
|
203
|
-
post
|
204
228
|
end
|
205
229
|
|
206
230
|
def add_capture_method(post, options)
|
207
231
|
capture_method = options[:capture_method].to_s
|
208
232
|
post[:capture_method] = capture_method if ALLOWED_METHOD_STATES.include?(capture_method)
|
209
|
-
post
|
210
233
|
end
|
211
234
|
|
212
235
|
def add_confirmation_method(post, options)
|
213
236
|
confirmation_method = options[:confirmation_method].to_s
|
214
237
|
post[:confirmation_method] = confirmation_method if ALLOWED_METHOD_STATES.include?(confirmation_method)
|
215
|
-
post
|
216
238
|
end
|
217
239
|
|
218
240
|
def add_customer(post, options)
|
219
241
|
customer = options[:customer].to_s
|
220
242
|
post[:customer] = customer if customer.start_with?('cus_')
|
221
|
-
post
|
222
243
|
end
|
223
244
|
|
224
245
|
def add_return_url(post, options)
|
@@ -226,22 +247,27 @@ module ActiveMerchant #:nodoc:
|
|
226
247
|
|
227
248
|
post[:confirm] = options[:confirm]
|
228
249
|
post[:return_url] = options[:return_url] if options[:return_url]
|
229
|
-
post
|
230
250
|
end
|
231
251
|
|
232
252
|
def add_payment_method_token(post, payment_method, options)
|
233
253
|
return if payment_method.nil?
|
234
254
|
|
235
255
|
if payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
236
|
-
|
237
|
-
|
256
|
+
if off_session_request?(options)
|
257
|
+
post[:payment_method_data] = create_payment_method_data(payment_method, options)
|
258
|
+
return
|
259
|
+
else
|
260
|
+
p = create_payment_method(payment_method, options)
|
261
|
+
return p unless p.success?
|
238
262
|
|
239
|
-
|
263
|
+
payment_method = p.params['id']
|
264
|
+
end
|
240
265
|
end
|
241
266
|
|
242
|
-
|
267
|
+
case payment_method
|
268
|
+
when StripePaymentToken
|
243
269
|
post[:payment_method] = payment_method.payment_data['id']
|
244
|
-
|
270
|
+
when String
|
245
271
|
if payment_method.include?('|')
|
246
272
|
customer_id, payment_method_id = payment_method.split('|')
|
247
273
|
token = payment_method_id
|
@@ -251,6 +277,8 @@ module ActiveMerchant #:nodoc:
|
|
251
277
|
end
|
252
278
|
post[:payment_method] = token
|
253
279
|
end
|
280
|
+
|
281
|
+
post
|
254
282
|
end
|
255
283
|
|
256
284
|
def add_payment_method_types(post, options)
|
@@ -258,7 +286,6 @@ module ActiveMerchant #:nodoc:
|
|
258
286
|
return if payment_method_types.nil?
|
259
287
|
|
260
288
|
post[:payment_method_types] = Array(payment_method_types)
|
261
|
-
post
|
262
289
|
end
|
263
290
|
|
264
291
|
def add_exemption(post, options = {})
|
@@ -269,6 +296,42 @@ module ActiveMerchant #:nodoc:
|
|
269
296
|
post[:payment_method_options][:card][:moto] = true if options[:moto]
|
270
297
|
end
|
271
298
|
|
299
|
+
# Stripe Payment Intents does not pass any parameters for cardholder/merchant initiated
|
300
|
+
# it also does not support installments for any country other than Mexico (reason for this is unknown)
|
301
|
+
# The only thing that Stripe PI requires for stored credentials to work currently is the network_transaction_id
|
302
|
+
# network_transaction_id is created when the card is authenticated using the field `setup_for_future_usage` with the value `off_session` see def setup_future_usage below
|
303
|
+
|
304
|
+
def add_stored_credentials(post, options = {})
|
305
|
+
return unless options[:stored_credential] && !options[:stored_credential].values.all?(&:nil?)
|
306
|
+
|
307
|
+
stored_credential = options[:stored_credential]
|
308
|
+
post[:payment_method_options] ||= {}
|
309
|
+
post[:payment_method_options][:card] ||= {}
|
310
|
+
post[:payment_method_options][:card][:mit_exemption] = {}
|
311
|
+
|
312
|
+
# Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
|
313
|
+
# The network_transaction_id can be sent in nested under stored credentials OR as its own field (add_ntid handles when it is sent in on its own)
|
314
|
+
# If it is sent is as its own field AND under stored credentials, the value sent under its own field is what will send.
|
315
|
+
post[:payment_method_options][:card][:mit_exemption][:ds_transaction_id] = stored_credential[:ds_transaction_id] if stored_credential[:ds_transaction_id]
|
316
|
+
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
317
|
+
end
|
318
|
+
|
319
|
+
def add_ntid(post, options = {})
|
320
|
+
return unless options[:network_transaction_id]
|
321
|
+
|
322
|
+
post[:payment_method_options] ||= {}
|
323
|
+
post[:payment_method_options][:card] ||= {}
|
324
|
+
post[:payment_method_options][:card][:mit_exemption] = {}
|
325
|
+
|
326
|
+
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id] if options[:network_transaction_id]
|
327
|
+
end
|
328
|
+
|
329
|
+
def add_error_on_requires_action(post, options = {})
|
330
|
+
return unless options[:confirm]
|
331
|
+
|
332
|
+
post[:error_on_requires_action] = true if options[:error_on_requires_action]
|
333
|
+
end
|
334
|
+
|
272
335
|
def request_three_d_secure(post, options = {})
|
273
336
|
return unless options[:request_three_d_secure] && %w(any automatic).include?(options[:request_three_d_secure])
|
274
337
|
|
@@ -292,7 +355,7 @@ module ActiveMerchant #:nodoc:
|
|
292
355
|
|
293
356
|
def setup_future_usage(post, options = {})
|
294
357
|
post[:setup_future_usage] = options[:setup_future_usage] if %w(on_session off_session).include?(options[:setup_future_usage])
|
295
|
-
post[:off_session] = options[:off_session] if options
|
358
|
+
post[:off_session] = options[:off_session] if off_session_request?(options)
|
296
359
|
post
|
297
360
|
end
|
298
361
|
|
@@ -310,7 +373,6 @@ module ActiveMerchant #:nodoc:
|
|
310
373
|
post[:billing_details][:email] = billing[:email] if billing[:email]
|
311
374
|
post[:billing_details][:name] = billing[:name] if billing[:name]
|
312
375
|
post[:billing_details][:phone] = billing[:phone] if billing[:phone]
|
313
|
-
post
|
314
376
|
end
|
315
377
|
|
316
378
|
def add_shipping_address(post, options = {})
|
@@ -329,7 +391,6 @@ module ActiveMerchant #:nodoc:
|
|
329
391
|
post[:shipping][:carrier] = shipping[:carrier] if shipping[:carrier]
|
330
392
|
post[:shipping][:phone] = shipping[:phone] if shipping[:phone]
|
331
393
|
post[:shipping][:tracking_number] = shipping[:tracking_number] if shipping[:tracking_number]
|
332
|
-
post
|
333
394
|
end
|
334
395
|
|
335
396
|
def format_idempotency_key(options, suffix)
|