activemerchant 1.117.0 → 1.123.0

Sign up to get free protection for your applications and to get access to all the features.
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