activemerchant 1.119.0 → 1.120.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +75 -1
- data/README.md +3 -1
- data/lib/active_merchant/billing/check.rb +10 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +9 -3
- data/lib/active_merchant/billing/gateways/adyen.rb +20 -6
- data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -3
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +47 -7
- data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +21 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +13 -8
- data/lib/active_merchant/billing/gateways/cyber_source.rb +23 -3
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +11 -1
- data/lib/active_merchant/billing/gateways/forte.rb +12 -0
- data/lib/active_merchant/billing/gateways/hps.rb +55 -1
- data/lib/active_merchant/billing/gateways/litle.rb +1 -1
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +2 -2
- data/lib/active_merchant/billing/gateways/netbanx.rb +26 -2
- data/lib/active_merchant/billing/gateways/orbital.rb +62 -53
- data/lib/active_merchant/billing/gateways/payeezy.rb +30 -6
- data/lib/active_merchant/billing/gateways/payment_express.rb +5 -5
- 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/redsys.rb +19 -4
- data/lib/active_merchant/billing/gateways/safe_charge.rb +18 -11
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +61 -25
- data/lib/active_merchant/billing/gateways/vpos.rb +172 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +24 -11
- data/lib/active_merchant/version.rb +1 -1
- data/lib/certs/cacert.pem +1582 -2431
- metadata +5 -3
@@ -334,6 +334,7 @@ module ActiveMerchant #:nodoc:
|
|
334
334
|
post[:f23] = options[:f23] if options[:f23]
|
335
335
|
post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
|
336
336
|
options.dig(:stored_credential, :initiator) == 'merchant' ? post[:'3ds_channel'] = '03' : post[:'3ds_channel'] = '02'
|
337
|
+
post[:'3ds_reqchallengeind'] = options[:three_ds_reqchallengeind] if options[:three_ds_reqchallengeind]
|
337
338
|
post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
|
338
339
|
post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
|
339
340
|
post[:d5] = browser_info[:user_agent]
|
@@ -345,14 +346,7 @@ module ActiveMerchant #:nodoc:
|
|
345
346
|
post[:d6] = browser_info[:language]
|
346
347
|
post[:'3ds_browserjavaenabled'] = browser_info[:java]
|
347
348
|
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
|
349
|
+
add_complete_shipping_address(post, options[:shipping_address]) if options[:shipping_address]
|
356
350
|
elsif options[:three_d_secure]
|
357
351
|
add_normalized_3d_secure_2_data(post, options)
|
358
352
|
end
|
@@ -372,6 +366,17 @@ module ActiveMerchant #:nodoc:
|
|
372
366
|
end
|
373
367
|
end
|
374
368
|
|
369
|
+
def add_complete_shipping_address(post, shipping_address)
|
370
|
+
return if shipping_address.values.any?(&:blank?)
|
371
|
+
|
372
|
+
post[:'3ds_shipaddrstate'] = shipping_address[:state]
|
373
|
+
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
|
374
|
+
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
|
375
|
+
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
|
376
|
+
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
|
377
|
+
post[:'3ds_shipaddrcity'] = shipping_address[:city]
|
378
|
+
end
|
379
|
+
|
375
380
|
def add_normalized_3d_secure_2_data(post, options)
|
376
381
|
three_d_secure_options = options[:three_d_secure]
|
377
382
|
|
@@ -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',
|
@@ -298,6 +298,8 @@ module ActiveMerchant #:nodoc:
|
|
298
298
|
add_partner_solution_id(xml)
|
299
299
|
add_stored_credential_options(xml, options)
|
300
300
|
add_merchant_description(xml, options)
|
301
|
+
add_sales_slip_number(xml, options)
|
302
|
+
add_airline_data(xml, options)
|
301
303
|
|
302
304
|
xml.target!
|
303
305
|
end
|
@@ -336,6 +338,8 @@ module ActiveMerchant #:nodoc:
|
|
336
338
|
add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
|
337
339
|
add_decision_manager_fields(xml, options)
|
338
340
|
add_mdd_fields(xml, options)
|
341
|
+
add_sales_slip_number(xml, options)
|
342
|
+
add_airline_data(xml, options)
|
339
343
|
if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
|
340
344
|
add_check_service(xml)
|
341
345
|
add_issuer_additional_data(xml, options)
|
@@ -523,6 +527,18 @@ module ActiveMerchant #:nodoc:
|
|
523
527
|
end
|
524
528
|
end
|
525
529
|
|
530
|
+
def add_sales_slip_number(xml, options)
|
531
|
+
xml.tag! 'salesSlipNumber', options[:sales_slip_number] if options[:sales_slip_number]
|
532
|
+
end
|
533
|
+
|
534
|
+
def add_airline_data(xml, options)
|
535
|
+
return unless options[:airline_agent_code]
|
536
|
+
|
537
|
+
xml.tag! 'airlineData' do
|
538
|
+
xml.tag! 'agentCode', options[:airline_agent_code]
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
526
542
|
def add_purchase_data(xml, money = 0, include_grand_total = false, options = {})
|
527
543
|
xml.tag! 'purchaseTotals' do
|
528
544
|
xml.tag! 'currency', options[:currency] || currency(money)
|
@@ -532,6 +548,7 @@ module ActiveMerchant #:nodoc:
|
|
532
548
|
|
533
549
|
def add_address(xml, payment_method, address, options, shipTo = false)
|
534
550
|
first_name, last_name = address_names(address[:name], payment_method)
|
551
|
+
bill_to_merchant_tax_id = options[:merchant_tax_id] unless shipTo
|
535
552
|
|
536
553
|
xml.tag! shipTo ? 'shipTo' : 'billTo' do
|
537
554
|
xml.tag! 'firstName', first_name if first_name
|
@@ -549,6 +566,7 @@ module ActiveMerchant #:nodoc:
|
|
549
566
|
xml.tag! 'ipAddress', options[:ip] unless options[:ip].blank? || shipTo
|
550
567
|
xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
|
551
568
|
xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
|
569
|
+
xml.tag! 'merchantTaxID', bill_to_merchant_tax_id unless bill_to_merchant_tax_id.blank?
|
552
570
|
end
|
553
571
|
end
|
554
572
|
|
@@ -604,7 +622,7 @@ module ActiveMerchant #:nodoc:
|
|
604
622
|
xml.tag! 'merchantDefinedData' do
|
605
623
|
(1..100).each do |each|
|
606
624
|
key = "mdd_field_#{each}".to_sym
|
607
|
-
xml.tag!(
|
625
|
+
xml.tag!('mddField', options[key], 'id' => each) if options[key]
|
608
626
|
end
|
609
627
|
end
|
610
628
|
end
|
@@ -853,6 +871,8 @@ module ActiveMerchant #:nodoc:
|
|
853
871
|
|
854
872
|
xml.tag! 'installment' do
|
855
873
|
xml.tag! 'totalCount', options[:installment_total_count]
|
874
|
+
xml.tag!('planType', options[:installment_plan_type]) if options[:installment_plan_type]
|
875
|
+
xml.tag!('firstInstallmentDate', options[:first_installment_date]) if options[:first_installment_date]
|
856
876
|
end
|
857
877
|
end
|
858
878
|
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
self.supported_countries = %w[AR BR CL CO MX PE UY TR]
|
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'
|
@@ -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)
|
@@ -423,7 +433,7 @@ module ActiveMerchant #:nodoc:
|
|
423
433
|
|
424
434
|
difference = value.force_encoding('iso-8859-1').length - value.length
|
425
435
|
|
426
|
-
return value.to_s[0, (size - difference)]
|
436
|
+
return value.delete('&"<>').to_s[0, (size - difference)]
|
427
437
|
end
|
428
438
|
end
|
429
439
|
end
|
@@ -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]
|
@@ -39,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
add_descriptor_name(xml, options)
|
40
40
|
add_card_or_token_payment(xml, card_or_token, options)
|
41
41
|
add_three_d_secure(xml, card_or_token, options)
|
42
|
+
add_stored_credentials(xml, options)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
@@ -52,6 +53,8 @@ module ActiveMerchant #:nodoc:
|
|
52
53
|
def purchase(money, payment_method, options = {})
|
53
54
|
if payment_method.is_a?(Check)
|
54
55
|
commit_check_sale(money, payment_method, options)
|
56
|
+
elsif options.dig(:stored_credential, :reason_type) == 'recurring'
|
57
|
+
commit_recurring_billing_sale(money, payment_method, options)
|
55
58
|
else
|
56
59
|
commit_credit_sale(money, payment_method, options)
|
57
60
|
end
|
@@ -131,6 +134,21 @@ module ActiveMerchant #:nodoc:
|
|
131
134
|
add_descriptor_name(xml, options)
|
132
135
|
add_card_or_token_payment(xml, card_or_token, options)
|
133
136
|
add_three_d_secure(xml, card_or_token, options)
|
137
|
+
add_stored_credentials(xml, options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def commit_recurring_billing_sale(money, card_or_token, options)
|
142
|
+
commit('RecurringBilling') do |xml|
|
143
|
+
add_amount(xml, money)
|
144
|
+
add_allow_dup(xml)
|
145
|
+
add_card_or_token_customer_data(xml, card_or_token, options)
|
146
|
+
add_details(xml, options)
|
147
|
+
add_descriptor_name(xml, options)
|
148
|
+
add_card_or_token_payment(xml, card_or_token, options)
|
149
|
+
add_three_d_secure(xml, card_or_token, options)
|
150
|
+
add_stored_credentials(xml, options)
|
151
|
+
add_stored_credentials_for_recurring_billing(xml, options)
|
134
152
|
end
|
135
153
|
end
|
136
154
|
|
@@ -157,7 +175,7 @@ module ActiveMerchant #:nodoc:
|
|
157
175
|
xml.hps :CardHolderAddr, billing_address[:address1] if billing_address[:address1]
|
158
176
|
xml.hps :CardHolderCity, billing_address[:city] if billing_address[:city]
|
159
177
|
xml.hps :CardHolderState, billing_address[:state] if billing_address[:state]
|
160
|
-
xml.hps :CardHolderZip, billing_address[:zip] if billing_address[:zip]
|
178
|
+
xml.hps :CardHolderZip, alphanumeric_zip(billing_address[:zip]) if billing_address[:zip]
|
161
179
|
end
|
162
180
|
end
|
163
181
|
end
|
@@ -265,6 +283,38 @@ module ActiveMerchant #:nodoc:
|
|
265
283
|
end
|
266
284
|
end
|
267
285
|
|
286
|
+
# We do not currently support installments on this gateway.
|
287
|
+
# The HPS gateway treats recurring transactions as a seperate transaction type
|
288
|
+
def add_stored_credentials(xml, options)
|
289
|
+
return unless options[:stored_credential]
|
290
|
+
|
291
|
+
xml.hps :CardOnFileData do
|
292
|
+
if options[:stored_credential][:initiator] == 'customer'
|
293
|
+
xml.hps :CardOnFile, 'C'
|
294
|
+
elsif options[:stored_credential][:initiator] == 'merchant'
|
295
|
+
xml.hps :CardOnFile, 'M'
|
296
|
+
else
|
297
|
+
return
|
298
|
+
end
|
299
|
+
|
300
|
+
if options[:stored_credential][:network_transaction_id]
|
301
|
+
xml.hps :CardBrandTxnId, options[:stored_credential][:network_transaction_id]
|
302
|
+
else
|
303
|
+
return
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def add_stored_credentials_for_recurring_billing(xml, options)
|
309
|
+
xml.hps :RecurringData do
|
310
|
+
if options[:stored_credential][:reason_type] = 'recurring'
|
311
|
+
xml.hps :OneTime, 'N'
|
312
|
+
else
|
313
|
+
xml.hps :OneTime, 'Y'
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
268
318
|
def strip_leading_zero(value)
|
269
319
|
return value unless value[0] == '0'
|
270
320
|
|
@@ -389,6 +439,10 @@ module ActiveMerchant #:nodoc:
|
|
389
439
|
@options[:secret_api_key]&.include?('_cert_')
|
390
440
|
end
|
391
441
|
|
442
|
+
def alphanumeric_zip(zip)
|
443
|
+
zip.gsub(/[^0-9a-z]/i, '')
|
444
|
+
end
|
445
|
+
|
392
446
|
ISSUER_MESSAGES = {
|
393
447
|
'13' => 'Must be greater than or equal 0.',
|
394
448
|
'14' => 'The card number is incorrect.',
|
@@ -494,7 +494,7 @@ module ActiveMerchant #:nodoc:
|
|
494
494
|
attributes = {}
|
495
495
|
attributes[:id] = truncate(options[:id] || options[:order_id], 24)
|
496
496
|
attributes[:reportGroup] = options[:merchant] || 'Default Report Group'
|
497
|
-
attributes[:customerId] = options[:
|
497
|
+
attributes[:customerId] = options[:customer_id]
|
498
498
|
attributes.delete_if { |_key, value| value == nil }
|
499
499
|
attributes
|
500
500
|
end
|
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.live_url = self.test_url = 'https://api.mercadopago.com/v1'
|
5
5
|
|
6
6
|
self.supported_countries = %w[AR BR CL CO MX PE UY]
|
7
|
-
self.supported_cardtypes = %i[visa master american_express elo cabal naranja]
|
7
|
+
self.supported_cardtypes = %i[visa master american_express elo cabal naranja creditel]
|
8
8
|
|
9
9
|
self.homepage_url = 'https://www.mercadopago.com/'
|
10
10
|
self.display_name = 'Mercado Pago'
|
@@ -105,7 +105,7 @@ module ActiveMerchant #:nodoc:
|
|
105
105
|
|
106
106
|
def authorize_request(money, payment, options = {})
|
107
107
|
post = purchase_request(money, payment, options)
|
108
|
-
post[:capture] = false
|
108
|
+
post[:capture] = options[:capture] || false
|
109
109
|
post
|
110
110
|
end
|
111
111
|
|
@@ -22,6 +22,22 @@ module ActiveMerchant #:nodoc:
|
|
22
22
|
self.homepage_url = 'https://processing.paysafe.com/'
|
23
23
|
self.display_name = 'Netbanx by PaySafe'
|
24
24
|
|
25
|
+
AVS_CODE_CONVERTER = {
|
26
|
+
'MATCH' => 'X',
|
27
|
+
'MATCH_ADDRESS_ONLY' => 'A',
|
28
|
+
'MATCH_ZIP_ONLY' => 'Z',
|
29
|
+
'NO_MATCH' => 'N',
|
30
|
+
'NOT_PROCESSED' => 'U',
|
31
|
+
'UNKNOWN' => 'Q'
|
32
|
+
}
|
33
|
+
|
34
|
+
CVV_CODE_CONVERTER = {
|
35
|
+
'MATCH' => 'M',
|
36
|
+
'NO_MATCH' => 'N',
|
37
|
+
'NOT_PROCESSED' => 'P',
|
38
|
+
'UNKNOWN' => 'U'
|
39
|
+
}
|
40
|
+
|
25
41
|
def initialize(options = {})
|
26
42
|
requires!(options, :account_number, :api_key)
|
27
43
|
super
|
@@ -256,11 +272,19 @@ module ActiveMerchant #:nodoc:
|
|
256
272
|
test: test?,
|
257
273
|
error_code: error_code_from(response),
|
258
274
|
authorization: authorization_from(success, get_url(uri), method, response),
|
259
|
-
avs_result:
|
260
|
-
cvv_result:
|
275
|
+
avs_result: avs_result(response),
|
276
|
+
cvv_result: cvv_result(response)
|
261
277
|
)
|
262
278
|
end
|
263
279
|
|
280
|
+
def avs_result(response)
|
281
|
+
AVSResult.new(code: AVS_CODE_CONVERTER[response['avsResponse']])
|
282
|
+
end
|
283
|
+
|
284
|
+
def cvv_result(response)
|
285
|
+
CVVResult.new(CVV_CODE_CONVERTER[response['cvvVerification']])
|
286
|
+
end
|
287
|
+
|
264
288
|
def get_url(uri)
|
265
289
|
url = (test? ? test_url : live_url)
|
266
290
|
if /^customervault/.match?(uri)
|
@@ -190,31 +190,6 @@ module ActiveMerchant #:nodoc:
|
|
190
190
|
'checking' => 'C'
|
191
191
|
}
|
192
192
|
|
193
|
-
# Fixed possible values for orbital ECP attributes
|
194
|
-
# Auth methods for electronic checks can be:
|
195
|
-
# Written, Internet, Telephonic, Account Receivable, Point of Purchase.
|
196
|
-
# Default auth method for ECP is Internet (I).
|
197
|
-
# Bank payment delivery can be either ACH (Automated Clearing House) or Best Possible.
|
198
|
-
# Default Bank Payment Delivery is Best Possible (B).
|
199
|
-
# Action codes to be used for Early Warning System and additional validations.
|
200
|
-
# Valid combinations of Message Type and Action Code to be used are:
|
201
|
-
# A W1
|
202
|
-
# AC W1
|
203
|
-
# FC W4
|
204
|
-
# R W6
|
205
|
-
# FC W8
|
206
|
-
# A W3
|
207
|
-
# AC W3
|
208
|
-
# FC W5
|
209
|
-
# R W7
|
210
|
-
# Default Action code for ECP is nil.
|
211
|
-
# Electronic check to be processed on same day (Y) or next day (N).
|
212
|
-
# Default ECP Same Day Index is Yes (Y).
|
213
|
-
ECP_AUTH_METHODS = %w[W I T A P]
|
214
|
-
ECP_BANK_PAYMENT = %w[A B]
|
215
|
-
ECP_ACTION_CODES = %w[LO ND NC W1 W3 W4 W5 W6 W7 W8 W9]
|
216
|
-
ECP_SAME_DAY = %w[Y N]
|
217
|
-
|
218
193
|
def initialize(options = {})
|
219
194
|
requires!(options, :merchant_id)
|
220
195
|
requires!(options, :login, :password) unless options[:ip_authentication]
|
@@ -224,6 +199,14 @@ module ActiveMerchant #:nodoc:
|
|
224
199
|
|
225
200
|
# A – Authorization request
|
226
201
|
def authorize(money, payment_source, options = {})
|
202
|
+
# ECP for Orbital requires $0 prenotes so ensure
|
203
|
+
# if we are doing a force capture with a check, that
|
204
|
+
# we do a purchase here
|
205
|
+
if options[:force_capture] && payment_source.is_a?(Check) &&
|
206
|
+
(options[:action_code].include?('W8') || options[:action_code].include?('W9') || options[:action_code].include?('ND'))
|
207
|
+
return purchase(money, payment_source, options)
|
208
|
+
end
|
209
|
+
|
227
210
|
order = build_new_order_xml(AUTH_ONLY, money, payment_source, options) do |xml|
|
228
211
|
add_payment_source(xml, payment_source, options)
|
229
212
|
add_address(xml, payment_source, options)
|
@@ -232,7 +215,7 @@ module ActiveMerchant #:nodoc:
|
|
232
215
|
add_managed_billing(xml, options)
|
233
216
|
end
|
234
217
|
end
|
235
|
-
commit(order, :authorize, options[:trace_number])
|
218
|
+
commit(order, :authorize, options[:retry_logic], options[:trace_number])
|
236
219
|
end
|
237
220
|
|
238
221
|
def verify(creditcard, options = {})
|
@@ -252,26 +235,34 @@ module ActiveMerchant #:nodoc:
|
|
252
235
|
add_managed_billing(xml, options)
|
253
236
|
end
|
254
237
|
end
|
255
|
-
|
238
|
+
|
239
|
+
commit(order, :purchase, options[:retry_logic], options[:trace_number])
|
256
240
|
end
|
257
241
|
|
258
242
|
# MFC - Mark For Capture
|
259
243
|
def capture(money, authorization, options = {})
|
260
|
-
commit(build_mark_for_capture_xml(money, authorization, options), :capture)
|
244
|
+
commit(build_mark_for_capture_xml(money, authorization, options), :capture, options[:retry_logic], options[:trace_number])
|
261
245
|
end
|
262
246
|
|
263
247
|
# R – Refund request
|
264
248
|
def refund(money, authorization, options = {})
|
265
|
-
|
266
|
-
|
249
|
+
payment_method = options[:payment_method]
|
250
|
+
order = build_new_order_xml(REFUND, money, payment_method, options.merge(authorization: authorization)) do |xml|
|
251
|
+
if payment_method.is_a?(Check)
|
252
|
+
add_echeck(xml, payment_method, options)
|
253
|
+
else
|
254
|
+
add_refund(xml, options[:currency])
|
255
|
+
end
|
267
256
|
xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn]
|
268
257
|
end
|
269
|
-
commit(order, :refund, options[:trace_number])
|
258
|
+
commit(order, :refund, options[:retry_logic], options[:trace_number])
|
270
259
|
end
|
271
260
|
|
272
|
-
def credit(money,
|
273
|
-
|
274
|
-
|
261
|
+
def credit(money, payment_method, options = {})
|
262
|
+
order = build_new_order_xml(REFUND, money, payment_method, options) do |xml|
|
263
|
+
add_payment_source(xml, payment_method, options)
|
264
|
+
end
|
265
|
+
commit(order, :refund, options[:retry_logic], options[:trace_number])
|
275
266
|
end
|
276
267
|
|
277
268
|
def void(authorization, options = {}, deprecated = {})
|
@@ -281,7 +272,7 @@ module ActiveMerchant #:nodoc:
|
|
281
272
|
end
|
282
273
|
|
283
274
|
order = build_void_request_xml(authorization, options)
|
284
|
-
commit(order, :void, options[:trace_number])
|
275
|
+
commit(order, :void, options[:retry_logic], options[:trace_number])
|
285
276
|
end
|
286
277
|
|
287
278
|
# ==== Customer Profiles
|
@@ -398,9 +389,9 @@ module ActiveMerchant #:nodoc:
|
|
398
389
|
def add_level3_tax(xml, options = {})
|
399
390
|
if (level3 = options[:level_3_data])
|
400
391
|
xml.tag! :PC3VATtaxAmt, byte_limit(level3[:vat_tax], 12) if level3[:vat_tax]
|
401
|
-
xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax]
|
402
392
|
xml.tag! :PC3VATtaxRate, byte_limit(level3[:vat_rate], 4) if level3[:vat_rate]
|
403
393
|
xml.tag! :PC3AltTaxInd, byte_limit(level3[:alt_ind], 15) if level3[:alt_ind]
|
394
|
+
xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax]
|
404
395
|
end
|
405
396
|
end
|
406
397
|
|
@@ -458,20 +449,22 @@ module ActiveMerchant #:nodoc:
|
|
458
449
|
xml.tag! :CardIndicators, options[:card_indicators] if options[:card_indicators]
|
459
450
|
end
|
460
451
|
|
461
|
-
def add_address(xml,
|
462
|
-
|
452
|
+
def add_address(xml, payment_source, options)
|
453
|
+
address = get_address(options)
|
454
|
+
|
455
|
+
unless address.blank?
|
463
456
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s) || empty?(address[:country])
|
464
457
|
|
465
458
|
if avs_supported
|
466
|
-
xml.tag! :AVSzip,
|
459
|
+
xml.tag! :AVSzip, byte_limit(format_address_field(address[:zip]), 10)
|
467
460
|
xml.tag! :AVSaddress1, byte_limit(format_address_field(address[:address1]), 30)
|
468
461
|
xml.tag! :AVSaddress2, byte_limit(format_address_field(address[:address2]), 30)
|
469
|
-
xml.tag! :AVScity,
|
470
|
-
xml.tag! :AVSstate,
|
462
|
+
xml.tag! :AVScity, byte_limit(format_address_field(address[:city]), 20)
|
463
|
+
xml.tag! :AVSstate, byte_limit(format_address_field(address[:state]), 2)
|
471
464
|
xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil)
|
472
465
|
end
|
473
466
|
|
474
|
-
xml.tag! :AVSname, (
|
467
|
+
xml.tag! :AVSname, (payment_source&.name ? payment_source.name[0..29] : nil)
|
475
468
|
xml.tag! :AVScountryCode, (avs_supported ? byte_limit(format_address_field(address[:country]), 2) : '')
|
476
469
|
|
477
470
|
# Needs to come after AVScountryCode
|
@@ -497,7 +490,9 @@ module ActiveMerchant #:nodoc:
|
|
497
490
|
|
498
491
|
# For Profile requests
|
499
492
|
def add_customer_address(xml, options)
|
500
|
-
|
493
|
+
address = get_address(options)
|
494
|
+
|
495
|
+
unless address.blank?
|
501
496
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s)
|
502
497
|
|
503
498
|
xml.tag! :CustomerAddress1, byte_limit(format_address_field(address[:address1]), 30)
|
@@ -530,8 +525,15 @@ module ActiveMerchant #:nodoc:
|
|
530
525
|
xml.tag! :BCRtNum, check.routing_number
|
531
526
|
xml.tag! :CheckDDA, check.account_number if check.account_number
|
532
527
|
xml.tag! :BankAccountType, ACCOUNT_TYPE[check.account_type] if ACCOUNT_TYPE[check.account_type]
|
533
|
-
xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method]
|
534
|
-
|
528
|
+
xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method]
|
529
|
+
|
530
|
+
if options[:payment_delivery]
|
531
|
+
xml.tag! :BankPmtDelv, options[:payment_delivery]
|
532
|
+
else
|
533
|
+
xml.tag! :BankPmtDelv, 'B'
|
534
|
+
end
|
535
|
+
|
536
|
+
xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank?
|
535
537
|
end
|
536
538
|
end
|
537
539
|
|
@@ -664,7 +666,9 @@ module ActiveMerchant #:nodoc:
|
|
664
666
|
end
|
665
667
|
|
666
668
|
def add_ews_details(xml, payment_source, parameters = {})
|
667
|
-
|
669
|
+
split_name = payment_source.first_name.split if payment_source.first_name
|
670
|
+
xml.tag! :EWSFirstName, split_name[0]
|
671
|
+
xml.tag! :EWSMiddleName, split_name[1..-1].join(' ')
|
668
672
|
xml.tag! :EWSLastName, payment_source.last_name
|
669
673
|
xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty?
|
670
674
|
|
@@ -684,7 +688,7 @@ module ActiveMerchant #:nodoc:
|
|
684
688
|
# Adds ECP conditional attributes depending on other attribute values
|
685
689
|
def add_ecp_details(xml, payment_source, parameters = {})
|
686
690
|
requires!(payment_source.account_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
|
687
|
-
xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code]
|
691
|
+
xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code]
|
688
692
|
xml.tag! :ECPCheckSerialNumber, payment_source.account_number if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
|
689
693
|
if parameters[:auth_method]&.eql?('P')
|
690
694
|
xml.tag! :ECPTerminalCity, parameters[:terminal_city] if parameters[:terminal_city]
|
@@ -753,9 +757,9 @@ module ActiveMerchant #:nodoc:
|
|
753
757
|
end
|
754
758
|
end
|
755
759
|
|
756
|
-
def commit(order, message_type, trace_number = nil)
|
760
|
+
def commit(order, message_type, retry_logic = nil, trace_number = nil)
|
757
761
|
headers = POST_HEADERS.merge('Content-length' => order.size.to_s)
|
758
|
-
if @options[:retry_logic] && trace_number
|
762
|
+
if (@options[:retry_logic] || retry_logic) && trace_number
|
759
763
|
headers['Trace-number'] = trace_number.to_s
|
760
764
|
headers['Merchant-Id'] = @options[:merchant_id]
|
761
765
|
end
|
@@ -854,12 +858,12 @@ module ActiveMerchant #:nodoc:
|
|
854
858
|
add_aevv(xml, payment_source, three_d_secure)
|
855
859
|
add_digital_token_cryptogram(xml, payment_source)
|
856
860
|
|
857
|
-
xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] &&
|
861
|
+
xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && payment_source.is_a?(Check)
|
858
862
|
|
859
863
|
set_recurring_ind(xml, parameters)
|
860
864
|
|
861
865
|
# Append Transaction Reference Number at the end for Refund transactions
|
862
|
-
if action == REFUND
|
866
|
+
if action == REFUND && parameters[:authorization]
|
863
867
|
tx_ref_num, = split_authorization(parameters[:authorization])
|
864
868
|
xml.tag! :TxRefNum, tx_ref_num
|
865
869
|
end
|
@@ -906,6 +910,7 @@ module ActiveMerchant #:nodoc:
|
|
906
910
|
add_level2_advice_addendum(xml, parameters)
|
907
911
|
add_level3_purchase(xml, parameters)
|
908
912
|
add_level3_tax(xml, parameters)
|
913
|
+
add_line_items(xml, parameters) if parameters[:line_items]
|
909
914
|
end
|
910
915
|
end
|
911
916
|
xml.target!
|
@@ -968,6 +973,10 @@ module ActiveMerchant #:nodoc:
|
|
968
973
|
@options[:merchant_id].length == 6
|
969
974
|
end
|
970
975
|
|
976
|
+
def get_address(options)
|
977
|
+
options[:billing_address] || options[:address]
|
978
|
+
end
|
979
|
+
|
971
980
|
# The valid characters include:
|
972
981
|
#
|
973
982
|
# 1. all letters and digits
|
@@ -1105,7 +1114,7 @@ module ActiveMerchant #:nodoc:
|
|
1105
1114
|
'Y' => %w(9 A B C H JA JD M2 M3 M5 N5 N8 N9 X Z),
|
1106
1115
|
'N' => %w(D E F G M8),
|
1107
1116
|
'X' => %w(4 J R),
|
1108
|
-
|
1117
|
+
nil => %w(1 2 3 5 6 7 8 JB JC M1 M4 M6 M7 N3 N4 N6 N7 UK)
|
1109
1118
|
}.inject({}) do |map, (type, codes)|
|
1110
1119
|
codes.each { |code| map[code] = type }
|
1111
1120
|
map
|
@@ -1116,7 +1125,7 @@ module ActiveMerchant #:nodoc:
|
|
1116
1125
|
'Y' => %w(9 B D F H JA JB M2 M4 M5 M6 M7 N3 N5 N7 N8 N9 X),
|
1117
1126
|
'N' => %w(A C E G M8 Z),
|
1118
1127
|
'X' => %w(4 J R),
|
1119
|
-
|
1128
|
+
nil => %w(1 2 3 5 6 7 8 JC JD M1 M3 N4 N6 UK)
|
1120
1129
|
}.inject({}) do |map, (type, codes)|
|
1121
1130
|
codes.each { |code| map[code] = type }
|
1122
1131
|
map
|