activemerchant 1.119.0 → 1.124.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 +216 -1
- data/README.md +4 -2
- data/lib/active_merchant/billing/check.rb +19 -12
- data/lib/active_merchant/billing/credit_card.rb +3 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +32 -14
- data/lib/active_merchant/billing/gateways/adyen.rb +94 -25
- data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +52 -8
- data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
- 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 +15 -9
- data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -6
- data/lib/active_merchant/billing/gateways/d_local.rb +9 -2
- data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +70 -28
- data/lib/active_merchant/billing/gateways/element.rb +2 -0
- data/lib/active_merchant/billing/gateways/forte.rb +12 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +24 -10
- data/lib/active_merchant/billing/gateways/hps.rb +55 -1
- data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
- data/lib/active_merchant/billing/gateways/litle.rb +1 -1
- 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/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +290 -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 +26 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +27 -9
- data/lib/active_merchant/billing/gateways/orbital.rb +99 -59
- data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +34 -6
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
- data/lib/active_merchant/billing/gateways/payment_express.rb +5 -5
- data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +376 -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/qvalent.rb +23 -9
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +42 -24
- data/lib/active_merchant/billing/gateways/safe_charge.rb +25 -13
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +18 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +126 -48
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
- 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 +78 -18
- data/lib/active_merchant/billing/response.rb +4 -0
- 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 +11 -3
@@ -37,12 +37,15 @@ module ActiveMerchant #:nodoc:
|
|
37
37
|
post = {}
|
38
38
|
add_invoice(post, amount, options)
|
39
39
|
add_customer_data(post, options)
|
40
|
+
add_metadata(post, options)
|
40
41
|
|
41
42
|
commit(:capture, post, authorization)
|
42
43
|
end
|
43
44
|
|
44
45
|
def void(authorization, _options = {})
|
45
46
|
post = {}
|
47
|
+
add_metadata(post, options)
|
48
|
+
|
46
49
|
commit(:void, post, authorization)
|
47
50
|
end
|
48
51
|
|
@@ -50,6 +53,7 @@ module ActiveMerchant #:nodoc:
|
|
50
53
|
post = {}
|
51
54
|
add_invoice(post, amount, options)
|
52
55
|
add_customer_data(post, options)
|
56
|
+
add_metadata(post, options)
|
53
57
|
|
54
58
|
commit(:refund, post, authorization)
|
55
59
|
end
|
@@ -79,8 +83,10 @@ module ActiveMerchant #:nodoc:
|
|
79
83
|
add_invoice(post, amount, options)
|
80
84
|
add_payment_method(post, payment_method, options)
|
81
85
|
add_customer_data(post, options)
|
86
|
+
add_stored_credential_options(post, options)
|
82
87
|
add_transaction_data(post, options)
|
83
88
|
add_3ds(post, options)
|
89
|
+
add_metadata(post, options)
|
84
90
|
end
|
85
91
|
|
86
92
|
def add_invoice(post, money, options)
|
@@ -96,6 +102,11 @@ module ActiveMerchant #:nodoc:
|
|
96
102
|
post[:metadata][:udf5] = application_id || 'ActiveMerchant'
|
97
103
|
end
|
98
104
|
|
105
|
+
def add_metadata(post, options)
|
106
|
+
post[:metadata] = {} unless post[:metadata]
|
107
|
+
post[:metadata].merge!(options[:metadata]) if options[:metadata]
|
108
|
+
end
|
109
|
+
|
99
110
|
def add_payment_method(post, payment_method, options)
|
100
111
|
post[:source] = {}
|
101
112
|
if payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :network_token
|
@@ -138,6 +149,26 @@ module ActiveMerchant #:nodoc:
|
|
138
149
|
post[:previous_payment_id] = options[:previous_charge_id] if options[:previous_charge_id]
|
139
150
|
end
|
140
151
|
|
152
|
+
def add_stored_credential_options(post, options = {})
|
153
|
+
return unless options[:stored_credential]
|
154
|
+
|
155
|
+
case options[:stored_credential][:initial_transaction]
|
156
|
+
when true
|
157
|
+
post[:merchant_initiated] = false
|
158
|
+
when false
|
159
|
+
post[:'source.stored'] = true
|
160
|
+
post[:previous_payment_id] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
|
161
|
+
post[:merchant_initiated] = true
|
162
|
+
end
|
163
|
+
|
164
|
+
case options[:stored_credential][:reason_type]
|
165
|
+
when 'recurring' || 'installment'
|
166
|
+
post[:payment_type] = 'Recurring'
|
167
|
+
when 'unscheduled'
|
168
|
+
return
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
141
172
|
def add_3ds(post, options)
|
142
173
|
if options[:three_d_secure] || options[:execute_threed]
|
143
174
|
post[:'3ds'] = {}
|
@@ -20,8 +20,9 @@ module ActiveMerchant #:nodoc:
|
|
20
20
|
self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
|
21
21
|
|
22
22
|
self.supported_countries = %w(AD AT BE BG HR CY CZ DK EE FR DE GI GR GG HU IS IE IM IT JE LV LI LT LU MT MC NO PL PT RO SM SK ES SE CH GB)
|
23
|
+
|
23
24
|
self.default_currency = 'EUR'
|
24
|
-
self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
|
25
|
+
self.currencies_without_fractions = %w(BIF CLP DJF GNF ISK JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
|
25
26
|
self.currencies_with_three_decimal_places = %w(BHD IQD JOD KWD LYD OMR TND)
|
26
27
|
|
27
28
|
self.money_format = :cents
|
@@ -334,6 +335,7 @@ module ActiveMerchant #:nodoc:
|
|
334
335
|
post[:f23] = options[:f23] if options[:f23]
|
335
336
|
post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
|
336
337
|
options.dig(:stored_credential, :initiator) == 'merchant' ? post[:'3ds_channel'] = '03' : post[:'3ds_channel'] = '02'
|
338
|
+
post[:'3ds_reqchallengeind'] = options[:three_ds_reqchallengeind] if options[:three_ds_reqchallengeind]
|
337
339
|
post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
|
338
340
|
post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
|
339
341
|
post[:d5] = browser_info[:user_agent]
|
@@ -345,14 +347,7 @@ module ActiveMerchant #:nodoc:
|
|
345
347
|
post[:d6] = browser_info[:language]
|
346
348
|
post[:'3ds_browserjavaenabled'] = browser_info[:java]
|
347
349
|
post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
|
348
|
-
|
349
|
-
post[:'3ds_shipaddrstate'] = shipping_address[:state]
|
350
|
-
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
|
351
|
-
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
|
352
|
-
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
|
353
|
-
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
|
354
|
-
post[:'3ds_shipaddrcity'] = shipping_address[:city]
|
355
|
-
end
|
350
|
+
add_complete_shipping_address(post, options[:shipping_address]) if options[:shipping_address]
|
356
351
|
elsif options[:three_d_secure]
|
357
352
|
add_normalized_3d_secure_2_data(post, options)
|
358
353
|
end
|
@@ -372,6 +367,17 @@ module ActiveMerchant #:nodoc:
|
|
372
367
|
end
|
373
368
|
end
|
374
369
|
|
370
|
+
def add_complete_shipping_address(post, shipping_address)
|
371
|
+
return if shipping_address.values.any?(&:blank?)
|
372
|
+
|
373
|
+
post[:'3ds_shipaddrstate'] = shipping_address[:state]
|
374
|
+
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
|
375
|
+
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
|
376
|
+
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
|
377
|
+
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
|
378
|
+
post[:'3ds_shipaddrcity'] = shipping_address[:city]
|
379
|
+
end
|
380
|
+
|
375
381
|
def add_normalized_3d_secure_2_data(post, options)
|
376
382
|
three_d_secure_options = options[:three_d_secure]
|
377
383
|
|
@@ -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.181'
|
29
|
+
PRODUCTION_XSD_VERSION = '1.181'
|
30
30
|
ECI_BRAND_MAPPING = {
|
31
31
|
visa: 'vbv',
|
32
32
|
master: 'spa',
|
@@ -153,6 +153,10 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
commit(build_refund_request(money, identification, options), :refund, money, options)
|
154
154
|
end
|
155
155
|
|
156
|
+
def adjust(money, authorization, options = {})
|
157
|
+
commit(build_adjust_request(money, authorization, options), :adjust, money, options)
|
158
|
+
end
|
159
|
+
|
156
160
|
def verify(payment, options = {})
|
157
161
|
MultiResponse.run(:use_first_response) do |r|
|
158
162
|
r.process { authorize(100, payment, options) }
|
@@ -285,6 +289,7 @@ module ActiveMerchant #:nodoc:
|
|
285
289
|
|
286
290
|
def build_auth_request(money, creditcard_or_reference, options)
|
287
291
|
xml = Builder::XmlMarkup.new indent: 2
|
292
|
+
add_customer_id(xml, options)
|
288
293
|
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
289
294
|
add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
|
290
295
|
add_decision_manager_fields(xml, options)
|
@@ -298,7 +303,17 @@ module ActiveMerchant #:nodoc:
|
|
298
303
|
add_partner_solution_id(xml)
|
299
304
|
add_stored_credential_options(xml, options)
|
300
305
|
add_merchant_description(xml, options)
|
306
|
+
add_sales_slip_number(xml, options)
|
307
|
+
add_airline_data(xml, options)
|
308
|
+
xml.target!
|
309
|
+
end
|
310
|
+
|
311
|
+
def build_adjust_request(money, authorization, options)
|
312
|
+
_, request_id = authorization.split(';')
|
301
313
|
|
314
|
+
xml = Builder::XmlMarkup.new indent: 2
|
315
|
+
add_purchase_data(xml, money, true, options)
|
316
|
+
add_incremental_auth_service(xml, request_id, options)
|
302
317
|
xml.target!
|
303
318
|
end
|
304
319
|
|
@@ -332,10 +347,13 @@ module ActiveMerchant #:nodoc:
|
|
332
347
|
|
333
348
|
def build_purchase_request(money, payment_method_or_reference, options)
|
334
349
|
xml = Builder::XmlMarkup.new indent: 2
|
350
|
+
add_customer_id(xml, options)
|
335
351
|
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
336
352
|
add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
|
337
353
|
add_decision_manager_fields(xml, options)
|
338
354
|
add_mdd_fields(xml, options)
|
355
|
+
add_sales_slip_number(xml, options)
|
356
|
+
add_airline_data(xml, options)
|
339
357
|
if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
|
340
358
|
add_check_service(xml)
|
341
359
|
add_issuer_additional_data(xml, options)
|
@@ -468,8 +486,8 @@ module ActiveMerchant #:nodoc:
|
|
468
486
|
|
469
487
|
unless network_tokenization?(payment_method)
|
470
488
|
xml.tag! 'businessRules' do
|
471
|
-
xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs)
|
472
|
-
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv)
|
489
|
+
xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
|
490
|
+
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
|
473
491
|
end
|
474
492
|
end
|
475
493
|
end
|
@@ -511,6 +529,12 @@ module ActiveMerchant #:nodoc:
|
|
511
529
|
end
|
512
530
|
end
|
513
531
|
|
532
|
+
def add_customer_id(xml, options)
|
533
|
+
return unless options[:customer_id]
|
534
|
+
|
535
|
+
xml.tag! 'customerID', options[:customer_id]
|
536
|
+
end
|
537
|
+
|
514
538
|
def add_merchant_description(xml, options)
|
515
539
|
return unless options[:merchant_descriptor_name] || options[:merchant_descriptor_address1] || options[:merchant_descriptor_locality]
|
516
540
|
|
@@ -523,6 +547,18 @@ module ActiveMerchant #:nodoc:
|
|
523
547
|
end
|
524
548
|
end
|
525
549
|
|
550
|
+
def add_sales_slip_number(xml, options)
|
551
|
+
xml.tag! 'salesSlipNumber', options[:sales_slip_number] if options[:sales_slip_number]
|
552
|
+
end
|
553
|
+
|
554
|
+
def add_airline_data(xml, options)
|
555
|
+
return unless options[:airline_agent_code]
|
556
|
+
|
557
|
+
xml.tag! 'airlineData' do
|
558
|
+
xml.tag! 'agentCode', options[:airline_agent_code]
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
526
562
|
def add_purchase_data(xml, money = 0, include_grand_total = false, options = {})
|
527
563
|
xml.tag! 'purchaseTotals' do
|
528
564
|
xml.tag! 'currency', options[:currency] || currency(money)
|
@@ -532,6 +568,7 @@ module ActiveMerchant #:nodoc:
|
|
532
568
|
|
533
569
|
def add_address(xml, payment_method, address, options, shipTo = false)
|
534
570
|
first_name, last_name = address_names(address[:name], payment_method)
|
571
|
+
bill_to_merchant_tax_id = options[:merchant_tax_id] unless shipTo
|
535
572
|
|
536
573
|
xml.tag! shipTo ? 'shipTo' : 'billTo' do
|
537
574
|
xml.tag! 'firstName', first_name if first_name
|
@@ -549,6 +586,7 @@ module ActiveMerchant #:nodoc:
|
|
549
586
|
xml.tag! 'ipAddress', options[:ip] unless options[:ip].blank? || shipTo
|
550
587
|
xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
|
551
588
|
xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
|
589
|
+
xml.tag! 'merchantTaxID', bill_to_merchant_tax_id unless bill_to_merchant_tax_id.blank?
|
552
590
|
end
|
553
591
|
end
|
554
592
|
|
@@ -567,7 +605,7 @@ module ActiveMerchant #:nodoc:
|
|
567
605
|
xml.tag! 'accountNumber', creditcard.number
|
568
606
|
xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
|
569
607
|
xml.tag! 'expirationYear', format(creditcard.year, :four_digits)
|
570
|
-
xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv] || creditcard.verification_value.blank?
|
608
|
+
xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv].to_s == 'true' || creditcard.verification_value.blank?
|
571
609
|
xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym]
|
572
610
|
end
|
573
611
|
end
|
@@ -604,7 +642,7 @@ module ActiveMerchant #:nodoc:
|
|
604
642
|
xml.tag! 'merchantDefinedData' do
|
605
643
|
(1..100).each do |each|
|
606
644
|
key = "mdd_field_#{each}".to_sym
|
607
|
-
xml.tag!(
|
645
|
+
xml.tag!('mddField', options[key], 'id' => each) if options[key]
|
608
646
|
end
|
609
647
|
end
|
610
648
|
end
|
@@ -640,6 +678,13 @@ module ActiveMerchant #:nodoc:
|
|
640
678
|
end
|
641
679
|
end
|
642
680
|
|
681
|
+
def add_incremental_auth_service(xml, authorization, options)
|
682
|
+
xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do
|
683
|
+
xml.tag! 'authRequestID', authorization
|
684
|
+
end
|
685
|
+
xml.tag! 'subsequentAuthReason', options[:auth_reason]
|
686
|
+
end
|
687
|
+
|
643
688
|
def add_normalized_threeds_2_data(xml, payment_method, options)
|
644
689
|
threeds_2_options = options[:three_d_secure]
|
645
690
|
cc_brand = card_brand(payment_method).to_sym
|
@@ -853,6 +898,8 @@ module ActiveMerchant #:nodoc:
|
|
853
898
|
|
854
899
|
xml.tag! 'installment' do
|
855
900
|
xml.tag! 'totalCount', options[:installment_total_count]
|
901
|
+
xml.tag!('planType', options[:installment_plan_type]) if options[:installment_plan_type]
|
902
|
+
xml.tag!('firstInstallmentDate', options[:first_installment_date]) if options[:first_installment_date]
|
856
903
|
end
|
857
904
|
end
|
858
905
|
|
@@ -4,9 +4,9 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.test_url = 'https://sandbox.dlocal.com'
|
5
5
|
self.live_url = 'https://api.dlocal.com'
|
6
6
|
|
7
|
-
self.supported_countries = %w[AR BR CL CO MX PE UY
|
7
|
+
self.supported_countries = %w[AR BD BO BR CL CM CN CO CR DO EC EG GH IN ID KE MY MX MA NG PA PY PE PH SN ZA TR UY VN]
|
8
8
|
self.default_currency = 'USD'
|
9
|
-
self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal]
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal elo alia carnet]
|
10
10
|
|
11
11
|
self.homepage_url = 'https://dlocal.com/'
|
12
12
|
self.display_name = 'dLocal'
|
@@ -78,6 +78,7 @@ module ActiveMerchant #:nodoc:
|
|
78
78
|
add_country(post, card, options)
|
79
79
|
add_payer(post, card, options)
|
80
80
|
add_card(post, card, action, options)
|
81
|
+
add_additional_data(post, options)
|
81
82
|
post[:order_id] = options[:order_id] || generate_unique_id
|
82
83
|
post[:description] = options[:description] if options[:description]
|
83
84
|
end
|
@@ -87,6 +88,10 @@ module ActiveMerchant #:nodoc:
|
|
87
88
|
post[:currency] = (options[:currency] || currency(money))
|
88
89
|
end
|
89
90
|
|
91
|
+
def add_additional_data(post, options)
|
92
|
+
post[:additional_risk_data] = options[:additional_data]
|
93
|
+
end
|
94
|
+
|
90
95
|
def add_country(post, card, options)
|
91
96
|
return unless address = options[:billing_address] || options[:address]
|
92
97
|
|
@@ -109,6 +114,8 @@ module ActiveMerchant #:nodoc:
|
|
109
114
|
post[:payer][:document] = options[:document] if options[:document]
|
110
115
|
post[:payer][:document2] = options[:document2] if options[:document2]
|
111
116
|
post[:payer][:user_reference] = options[:user_reference] if options[:user_reference]
|
117
|
+
post[:payer][:event_uuid] = options[:device_id] if options[:device_id]
|
118
|
+
post[:payer][:onboarding_ip_address] = options[:ip] if options[:ip]
|
112
119
|
post[:payer][:address] = add_address(post, card, options)
|
113
120
|
end
|
114
121
|
|
@@ -282,7 +282,13 @@ module ActiveMerchant #:nodoc:
|
|
282
282
|
if error = response.dig('status_details', 'error')
|
283
283
|
message = "#{error.dig('reason', 'description')} | #{error['type']}"
|
284
284
|
elsif response['error_type']
|
285
|
-
|
285
|
+
if response['validation_errors'].is_a?(Array)
|
286
|
+
message = response['validation_errors'].map { |errors| "#{errors['code']}: #{errors['param']}" }.join(', ')
|
287
|
+
elsif response['validation_errors'].is_a?(Hash)
|
288
|
+
errors = response['validation_errors'].map { |k, v| "#{k}: #{v}" }.join(', ')
|
289
|
+
message = "#{response['error_type']} - #{errors}"
|
290
|
+
end
|
291
|
+
|
286
292
|
message ||= response['error_type']
|
287
293
|
end
|
288
294
|
|
@@ -39,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
|
40
40
|
def purchase(money, payment_method, options = {})
|
41
41
|
request = build_xml_request do |xml|
|
42
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
42
43
|
xml.ssl_transaction_type self.actions[:purchase]
|
43
44
|
xml.ssl_amount amount(money)
|
44
45
|
|
@@ -63,6 +64,7 @@ module ActiveMerchant #:nodoc:
|
|
63
64
|
|
64
65
|
def authorize(money, creditcard, options = {})
|
65
66
|
request = build_xml_request do |xml|
|
67
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
66
68
|
xml.ssl_transaction_type self.actions[:authorize]
|
67
69
|
xml.ssl_amount amount(money)
|
68
70
|
|
@@ -82,6 +84,8 @@ module ActiveMerchant #:nodoc:
|
|
82
84
|
|
83
85
|
def capture(money, authorization, options = {})
|
84
86
|
request = build_xml_request do |xml|
|
87
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
88
|
+
|
85
89
|
if options[:credit_card]
|
86
90
|
xml.ssl_transaction_type self.actions[:capture]
|
87
91
|
xml.ssl_amount amount(money)
|
@@ -107,6 +111,7 @@ module ActiveMerchant #:nodoc:
|
|
107
111
|
|
108
112
|
def refund(money, identification, options = {})
|
109
113
|
request = build_xml_request do |xml|
|
114
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
110
115
|
xml.ssl_transaction_type self.actions[:refund]
|
111
116
|
xml.ssl_amount amount(money)
|
112
117
|
add_txn_id(xml, identification)
|
@@ -117,6 +122,7 @@ module ActiveMerchant #:nodoc:
|
|
117
122
|
|
118
123
|
def void(identification, options = {})
|
119
124
|
request = build_xml_request do |xml|
|
125
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
120
126
|
xml.ssl_transaction_type self.actions[:void]
|
121
127
|
|
122
128
|
add_txn_id(xml, identification)
|
@@ -129,6 +135,7 @@ module ActiveMerchant #:nodoc:
|
|
129
135
|
raise ArgumentError, 'Reference credits are not supported. Please supply the original credit card or use the #refund method.' if creditcard.is_a?(String)
|
130
136
|
|
131
137
|
request = build_xml_request do |xml|
|
138
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
132
139
|
xml.ssl_transaction_type self.actions[:credit]
|
133
140
|
xml.ssl_amount amount(money)
|
134
141
|
add_invoice(xml, options)
|
@@ -143,6 +150,7 @@ module ActiveMerchant #:nodoc:
|
|
143
150
|
|
144
151
|
def verify(credit_card, options = {})
|
145
152
|
request = build_xml_request do |xml|
|
153
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
146
154
|
xml.ssl_transaction_type self.actions[:verify]
|
147
155
|
add_creditcard(xml, credit_card)
|
148
156
|
add_address(xml, options)
|
@@ -154,6 +162,7 @@ module ActiveMerchant #:nodoc:
|
|
154
162
|
|
155
163
|
def store(creditcard, options = {})
|
156
164
|
request = build_xml_request do |xml|
|
165
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
157
166
|
xml.ssl_transaction_type self.actions[:store]
|
158
167
|
xml.ssl_add_token 'Y'
|
159
168
|
add_creditcard(xml, creditcard)
|
@@ -167,6 +176,7 @@ module ActiveMerchant #:nodoc:
|
|
167
176
|
|
168
177
|
def update(token, creditcard, options = {})
|
169
178
|
request = build_xml_request do |xml|
|
179
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
170
180
|
xml.ssl_transaction_type self.actions[:update]
|
171
181
|
add_token(xml, token)
|
172
182
|
add_creditcard(xml, creditcard)
|
@@ -191,8 +201,8 @@ module ActiveMerchant #:nodoc:
|
|
191
201
|
private
|
192
202
|
|
193
203
|
def add_invoice(xml, options)
|
194
|
-
xml.ssl_invoice_number
|
195
|
-
xml.ssl_description
|
204
|
+
xml.ssl_invoice_number url_encode_truncate((options[:order_id] || options[:invoice]), 25)
|
205
|
+
xml.ssl_description url_encode_truncate(options[:description], 255)
|
196
206
|
end
|
197
207
|
|
198
208
|
def add_approval_code(xml, authorization)
|
@@ -209,8 +219,8 @@ module ActiveMerchant #:nodoc:
|
|
209
219
|
|
210
220
|
add_verification_value(xml, creditcard) if creditcard.verification_value?
|
211
221
|
|
212
|
-
xml.ssl_first_name
|
213
|
-
xml.ssl_last_name
|
222
|
+
xml.ssl_first_name url_encode_truncate(creditcard.first_name, 20)
|
223
|
+
xml.ssl_last_name url_encode_truncate(creditcard.last_name, 30)
|
214
224
|
end
|
215
225
|
|
216
226
|
def add_currency(xml, money, options)
|
@@ -230,7 +240,7 @@ module ActiveMerchant #:nodoc:
|
|
230
240
|
end
|
231
241
|
|
232
242
|
def add_customer_email(xml, options)
|
233
|
-
xml.ssl_email
|
243
|
+
xml.ssl_email url_encode_truncate(options[:email], 100) unless empty?(options[:email])
|
234
244
|
end
|
235
245
|
|
236
246
|
def add_salestax(xml, options)
|
@@ -243,27 +253,27 @@ module ActiveMerchant #:nodoc:
|
|
243
253
|
billing_address = options[:billing_address] || options[:address]
|
244
254
|
|
245
255
|
if billing_address
|
246
|
-
xml.ssl_avs_address
|
247
|
-
xml.ssl_address2
|
248
|
-
xml.ssl_avs_zip
|
249
|
-
xml.ssl_city
|
250
|
-
xml.ssl_state
|
251
|
-
xml.ssl_company
|
252
|
-
xml.ssl_phone
|
253
|
-
xml.ssl_country
|
256
|
+
xml.ssl_avs_address url_encode_truncate(billing_address[:address1], 30)
|
257
|
+
xml.ssl_address2 url_encode_truncate(billing_address[:address2], 30)
|
258
|
+
xml.ssl_avs_zip url_encode_truncate(billing_address[:zip].to_s.gsub(/[^a-zA-Z0-9]/, ''), 9)
|
259
|
+
xml.ssl_city url_encode_truncate(billing_address[:city], 30)
|
260
|
+
xml.ssl_state url_encode_truncate(billing_address[:state], 10)
|
261
|
+
xml.ssl_company url_encode_truncate(billing_address[:company], 50)
|
262
|
+
xml.ssl_phone url_encode_truncate(billing_address[:phone], 20)
|
263
|
+
xml.ssl_country url_encode_truncate(billing_address[:country], 50)
|
254
264
|
end
|
255
265
|
|
256
266
|
if shipping_address = options[:shipping_address]
|
257
|
-
xml.ssl_ship_to_address1
|
258
|
-
xml.ssl_ship_to_address2
|
259
|
-
xml.ssl_ship_to_city
|
260
|
-
xml.ssl_ship_to_company
|
261
|
-
xml.ssl_ship_to_country
|
262
|
-
xml.ssl_ship_to_first_name
|
263
|
-
xml.ssl_ship_to_last_name
|
264
|
-
xml.ssl_ship_to_phone
|
265
|
-
xml.ssl_ship_to_state
|
266
|
-
xml.ssl_ship_to_zip
|
267
|
+
xml.ssl_ship_to_address1 url_encode_truncate(shipping_address[:address1], 30)
|
268
|
+
xml.ssl_ship_to_address2 url_encode_truncate(shipping_address[:address2], 30)
|
269
|
+
xml.ssl_ship_to_city url_encode_truncate(shipping_address[:city], 30)
|
270
|
+
xml.ssl_ship_to_company url_encode_truncate(shipping_address[:company], 50)
|
271
|
+
xml.ssl_ship_to_country url_encode_truncate(shipping_address[:country], 50)
|
272
|
+
xml.ssl_ship_to_first_name url_encode_truncate(shipping_address[:first_name], 20)
|
273
|
+
xml.ssl_ship_to_last_name url_encode_truncate(shipping_address[:last_name], 30)
|
274
|
+
xml.ssl_ship_to_phone url_encode_truncate(shipping_address[:phone], 10)
|
275
|
+
xml.ssl_ship_to_state url_encode_truncate(shipping_address[:state], 2)
|
276
|
+
xml.ssl_ship_to_zip url_encode_truncate(shipping_address[:zip], 10)
|
267
277
|
end
|
268
278
|
end
|
269
279
|
|
@@ -283,9 +293,12 @@ module ActiveMerchant #:nodoc:
|
|
283
293
|
xml.ssl_cardholder_ip options[:ip] if options.has_key?(:ip)
|
284
294
|
end
|
285
295
|
|
296
|
+
# add_recurring_token is a field that can be sent in to obtain a token from Elavon for use with their tokenization program
|
286
297
|
def add_auth_purchase_params(xml, options)
|
287
298
|
xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba)
|
288
299
|
xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options)
|
300
|
+
xml.ssl_add_token options[:add_recurring_token] if options.has_key?(:add_recurring_token)
|
301
|
+
xml.ssl_token options[:ssl_token] if options.has_key?(:ssl_token)
|
289
302
|
xml.ssl_customer_code options[:customer] if options.has_key?(:customer)
|
290
303
|
xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number)
|
291
304
|
xml.ssl_entry_mode entry_mode(options) if entry_mode(options)
|
@@ -357,7 +370,7 @@ module ActiveMerchant #:nodoc:
|
|
357
370
|
|
358
371
|
def merchant_initiated_unscheduled(options)
|
359
372
|
return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled]
|
360
|
-
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
|
373
|
+
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled' || options.dig(:stored_credential, :reason_type) == 'recurring'
|
361
374
|
end
|
362
375
|
|
363
376
|
def entry_mode(options)
|
@@ -382,6 +395,7 @@ module ActiveMerchant #:nodoc:
|
|
382
395
|
request = "xmldata=#{request}".delete('&')
|
383
396
|
|
384
397
|
response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
|
398
|
+
response = hash_html_decode(response)
|
385
399
|
|
386
400
|
Response.new(
|
387
401
|
response[:result] == '0',
|
@@ -403,7 +417,7 @@ module ActiveMerchant #:nodoc:
|
|
403
417
|
def headers
|
404
418
|
{
|
405
419
|
'Accept' => 'application/xml',
|
406
|
-
'Content-type' => 'application/x-www-form-urlencoded'
|
420
|
+
'Content-type' => 'application/x-www-form-urlencoded;charset=utf8'
|
407
421
|
}
|
408
422
|
end
|
409
423
|
|
@@ -418,12 +432,40 @@ module ActiveMerchant #:nodoc:
|
|
418
432
|
[response[:approval_code], response[:txn_id]].join(';')
|
419
433
|
end
|
420
434
|
|
421
|
-
def
|
435
|
+
def url_encode_truncate(value, size)
|
422
436
|
return nil unless value
|
423
437
|
|
424
|
-
|
438
|
+
encoded = url_encode(value)
|
439
|
+
|
440
|
+
while encoded.length > size
|
441
|
+
value.chop!
|
442
|
+
encoded = url_encode(value)
|
443
|
+
end
|
444
|
+
encoded
|
445
|
+
end
|
446
|
+
|
447
|
+
def url_encode(value)
|
448
|
+
if value.is_a?(String)
|
449
|
+
encoded = CGI.escape(value)
|
450
|
+
encoded = encoded.tr('+', ' ') # don't encode spaces
|
451
|
+
encoded = encoded.gsub('%26', '%26amp;') # account for Elavon's weird '&' handling
|
452
|
+
encoded
|
453
|
+
else
|
454
|
+
value.to_s
|
455
|
+
end
|
456
|
+
end
|
425
457
|
|
426
|
-
|
458
|
+
def hash_html_decode(hash)
|
459
|
+
hash.each do |k, v|
|
460
|
+
if v.is_a?(String)
|
461
|
+
# decode all string params
|
462
|
+
v = v.gsub('&', '&') # account for Elavon's weird '&' handling
|
463
|
+
hash[k] = CGI.unescape_html(v)
|
464
|
+
elsif v.is_a?(Hash)
|
465
|
+
hash_html_decode(v)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
hash
|
427
469
|
end
|
428
470
|
end
|
429
471
|
end
|
@@ -192,6 +192,8 @@ module ActiveMerchant #:nodoc:
|
|
192
192
|
xml.PaymentType options[:payment_type] if options[:payment_type]
|
193
193
|
xml.SubmissionType options[:submission_type] if options[:submission_type]
|
194
194
|
xml.DuplicateCheckDisableFlag options[:duplicate_check_disable_flag].to_s == 'true' ? 'True' : 'False' unless options[:duplicate_check_disable_flag].nil?
|
195
|
+
xml.DuplicateOverrideFlag options[:duplicate_override_flag].to_s == 'true' ? 'True' : 'False' unless options[:duplicate_override_flag].nil?
|
196
|
+
xml.MerchantDescriptor options[:merchant_descriptor] if options[:merchant_descriptor]
|
195
197
|
end
|
196
198
|
end
|
197
199
|
|
@@ -28,6 +28,7 @@ module ActiveMerchant #:nodoc:
|
|
28
28
|
add_payment_method(post, payment_method, options)
|
29
29
|
add_billing_address(post, payment_method, options)
|
30
30
|
add_shipping_address(post, options)
|
31
|
+
add_xdata(post, options)
|
31
32
|
post[:action] = 'sale'
|
32
33
|
|
33
34
|
commit(:post, post)
|
@@ -41,6 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
41
42
|
add_payment_method(post, payment_method, options)
|
42
43
|
add_billing_address(post, payment_method, options)
|
43
44
|
add_shipping_address(post, options)
|
45
|
+
add_xdata(post, options)
|
44
46
|
post[:action] = 'authorize'
|
45
47
|
|
46
48
|
commit(:post, post)
|
@@ -122,6 +124,16 @@ module ActiveMerchant #:nodoc:
|
|
122
124
|
post[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
|
123
125
|
end
|
124
126
|
|
127
|
+
def add_xdata(post, options)
|
128
|
+
post[:xdata] = {}
|
129
|
+
if xdata = options[:xdata]
|
130
|
+
(1..9).each do |n|
|
131
|
+
field = "xdata_#{n}".to_sym
|
132
|
+
post[:xdata][field] = xdata[field] if xdata[field]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
125
137
|
def add_billing_address(post, payment, options)
|
126
138
|
post[:billing_address] = {}
|
127
139
|
if address = options[:billing_address] || options[:address]
|