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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +217 -0
  3. data/README.md +5 -3
  4. data/lib/active_merchant/billing/check.rb +19 -12
  5. data/lib/active_merchant/billing/credit_card.rb +6 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +96 -22
  8. data/lib/active_merchant/billing/gateways/adyen.rb +38 -21
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -0
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -3
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -8
  14. data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
  15. data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
  16. data/lib/active_merchant/billing/gateways/credorax.rb +16 -9
  17. data/lib/active_merchant/billing/gateways/cyber_source.rb +67 -9
  18. data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/decidir.rb +29 -3
  20. data/lib/active_merchant/billing/gateways/elavon.rb +110 -26
  21. data/lib/active_merchant/billing/gateways/element.rb +2 -0
  22. data/lib/active_merchant/billing/gateways/eway_rapid.rb +13 -0
  23. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +17 -6
  24. data/lib/active_merchant/billing/gateways/forte.rb +12 -0
  25. data/lib/active_merchant/billing/gateways/global_collect.rb +25 -16
  26. data/lib/active_merchant/billing/gateways/hps.rb +65 -2
  27. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  28. data/lib/active_merchant/billing/gateways/litle.rb +9 -4
  29. data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
  30. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +277 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  34. data/lib/active_merchant/billing/gateways/netbanx.rb +37 -2
  35. data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
  36. data/lib/active_merchant/billing/gateways/orbital.rb +202 -47
  37. data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
  38. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  39. data/lib/active_merchant/billing/gateways/payeezy.rb +57 -11
  40. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  41. data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
  42. data/lib/active_merchant/billing/gateways/payment_express.rb +10 -5
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +26 -1
  44. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
  45. data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
  46. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  47. data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
  48. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  49. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  50. data/lib/active_merchant/billing/gateways/pin.rb +11 -0
  51. data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
  52. data/lib/active_merchant/billing/gateways/redsys.rb +78 -30
  53. data/lib/active_merchant/billing/gateways/safe_charge.rb +19 -8
  54. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  55. data/lib/active_merchant/billing/gateways/stripe.rb +8 -8
  56. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +86 -25
  57. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  58. data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
  59. data/lib/active_merchant/billing/gateways/worldpay.rb +68 -20
  60. data/lib/active_merchant/billing/response.rb +2 -1
  61. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  62. data/lib/active_merchant/billing.rb +1 -0
  63. data/lib/active_merchant/version.rb +1 -1
  64. data/lib/certs/cacert.pem +1582 -2431
  65. metadata +10 -3
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
30
30
  class OrbitalGateway < Gateway
31
31
  include Empty
32
32
 
33
- API_VERSION = '7.7'
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' # Partial approval
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, creditcard, options = {})
195
- order = build_new_order_xml(AUTH_ONLY, money, creditcard, options) do |xml|
196
- add_creditcard(xml, creditcard, options[:currency])
197
- add_address(xml, creditcard, options)
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, creditcard, options)
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, creditcard, options = {})
215
- order = build_new_order_xml(AUTH_AND_CAPTURE, money, creditcard, options) do |xml|
216
- add_creditcard(xml, creditcard, options[:currency])
217
- add_address(xml, creditcard, options)
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, creditcard, options)
235
+ add_customer_data(xml, payment_source, options)
220
236
  add_managed_billing(xml, options)
221
237
  end
222
238
  end
223
- commit(order, :purchase, options[:trace_number])
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
- order = build_new_order_xml(REFUND, money, nil, options.merge(authorization: authorization)) do |xml|
234
- add_refund(xml, options[:currency])
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, authorization, options = {})
241
- ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
242
- refund(money, authorization, options)
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, creditcard, options)
429
- if (address = (options[:billing_address] || options[:address]))
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, byte_limit(format_address_field(address[:zip]), 10)
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, byte_limit(format_address_field(address[:city]), 20)
437
- xml.tag! :AVSstate, byte_limit(format_address_field(address[:state]), 2)
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, (creditcard&.name ? creditcard.name[0..29] : nil)
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
- if (address = (options[:billing_address] || options[:address]))
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[refund void].include?(message_type)
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, creditcard, parameters = {})
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, creditcard, three_d_secure)
724
- add_cavv(xml, creditcard, three_d_secure)
725
- add_xid(xml, creditcard, three_d_secure)
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, creditcard, three_d_secure)
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, creditcard)
744
- add_aevv(xml, creditcard, three_d_secure)
745
- add_digital_token_cryptogram(xml, creditcard)
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, creditcard, three_d_secure)
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
- nil => %w(1 2 3 5 6 7 8 JB JC M1 M4 M6 M7 N3 N4 N6 N7 UK)
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
- nil => %w(1 2 3 5 6 7 8 JC JD M1 M3 N4 N6 UK)
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