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
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
class OrbitalGateway < Gateway
|
31
31
|
include Empty
|
32
32
|
|
33
|
-
API_VERSION = '
|
33
|
+
API_VERSION = '8.1'
|
34
34
|
|
35
35
|
POST_HEADERS = {
|
36
36
|
'MIME-Version' => '1.1',
|
@@ -42,6 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
42
42
|
}
|
43
43
|
|
44
44
|
SUCCESS = '0'
|
45
|
+
APPROVAL_SUCCESS = '1'
|
45
46
|
|
46
47
|
APPROVED = [
|
47
48
|
'00', # Approved
|
@@ -60,7 +61,8 @@ module ActiveMerchant #:nodoc:
|
|
60
61
|
'93', # Approved high fraud
|
61
62
|
'94', # Approved fraud service unavailable
|
62
63
|
'E7', # Stored
|
63
|
-
'PA'
|
64
|
+
'PA', # Partial approval
|
65
|
+
'P1' # ECP - AVS - Account Status Verification and/or AOA data is in a positive status.
|
64
66
|
]
|
65
67
|
|
66
68
|
class_attribute :secondary_test_url, :secondary_live_url
|
@@ -183,6 +185,12 @@ module ActiveMerchant #:nodoc:
|
|
183
185
|
|
184
186
|
SENSITIVE_FIELDS = %i[account_num cc_account_num]
|
185
187
|
|
188
|
+
# Bank account types to be used for check processing
|
189
|
+
ACCOUNT_TYPE = {
|
190
|
+
'savings' => 'S',
|
191
|
+
'checking' => 'C'
|
192
|
+
}
|
193
|
+
|
186
194
|
def initialize(options = {})
|
187
195
|
requires!(options, :merchant_id)
|
188
196
|
requires!(options, :login, :password) unless options[:ip_authentication]
|
@@ -191,16 +199,24 @@ module ActiveMerchant #:nodoc:
|
|
191
199
|
end
|
192
200
|
|
193
201
|
# A – Authorization request
|
194
|
-
def authorize(money,
|
195
|
-
|
196
|
-
|
197
|
-
|
202
|
+
def authorize(money, payment_source, options = {})
|
203
|
+
# ECP for Orbital requires $0 prenotes so ensure
|
204
|
+
# if we are doing a force capture with a check, that
|
205
|
+
# we do a purchase here
|
206
|
+
if options[:force_capture] && payment_source.is_a?(Check) &&
|
207
|
+
(options[:action_code].include?('W8') || options[:action_code].include?('W9') || options[:action_code].include?('ND'))
|
208
|
+
return purchase(money, payment_source, options)
|
209
|
+
end
|
210
|
+
|
211
|
+
order = build_new_order_xml(AUTH_ONLY, money, payment_source, options) do |xml|
|
212
|
+
add_payment_source(xml, payment_source, options)
|
213
|
+
add_address(xml, payment_source, options)
|
198
214
|
if @options[:customer_profiles]
|
199
|
-
add_customer_data(xml,
|
215
|
+
add_customer_data(xml, payment_source, options)
|
200
216
|
add_managed_billing(xml, options)
|
201
217
|
end
|
202
218
|
end
|
203
|
-
commit(order, :authorize, options[:trace_number])
|
219
|
+
commit(order, :authorize, options[:retry_logic], options[:trace_number])
|
204
220
|
end
|
205
221
|
|
206
222
|
def verify(creditcard, options = {})
|
@@ -211,35 +227,43 @@ module ActiveMerchant #:nodoc:
|
|
211
227
|
end
|
212
228
|
|
213
229
|
# AC – Authorization and Capture
|
214
|
-
def purchase(money,
|
215
|
-
order = build_new_order_xml(AUTH_AND_CAPTURE, money,
|
216
|
-
|
217
|
-
add_address(xml,
|
230
|
+
def purchase(money, payment_source, options = {})
|
231
|
+
order = build_new_order_xml(options[:force_capture] ? FORCE_AUTH_AND_CAPTURE : AUTH_AND_CAPTURE, money, payment_source, options) do |xml|
|
232
|
+
add_payment_source(xml, payment_source, options)
|
233
|
+
add_address(xml, payment_source, options)
|
218
234
|
if @options[:customer_profiles]
|
219
|
-
add_customer_data(xml,
|
235
|
+
add_customer_data(xml, payment_source, options)
|
220
236
|
add_managed_billing(xml, options)
|
221
237
|
end
|
222
238
|
end
|
223
|
-
|
239
|
+
|
240
|
+
commit(order, :purchase, options[:retry_logic], options[:trace_number])
|
224
241
|
end
|
225
242
|
|
226
243
|
# MFC - Mark For Capture
|
227
244
|
def capture(money, authorization, options = {})
|
228
|
-
commit(build_mark_for_capture_xml(money, authorization, options), :capture)
|
245
|
+
commit(build_mark_for_capture_xml(money, authorization, options), :capture, options[:retry_logic], options[:trace_number])
|
229
246
|
end
|
230
247
|
|
231
248
|
# R – Refund request
|
232
249
|
def refund(money, authorization, options = {})
|
233
|
-
|
234
|
-
|
250
|
+
payment_method = options[:payment_method]
|
251
|
+
order = build_new_order_xml(REFUND, money, payment_method, options.merge(authorization: authorization)) do |xml|
|
252
|
+
if payment_method.is_a?(Check)
|
253
|
+
add_echeck(xml, payment_method, options)
|
254
|
+
else
|
255
|
+
add_refund(xml, options[:currency])
|
256
|
+
end
|
235
257
|
xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn]
|
236
258
|
end
|
237
|
-
commit(order, :refund, options[:trace_number])
|
259
|
+
commit(order, :refund, options[:retry_logic], options[:trace_number])
|
238
260
|
end
|
239
261
|
|
240
|
-
def credit(money,
|
241
|
-
|
242
|
-
|
262
|
+
def credit(money, payment_method, options = {})
|
263
|
+
order = build_new_order_xml(REFUND, money, payment_method, options) do |xml|
|
264
|
+
add_payment_source(xml, payment_method, options)
|
265
|
+
end
|
266
|
+
commit(order, :refund, options[:retry_logic], options[:trace_number])
|
243
267
|
end
|
244
268
|
|
245
269
|
def void(authorization, options = {}, deprecated = {})
|
@@ -249,7 +273,7 @@ module ActiveMerchant #:nodoc:
|
|
249
273
|
end
|
250
274
|
|
251
275
|
order = build_void_request_xml(authorization, options)
|
252
|
-
commit(order, :void, options[:trace_number])
|
276
|
+
commit(order, :void, options[:retry_logic], options[:trace_number])
|
253
277
|
end
|
254
278
|
|
255
279
|
# ==== Customer Profiles
|
@@ -310,7 +334,10 @@ module ActiveMerchant #:nodoc:
|
|
310
334
|
gsub(%r((<CCAccountNum>).+(</CC)), '\1[FILTERED]\2').
|
311
335
|
gsub(%r((<CardSecVal>).+(</CardSecVal>)), '\1[FILTERED]\2').
|
312
336
|
gsub(%r((<MerchantID>).+(</MerchantID>)), '\1[FILTERED]\2').
|
313
|
-
gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2')
|
337
|
+
gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2').
|
338
|
+
gsub(%r((<CustomerProfileMessage>).+(</CustomerProfileMessage>)), '\1[FILTERED]\2').
|
339
|
+
gsub(%r((<CheckDDA>).+(</CheckDDA>)), '\1[FILTERED]\2').
|
340
|
+
gsub(%r((<BCRtNum>).+(</BCRtNum>)), '\1[FILTERED]\2')
|
314
341
|
end
|
315
342
|
|
316
343
|
private
|
@@ -365,9 +392,9 @@ module ActiveMerchant #:nodoc:
|
|
365
392
|
def add_level3_tax(xml, options = {})
|
366
393
|
if (level3 = options[:level_3_data])
|
367
394
|
xml.tag! :PC3VATtaxAmt, byte_limit(level3[:vat_tax], 12) if level3[:vat_tax]
|
368
|
-
xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax]
|
369
395
|
xml.tag! :PC3VATtaxRate, byte_limit(level3[:vat_rate], 4) if level3[:vat_rate]
|
370
396
|
xml.tag! :PC3AltTaxInd, byte_limit(level3[:alt_ind], 15) if level3[:alt_ind]
|
397
|
+
xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax]
|
371
398
|
end
|
372
399
|
end
|
373
400
|
|
@@ -425,20 +452,22 @@ module ActiveMerchant #:nodoc:
|
|
425
452
|
xml.tag! :CardIndicators, options[:card_indicators] if options[:card_indicators]
|
426
453
|
end
|
427
454
|
|
428
|
-
def add_address(xml,
|
429
|
-
|
455
|
+
def add_address(xml, payment_source, options)
|
456
|
+
address = get_address(options)
|
457
|
+
|
458
|
+
unless address.blank?
|
430
459
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s) || empty?(address[:country])
|
431
460
|
|
432
461
|
if avs_supported
|
433
|
-
xml.tag! :AVSzip,
|
462
|
+
xml.tag! :AVSzip, byte_limit(format_address_field(address[:zip]), 10)
|
434
463
|
xml.tag! :AVSaddress1, byte_limit(format_address_field(address[:address1]), 30)
|
435
464
|
xml.tag! :AVSaddress2, byte_limit(format_address_field(address[:address2]), 30)
|
436
|
-
xml.tag! :AVScity,
|
437
|
-
xml.tag! :AVSstate,
|
465
|
+
xml.tag! :AVScity, byte_limit(format_address_field(address[:city]), 20)
|
466
|
+
xml.tag! :AVSstate, byte_limit(format_address_field(address[:state]), 2)
|
438
467
|
xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil)
|
439
468
|
end
|
440
469
|
|
441
|
-
xml.tag! :AVSname, (
|
470
|
+
xml.tag! :AVSname, billing_name(payment_source, options)
|
442
471
|
xml.tag! :AVScountryCode, (avs_supported ? byte_limit(format_address_field(address[:country]), 2) : '')
|
443
472
|
|
444
473
|
# Needs to come after AVScountryCode
|
@@ -446,6 +475,14 @@ module ActiveMerchant #:nodoc:
|
|
446
475
|
end
|
447
476
|
end
|
448
477
|
|
478
|
+
def billing_name(payment_source, options)
|
479
|
+
if payment_source&.name.present?
|
480
|
+
payment_source.name[0..29]
|
481
|
+
elsif options[:billing_address][:name].present?
|
482
|
+
options[:billing_address][:name][0..29]
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
449
486
|
def add_destination_address(xml, address)
|
450
487
|
if address[:dest_zip]
|
451
488
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:dest_country].to_s)
|
@@ -464,7 +501,9 @@ module ActiveMerchant #:nodoc:
|
|
464
501
|
|
465
502
|
# For Profile requests
|
466
503
|
def add_customer_address(xml, options)
|
467
|
-
|
504
|
+
address = get_address(options)
|
505
|
+
|
506
|
+
unless address.blank?
|
468
507
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s)
|
469
508
|
|
470
509
|
xml.tag! :CustomerAddress1, byte_limit(format_address_field(address[:address1]), 30)
|
@@ -478,6 +517,38 @@ module ActiveMerchant #:nodoc:
|
|
478
517
|
end
|
479
518
|
end
|
480
519
|
|
520
|
+
# Payment can be done through either Credit Card or Electronic Check
|
521
|
+
def add_payment_source(xml, payment_source, options = {})
|
522
|
+
if payment_source.is_a?(Check)
|
523
|
+
add_echeck(xml, payment_source, options)
|
524
|
+
else
|
525
|
+
add_creditcard(xml, payment_source, options[:currency])
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
# Adds Electronic Check attributes
|
530
|
+
def add_echeck(xml, check, options = {})
|
531
|
+
xml.tag! :CardBrand, 'EC'
|
532
|
+
xml.tag! :CurrencyCode, currency_code(options[:currency])
|
533
|
+
xml.tag! :CurrencyExponent, currency_exponents(options[:currency])
|
534
|
+
unless check.nil?
|
535
|
+
|
536
|
+
xml.tag! :BCRtNum, check.routing_number
|
537
|
+
xml.tag! :CheckDDA, check.account_number if check.account_number
|
538
|
+
xml.tag! :BankAccountType, ACCOUNT_TYPE[check.account_type] if ACCOUNT_TYPE[check.account_type]
|
539
|
+
xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method]
|
540
|
+
|
541
|
+
if options[:payment_delivery]
|
542
|
+
xml.tag! :BankPmtDelv, options[:payment_delivery]
|
543
|
+
else
|
544
|
+
xml.tag! :BankPmtDelv, 'B'
|
545
|
+
end
|
546
|
+
|
547
|
+
xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank?
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# Adds Credit Card attributes
|
481
552
|
def add_creditcard(xml, creditcard, currency = nil)
|
482
553
|
unless creditcard.nil?
|
483
554
|
xml.tag! :AccountNum, creditcard.number
|
@@ -532,6 +603,34 @@ module ActiveMerchant #:nodoc:
|
|
532
603
|
xml.tag!(:AAV, three_d_secure[:cavv])
|
533
604
|
end
|
534
605
|
|
606
|
+
def add_mc_program_protocol(xml, creditcard, three_d_secure)
|
607
|
+
return unless three_d_secure && creditcard.brand == 'master'
|
608
|
+
return unless three_d_secure[:version]
|
609
|
+
|
610
|
+
truncated_version = three_d_secure[:version].to_s[0]
|
611
|
+
xml.tag!(:MCProgramProtocol, truncated_version)
|
612
|
+
end
|
613
|
+
|
614
|
+
def add_mc_directory_trans_id(xml, creditcard, three_d_secure)
|
615
|
+
return unless three_d_secure && creditcard.brand == 'master'
|
616
|
+
|
617
|
+
xml.tag!(:MCDirectoryTransID, three_d_secure[:ds_transaction_id]) if three_d_secure[:ds_transaction_id]
|
618
|
+
end
|
619
|
+
|
620
|
+
def add_mc_ucafind(xml, creditcard, three_d_secure)
|
621
|
+
return unless three_d_secure && creditcard.brand == 'master'
|
622
|
+
|
623
|
+
xml.tag! :UCAFInd, '4'
|
624
|
+
end
|
625
|
+
|
626
|
+
def add_mc_scarecurring(xml, creditcard, parameters, three_d_secure)
|
627
|
+
return unless parameters && parameters[:sca_recurring] && creditcard.brand == 'master'
|
628
|
+
|
629
|
+
valid_eci = three_d_secure && three_d_secure[:eci] && three_d_secure[:eci] == '7'
|
630
|
+
|
631
|
+
xml.tag!(:SCARecurringPayment, parameters[:sca_recurring]) if valid_eci
|
632
|
+
end
|
633
|
+
|
535
634
|
def add_dpanind(xml, creditcard)
|
536
635
|
return unless creditcard.is_a?(NetworkTokenizationCreditCard)
|
537
636
|
|
@@ -587,6 +686,42 @@ module ActiveMerchant #:nodoc:
|
|
587
686
|
end
|
588
687
|
end
|
589
688
|
|
689
|
+
def add_ews_details(xml, payment_source, parameters = {})
|
690
|
+
split_name = payment_source.first_name.split if payment_source.first_name
|
691
|
+
xml.tag! :EWSFirstName, split_name[0]
|
692
|
+
xml.tag! :EWSMiddleName, split_name[1..-1].join(' ')
|
693
|
+
xml.tag! :EWSLastName, payment_source.last_name
|
694
|
+
xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty?
|
695
|
+
|
696
|
+
if (address = (parameters[:billing_address] || parameters[:address]))
|
697
|
+
xml.tag! :EWSAddressLine1, byte_limit(format_address_field(address[:address1]), 30)
|
698
|
+
xml.tag! :EWSAddressLine2, byte_limit(format_address_field(address[:address2]), 30)
|
699
|
+
xml.tag! :EWSCity, byte_limit(format_address_field(address[:city]), 20)
|
700
|
+
xml.tag! :EWSState, byte_limit(format_address_field(address[:state]), 2)
|
701
|
+
xml.tag! :EWSZip, byte_limit(format_address_field(address[:zip]), 10)
|
702
|
+
end
|
703
|
+
|
704
|
+
xml.tag! :EWSPhoneType, parameters[:phone_type]
|
705
|
+
xml.tag! :EWSPhoneNumber, parameters[:phone_number]
|
706
|
+
xml.tag! :EWSCheckSerialNumber, payment_source.account_number unless parameters[:auth_method].eql?('I')
|
707
|
+
end
|
708
|
+
|
709
|
+
# Adds ECP conditional attributes depending on other attribute values
|
710
|
+
def add_ecp_details(xml, payment_source, parameters = {})
|
711
|
+
requires!(payment_source.account_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
|
712
|
+
xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code]
|
713
|
+
xml.tag! :ECPCheckSerialNumber, payment_source.account_number if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
|
714
|
+
if parameters[:auth_method]&.eql?('P')
|
715
|
+
xml.tag! :ECPTerminalCity, parameters[:terminal_city] if parameters[:terminal_city]
|
716
|
+
xml.tag! :ECPTerminalState, parameters[:terminal_state] if parameters[:terminal_state]
|
717
|
+
xml.tag! :ECPImageReferenceNumber, parameters[:image_reference_number] if parameters[:image_reference_number]
|
718
|
+
end
|
719
|
+
if parameters[:action_code]&.eql?('W3') || parameters[:action_code]&.eql?('W5') ||
|
720
|
+
parameters[:action_code]&.eql?('W7') || parameters[:action_code]&.eql?('W9')
|
721
|
+
add_ews_details(xml, payment_source, parameters)
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
590
725
|
def add_stored_credentials(xml, parameters)
|
591
726
|
return unless parameters[:mit_stored_credential_ind] == 'Y' || parameters[:stored_credential] && !parameters[:stored_credential].values.all?(&:nil?)
|
592
727
|
|
@@ -623,7 +758,7 @@ module ActiveMerchant #:nodoc:
|
|
623
758
|
|
624
759
|
def parse(body)
|
625
760
|
response = {}
|
626
|
-
xml = REXML::Document.new(body)
|
761
|
+
xml = REXML::Document.new(strip_invalid_xml_chars(body))
|
627
762
|
root = REXML::XPath.first(xml, '//Response') ||
|
628
763
|
REXML::XPath.first(xml, '//ErrorResponse')
|
629
764
|
if root
|
@@ -643,9 +778,9 @@ module ActiveMerchant #:nodoc:
|
|
643
778
|
end
|
644
779
|
end
|
645
780
|
|
646
|
-
def commit(order, message_type, trace_number = nil)
|
781
|
+
def commit(order, message_type, retry_logic = nil, trace_number = nil)
|
647
782
|
headers = POST_HEADERS.merge('Content-length' => order.size.to_s)
|
648
|
-
if @options[:retry_logic] && trace_number
|
783
|
+
if (@options[:retry_logic] || retry_logic) && trace_number
|
649
784
|
headers['Trace-number'] = trace_number.to_s
|
650
785
|
headers['Merchant-Id'] = @options[:merchant_id]
|
651
786
|
end
|
@@ -677,8 +812,10 @@ module ActiveMerchant #:nodoc:
|
|
677
812
|
end
|
678
813
|
|
679
814
|
def success?(response, message_type)
|
680
|
-
if %i[
|
815
|
+
if %i[void].include?(message_type)
|
681
816
|
response[:proc_status] == SUCCESS
|
817
|
+
elsif %i[refund].include?(message_type)
|
818
|
+
response[:proc_status] == SUCCESS && response[:approval_status] == APPROVAL_SUCCESS
|
682
819
|
elsif response[:customer_profile_action]
|
683
820
|
response[:profile_proc_status] == SUCCESS
|
684
821
|
else
|
@@ -695,7 +832,7 @@ module ActiveMerchant #:nodoc:
|
|
695
832
|
@options[:ip_authentication] == true
|
696
833
|
end
|
697
834
|
|
698
|
-
def build_new_order_xml(action, money,
|
835
|
+
def build_new_order_xml(action, money, payment_source, parameters = {})
|
699
836
|
requires!(parameters, :order_id)
|
700
837
|
xml = xml_envelope
|
701
838
|
xml.tag! :Request do
|
@@ -720,9 +857,9 @@ module ActiveMerchant #:nodoc:
|
|
720
857
|
|
721
858
|
three_d_secure = parameters[:three_d_secure]
|
722
859
|
|
723
|
-
add_eci(xml,
|
724
|
-
add_cavv(xml,
|
725
|
-
add_xid(xml,
|
860
|
+
add_eci(xml, payment_source, three_d_secure)
|
861
|
+
add_cavv(xml, payment_source, three_d_secure)
|
862
|
+
add_xid(xml, payment_source, three_d_secure)
|
726
863
|
|
727
864
|
xml.tag! :OrderID, format_order_id(parameters[:order_id])
|
728
865
|
xml.tag! :Amount, amount(money)
|
@@ -731,7 +868,7 @@ module ActiveMerchant #:nodoc:
|
|
731
868
|
add_level2_tax(xml, parameters)
|
732
869
|
add_level2_advice_addendum(xml, parameters)
|
733
870
|
|
734
|
-
add_aav(xml,
|
871
|
+
add_aav(xml, payment_source, three_d_secure)
|
735
872
|
# CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
|
736
873
|
|
737
874
|
if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors)
|
@@ -740,14 +877,16 @@ module ActiveMerchant #:nodoc:
|
|
740
877
|
add_soft_descriptors_from_hash(xml, parameters[:soft_descriptors])
|
741
878
|
end
|
742
879
|
|
743
|
-
add_dpanind(xml,
|
744
|
-
add_aevv(xml,
|
745
|
-
add_digital_token_cryptogram(xml,
|
880
|
+
add_dpanind(xml, payment_source)
|
881
|
+
add_aevv(xml, payment_source, three_d_secure)
|
882
|
+
add_digital_token_cryptogram(xml, payment_source)
|
883
|
+
|
884
|
+
xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && payment_source.is_a?(Check)
|
746
885
|
|
747
886
|
set_recurring_ind(xml, parameters)
|
748
887
|
|
749
888
|
# Append Transaction Reference Number at the end for Refund transactions
|
750
|
-
if action == REFUND
|
889
|
+
if action == REFUND && parameters[:authorization]
|
751
890
|
tx_ref_num, = split_authorization(parameters[:authorization])
|
752
891
|
xml.tag! :TxRefNum, tx_ref_num
|
753
892
|
end
|
@@ -756,9 +895,14 @@ module ActiveMerchant #:nodoc:
|
|
756
895
|
add_level3_purchase(xml, parameters)
|
757
896
|
add_level3_tax(xml, parameters)
|
758
897
|
add_line_items(xml, parameters) if parameters[:line_items]
|
898
|
+
add_ecp_details(xml, payment_source, parameters) if payment_source.is_a?(Check)
|
759
899
|
add_card_indicators(xml, parameters)
|
760
900
|
add_stored_credentials(xml, parameters)
|
761
|
-
add_pymt_brand_program_code(xml,
|
901
|
+
add_pymt_brand_program_code(xml, payment_source, three_d_secure)
|
902
|
+
add_mc_scarecurring(xml, payment_source, parameters, three_d_secure)
|
903
|
+
add_mc_program_protocol(xml, payment_source, three_d_secure)
|
904
|
+
add_mc_directory_trans_id(xml, payment_source, three_d_secure)
|
905
|
+
add_mc_ucafind(xml, payment_source, three_d_secure)
|
762
906
|
end
|
763
907
|
end
|
764
908
|
xml.target!
|
@@ -790,6 +934,7 @@ module ActiveMerchant #:nodoc:
|
|
790
934
|
add_level2_advice_addendum(xml, parameters)
|
791
935
|
add_level3_purchase(xml, parameters)
|
792
936
|
add_level3_tax(xml, parameters)
|
937
|
+
add_line_items(xml, parameters) if parameters[:line_items]
|
793
938
|
end
|
794
939
|
end
|
795
940
|
xml.target!
|
@@ -852,6 +997,16 @@ module ActiveMerchant #:nodoc:
|
|
852
997
|
@options[:merchant_id].length == 6
|
853
998
|
end
|
854
999
|
|
1000
|
+
def get_address(options)
|
1001
|
+
options[:billing_address] || options[:address]
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
# Null characters are possible in some responses (namely, the respMsg field), causing XML parsing errors
|
1005
|
+
# Prevent by substituting these with a valid placeholder string
|
1006
|
+
def strip_invalid_xml_chars(xml)
|
1007
|
+
xml.gsub(/\u0000/, '[null]')
|
1008
|
+
end
|
1009
|
+
|
855
1010
|
# The valid characters include:
|
856
1011
|
#
|
857
1012
|
# 1. all letters and digits
|
@@ -989,7 +1144,7 @@ module ActiveMerchant #:nodoc:
|
|
989
1144
|
'Y' => %w(9 A B C H JA JD M2 M3 M5 N5 N8 N9 X Z),
|
990
1145
|
'N' => %w(D E F G M8),
|
991
1146
|
'X' => %w(4 J R),
|
992
|
-
|
1147
|
+
nil => %w(1 2 3 5 6 7 8 JB JC M1 M4 M6 M7 N3 N4 N6 N7 UK)
|
993
1148
|
}.inject({}) do |map, (type, codes)|
|
994
1149
|
codes.each { |code| map[code] = type }
|
995
1150
|
map
|
@@ -1000,7 +1155,7 @@ module ActiveMerchant #:nodoc:
|
|
1000
1155
|
'Y' => %w(9 B D F H JA JB M2 M4 M5 M6 M7 N3 N5 N7 N8 N9 X),
|
1001
1156
|
'N' => %w(A C E G M8 Z),
|
1002
1157
|
'X' => %w(4 J R),
|
1003
|
-
|
1158
|
+
nil => %w(1 2 3 5 6 7 8 JC JD M1 M3 N4 N6 UK)
|
1004
1159
|
}.inject({}) do |map, (type, codes)|
|
1005
1160
|
codes.each { |code| map[code] = type }
|
1006
1161
|
map
|