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
@@ -16,8 +16,8 @@ module ActiveMerchant #:nodoc:
16
16
  self.homepage_url = 'https://www.adyen.com/'
17
17
  self.display_name = 'Adyen'
18
18
 
19
- PAYMENT_API_VERSION = 'v40'
20
- RECURRING_API_VERSION = 'v30'
19
+ PAYMENT_API_VERSION = 'v64'
20
+ RECURRING_API_VERSION = 'v49'
21
21
 
22
22
  STANDARD_ERROR_CODE_MAPPING = {
23
23
  '101' => STANDARD_ERROR_CODE[:incorrect_number],
@@ -59,6 +59,7 @@ module ActiveMerchant #:nodoc:
59
59
  add_3ds_authenticated_data(post, options)
60
60
  add_splits(post, options)
61
61
  add_recurring_contract(post, options)
62
+ add_network_transaction_reference(post, options)
62
63
  commit('authorise', post, options)
63
64
  end
64
65
 
@@ -67,21 +68,34 @@ module ActiveMerchant #:nodoc:
67
68
  add_invoice_for_modification(post, money, options)
68
69
  add_reference(post, authorization, options)
69
70
  add_splits(post, options)
71
+ add_network_transaction_reference(post, options)
70
72
  commit('capture', post, options)
71
73
  end
72
74
 
73
75
  def refund(money, authorization, options = {})
74
76
  post = init_post(options)
75
77
  add_invoice_for_modification(post, money, options)
76
- add_original_reference(post, authorization, options)
78
+ add_reference(post, authorization, options)
77
79
  add_splits(post, options)
80
+ add_network_transaction_reference(post, options)
78
81
  commit('refund', post, options)
79
82
  end
80
83
 
84
+ def credit(money, payment, options = {})
85
+ post = init_post(options)
86
+ add_invoice(post, money, options)
87
+ add_payment(post, payment, options)
88
+ add_shopper_reference(post, options)
89
+ add_network_transaction_reference(post, options)
90
+ commit('refundWithData', post, options)
91
+ end
92
+
81
93
  def void(authorization, options = {})
82
94
  post = init_post(options)
95
+ endpoint = options[:cancel_or_refund] ? 'cancelOrRefund' : 'cancel'
83
96
  add_reference(post, authorization, options)
84
- commit('cancel', post, options)
97
+ add_network_transaction_reference(post, options)
98
+ commit(endpoint, post, options)
85
99
  end
86
100
 
87
101
  def adjust(money, authorization, options = {})
@@ -227,7 +241,7 @@ module ActiveMerchant #:nodoc:
227
241
  end
228
242
 
229
243
  def add_merchant_data(post, options)
230
- post[:additionalData][:subMerchantId] = options[:sub_merchant_id] if options[:sub_merchant_id]
244
+ post[:additionalData][:subMerchantID] = options[:sub_merchant_id] if options[:sub_merchant_id]
231
245
  post[:additionalData][:subMerchantName] = options[:sub_merchant_name] if options[:sub_merchant_name]
232
246
  post[:additionalData][:subMerchantStreet] = options[:sub_merchant_street] if options[:sub_merchant_street]
233
247
  post[:additionalData][:subMerchantCity] = options[:sub_merchant_city] if options[:sub_merchant_city]
@@ -235,8 +249,8 @@ module ActiveMerchant #:nodoc:
235
249
  post[:additionalData][:subMerchantPostalCode] = options[:sub_merchant_postal_code] if options[:sub_merchant_postal_code]
236
250
  post[:additionalData][:subMerchantCountry] = options[:sub_merchant_country] if options[:sub_merchant_country]
237
251
  post[:additionalData][:subMerchantTaxId] = options[:sub_merchant_tax_id] if options[:sub_merchant_tax_id]
238
- post[:additionalData][:subMerchantId] = options[:sub_merchant_id] if options[:sub_merchant_id]
239
252
  post[:additionalData][:subMerchantMCC] = options[:sub_merchant_mcc] if options[:sub_merchant_mcc]
253
+ post[:additionalData] = post[:additionalData].merge(options[:sub_merchant_data]) if options[:sub_merchant_data]
240
254
  end
241
255
 
242
256
  def add_risk_data(post, options)
@@ -374,7 +388,7 @@ module ActiveMerchant #:nodoc:
374
388
  }
375
389
 
376
390
  card.delete_if { |_k, v| v.blank? }
377
- card[:holderName] ||= 'Not Provided' if credit_card.is_a?(NetworkTokenizationCreditCard)
391
+ card[:holderName] ||= 'Not Provided'
378
392
  requires!(card, :expiryMonth, :expiryYear, :holderName, :number)
379
393
  post[:card] = card
380
394
  end
@@ -385,14 +399,14 @@ module ActiveMerchant #:nodoc:
385
399
  options
386
400
  end
387
401
 
388
- def add_reference(post, authorization, options = {})
389
- _, psp_reference, = authorization.split('#')
390
- post[:originalReference] = single_reference(authorization) || psp_reference
402
+ def add_network_transaction_reference(post, options)
403
+ post[:additionalData] = {} unless post[:additionalData]
404
+ post[:additionalData][:networkTxReference] = options[:network_transaction_id] if options[:network_transaction_id]
391
405
  end
392
406
 
393
- def add_original_reference(post, authorization, options = {})
394
- original_psp_reference, = authorization.split('#')
395
- post[:originalReference] = single_reference(authorization) || original_psp_reference
407
+ def add_reference(post, authorization, options = {})
408
+ original_reference = authorization.split('#').reject(&:empty?).first
409
+ post[:originalReference] = original_reference
396
410
  end
397
411
 
398
412
  def add_mpi_data_for_network_tokenization_card(post, payment)
@@ -403,10 +417,6 @@ module ActiveMerchant #:nodoc:
403
417
  post[:mpiData][:eci] = payment.eci || '07'
404
418
  end
405
419
 
406
- def single_reference(authorization)
407
- authorization if !authorization.include?('#')
408
- end
409
-
410
420
  def add_recurring_contract(post, options = {})
411
421
  return unless options[:recurring_contract_type]
412
422
 
@@ -498,6 +508,7 @@ module ActiveMerchant #:nodoc:
498
508
  raw_response = e.response.body
499
509
  response = parse(raw_response)
500
510
  end
511
+
501
512
  success = success_from(action, response, options)
502
513
  Response.new(
503
514
  success,
@@ -506,6 +517,7 @@ module ActiveMerchant #:nodoc:
506
517
  authorization: authorization_from(action, parameters, response),
507
518
  test: test?,
508
519
  error_code: success ? nil : error_code_from(response),
520
+ network_transaction_id: network_transaction_id_from(response),
509
521
  avs_result: AVSResult.new(code: avs_code_from(response)),
510
522
  cvv_result: CVVResult.new(cvv_result_from(response))
511
523
  )
@@ -552,11 +564,10 @@ module ActiveMerchant #:nodoc:
552
564
  response['refusalReason'] = 'Received unexpected 3DS authentication response. Use the execute_threed and/or threed_dynamic options to initiate a proper 3DS flow.'
553
565
  return false
554
566
  end
555
-
556
567
  case action.to_s
557
568
  when 'authorise', 'authorise3d'
558
569
  %w[Authorised Received RedirectShopper].include?(response['resultCode'])
559
- when 'capture', 'refund', 'cancel'
570
+ when 'capture', 'refund', 'cancel', 'cancelOrRefund'
560
571
  response['response'] == "[#{action}-received]"
561
572
  when 'adjustAuthorisation'
562
573
  response['response'] == 'Authorised' || response['response'] == '[adjustAuthorisation-received]'
@@ -564,6 +575,8 @@ module ActiveMerchant #:nodoc:
564
575
  response['result'] == 'Success'
565
576
  when 'disable'
566
577
  response['response'] == '[detail-successfully-disabled]'
578
+ when 'refundWithData'
579
+ response['resultCode'] == 'Received'
567
580
  else
568
581
  false
569
582
  end
@@ -572,7 +585,7 @@ module ActiveMerchant #:nodoc:
572
585
  def message_from(action, response)
573
586
  return authorize_message_from(response) if %w(authorise authorise3d authorise3ds2).include?(action.to_s)
574
587
 
575
- response['response'] || response['message'] || response['result']
588
+ response['response'] || response['message'] || response['result'] || response['resultCode']
576
589
  end
577
590
 
578
591
  def authorize_message_from(response)
@@ -595,7 +608,7 @@ module ActiveMerchant #:nodoc:
595
608
  def init_post(options = {})
596
609
  post = {}
597
610
  add_merchant_account(post, options)
598
- post[:reference] = options[:order_id] if options[:order_id]
611
+ post[:reference] = options[:order_id][0..79] if options[:order_id]
599
612
  post
600
613
  end
601
614
 
@@ -607,6 +620,10 @@ module ActiveMerchant #:nodoc:
607
620
  STANDARD_ERROR_CODE_MAPPING[response['errorCode']]
608
621
  end
609
622
 
623
+ def network_transaction_id_from(response)
624
+ response.dig('additionalData', 'networkTxReference')
625
+ end
626
+
610
627
  def add_browser_info(browser_info, post)
611
628
  return unless browser_info
612
629
 
@@ -567,14 +567,16 @@ module ActiveMerchant
567
567
 
568
568
  xml.customerIP(options[:ip]) unless empty?(options[:ip])
569
569
 
570
- xml.cardholderAuthentication do
571
- three_d_secure = options.fetch(:three_d_secure, {})
572
- xml.authenticationIndicator(
573
- options[:authentication_indicator] || three_d_secure[:eci]
574
- )
575
- xml.cardholderAuthenticationValue(
576
- options[:cardholder_authentication_value] || three_d_secure[:cavv]
577
- )
570
+ if !empty?(options.fetch(:three_d_secure, {})) || options[:authentication_indicator] || options[:cardholder_authentication_value]
571
+ xml.cardholderAuthentication do
572
+ three_d_secure = options.fetch(:three_d_secure, {})
573
+ xml.authenticationIndicator(
574
+ options[:authentication_indicator] || three_d_secure[:eci]
575
+ )
576
+ xml.cardholderAuthenticationValue(
577
+ options[:cardholder_authentication_value] || three_d_secure[:cavv]
578
+ )
579
+ end
578
580
  end
579
581
  end
580
582
 
@@ -708,9 +710,10 @@ module ActiveMerchant
708
710
  return unless options[:stored_credential]
709
711
 
710
712
  xml.processingOptions do
711
- if options[:stored_credential][:initial_transaction]
713
+ if options[:stored_credential][:initial_transaction] && options[:stored_credential][:reason_type] == 'recurring'
714
+ xml.isFirstRecurringPayment 'true'
715
+ elsif options[:stored_credential][:initial_transaction]
712
716
  xml.isFirstSubsequentAuth 'true'
713
- # xml.isFirstRecurringPayment 'true' if options[:stored_credential][:reason_type] == 'recurring'
714
717
  elsif options[:stored_credential][:initiator] == 'cardholder'
715
718
  xml.isStoredCredentials 'true'
716
719
  else
@@ -720,7 +723,7 @@ module ActiveMerchant
720
723
  end
721
724
 
722
725
  def add_subsequent_auth_information(xml, options)
723
- return unless options.dig(:stored_credential, :reason_type) == 'unscheduled'
726
+ return unless options.dig(:stored_credential, :initiator) == 'merchant'
724
727
 
725
728
  xml.subsequentAuthInformation do
726
729
  xml.reason options[:stored_credential_reason_type_override] if options[:stored_credential_reason_type_override]
@@ -934,6 +937,11 @@ module ActiveMerchant
934
937
  empty?(element.content) ? nil : element.content
935
938
  end
936
939
 
940
+ response[:network_trans_id] =
941
+ if element = doc.at_xpath('//networkTransId')
942
+ empty?(element.content) ? nil : element.content
943
+ end
944
+
937
945
  response
938
946
  end
939
947
 
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+
2
3
  module ActiveMerchant #:nodoc:
3
4
  module Billing #:nodoc:
4
5
  # ==== Customer Information Manager (CIM)
@@ -562,6 +563,8 @@ module ActiveMerchant #:nodoc:
562
563
 
563
564
  def build_get_customer_profile_request(xml, options)
564
565
  xml.tag!('customerProfileId', options[:customer_profile_id])
566
+ xml.tag!('unmaskExpirationDate', options[:unmask_expiration_date]) if options[:unmask_expiration_date]
567
+ xml.tag!('includeIssuerInfo', options[:include_issuer_info]) if options[:include_issuer_info]
565
568
  xml.target!
566
569
  end
567
570
 
@@ -573,6 +576,7 @@ module ActiveMerchant #:nodoc:
573
576
  xml.tag!('customerProfileId', options[:customer_profile_id])
574
577
  xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id])
575
578
  xml.tag!('unmaskExpirationDate', options[:unmask_expiration_date]) if options[:unmask_expiration_date]
579
+ xml.tag!('includeIssuerInfo', options[:include_issuer_info]) if options[:include_issuer_info]
576
580
  xml.target!
577
581
  end
578
582
 
@@ -84,6 +84,7 @@ module ActiveMerchant #:nodoc:
84
84
  add_customer_data(post, options)
85
85
  add_rebill(post, options) if options[:rebill]
86
86
  add_duplicate_override(post, options)
87
+ add_stored_credential(post, options)
87
88
  post[:TRANS_TYPE] = 'AUTH'
88
89
  commit('AUTH_ONLY', money, post, options)
89
90
  end
@@ -107,6 +108,7 @@ module ActiveMerchant #:nodoc:
107
108
  add_customer_data(post, options)
108
109
  add_rebill(post, options) if options[:rebill]
109
110
  add_duplicate_override(post, options)
111
+ add_stored_credential(post, options)
110
112
  post[:TRANS_TYPE] = 'SALE'
111
113
  commit('AUTH_CAPTURE', money, post, options)
112
114
  end
@@ -461,6 +463,33 @@ module ActiveMerchant #:nodoc:
461
463
  post[:REB_CYCLES] = options[:rebill_cycles]
462
464
  end
463
465
 
466
+ def add_stored_credential(post, options)
467
+ post[:cof] = initiator(options)
468
+ post[:cofscheduled] = scheduled(options)
469
+ end
470
+
471
+ def initiator(options)
472
+ return unless initiator = options.dig(:stored_credential, :initiator)
473
+
474
+ case initiator
475
+ when 'merchant'
476
+ 'M'
477
+ when 'cardholder'
478
+ 'C'
479
+ end
480
+ end
481
+
482
+ def scheduled(options)
483
+ return unless reason_type = options.dig(:stored_credential, :reason_type)
484
+
485
+ case reason_type
486
+ when 'recurring' || 'installment'
487
+ 'Y'
488
+ when 'unscheduled'
489
+ 'N'
490
+ end
491
+ end
492
+
464
493
  def post_data(action, parameters = {})
465
494
  post = {}
466
495
  post[:version] = '1'
@@ -319,7 +319,9 @@ module ActiveMerchant
319
319
  def add_fraud_info(doc, payment_method, options)
320
320
  doc.send('transaction-fraud-info') do
321
321
  doc.send('shopper-ip-address', options[:ip]) if options[:ip]
322
-
322
+ if fraud_info = options[:transaction_fraud_info]
323
+ doc.send('fraud-session-id', fraud_info[:fraud_session_id]) if fraud_info[:fraud_session_id]
324
+ end
323
325
  unless payment_method.is_a? String
324
326
  doc.send('shipping-contact-info') do
325
327
  add_shipping_contact_info(doc, payment_method, options)
@@ -384,7 +386,7 @@ module ActiveMerchant
384
386
 
385
387
  def parse(response)
386
388
  return bad_authentication_response if response.code.to_i == 401
387
- return forbidden_response(response.body) if response.code.to_i == 403
389
+ return generic_error_response(response.body) if [403, 429].include?(response.code.to_i)
388
390
 
389
391
  parsed = {}
390
392
  doc = Nokogiri::XML(response.body)
@@ -562,7 +564,7 @@ module ActiveMerchant
562
564
  { 'description' => 'Unable to authenticate. Please check your credentials.' }
563
565
  end
564
566
 
565
- def forbidden_response(body)
567
+ def generic_error_response(body)
566
568
  { 'description' => body }
567
569
  end
568
570
  end
@@ -7,7 +7,7 @@ rescue LoadError
7
7
  raise 'Could not load the braintree gem. Use `gem install braintree` to install it.'
8
8
  end
9
9
 
10
- raise "Need braintree gem >= 2.78.0. Run `gem install braintree --version '~>2.78'` to get the correct version." unless Braintree::Version::Major == 2 && Braintree::Version::Minor >= 78
10
+ raise 'Need braintree gem >= 2.0.0.' unless Braintree::Version::Major >= 2 && Braintree::Version::Minor >= 0
11
11
 
12
12
  module ActiveMerchant #:nodoc:
13
13
  module Billing #:nodoc:
@@ -115,10 +115,36 @@ module ActiveMerchant #:nodoc:
115
115
  end
116
116
  end
117
117
 
118
- def verify(credit_card, options = {})
119
- MultiResponse.run(:use_first_response) do |r|
120
- r.process { authorize(100, credit_card, options) }
121
- r.process(:ignore_result) { void(r.authorization, options) }
118
+ def verify(creditcard, options = {})
119
+ if options[:allow_card_verification] == true
120
+ options.delete(:allow_card_verification)
121
+ exp_month = creditcard.month.to_s
122
+ exp_year = creditcard.year.to_s
123
+ expiration = "#{exp_month}/#{exp_year}"
124
+ payload = {
125
+ credit_card: {
126
+ number: creditcard.number,
127
+ expiration_date: expiration,
128
+ cvv: creditcard.verification_value,
129
+ billing_address: {
130
+ postal_code: options[:billing_address][:zip]
131
+ }
132
+ }
133
+ }
134
+ commit do
135
+ result = @braintree_gateway.verification.create(payload)
136
+ response = Response.new(result.success?, message_from_transaction_result(result), response_options(result))
137
+ response.cvv_result['message'] = ''
138
+ response.cvv_result['code'] = response.params['cvv_result'] if response.params['cvv_result']
139
+ response.avs_result['code'] = response.params['avs_result'][:code] if response.params.dig('avs_result', :code)
140
+ response
141
+ end
142
+
143
+ else
144
+ MultiResponse.run(:use_first_response) do |r|
145
+ r.process { authorize(100, creditcard, options) }
146
+ r.process(:ignore_result) { void(r.authorization, options) }
147
+ end
122
148
  end
123
149
  end
124
150
 
@@ -368,7 +394,11 @@ module ActiveMerchant #:nodoc:
368
394
 
369
395
  def response_options(result)
370
396
  options = {}
371
- if result.transaction
397
+ if result.credit_card_verification
398
+ options[:authorization] = result.credit_card_verification.id
399
+ options[:avs_result] = { code: avs_code_from(result.credit_card_verification) }
400
+ options[:cvv_result] = result.credit_card_verification.cvv_response_code
401
+ elsif result.transaction
372
402
  options[:authorization] = result.transaction.id
373
403
  options[:avs_result] = { code: avs_code_from(result.transaction) }
374
404
  options[:cvv_result] = result.transaction.cvv_response_code
@@ -558,7 +588,8 @@ module ActiveMerchant #:nodoc:
558
588
  'merchant_account_id' => transaction.merchant_account_id,
559
589
  'risk_data' => risk_data,
560
590
  'network_transaction_id' => transaction.network_transaction_id || nil,
561
- 'processor_response_code' => response_code_from_result(result)
591
+ 'processor_response_code' => response_code_from_result(result),
592
+ 'recurring' => transaction.recurring
562
593
  }
563
594
  end
564
595
 
@@ -583,6 +614,7 @@ module ActiveMerchant #:nodoc:
583
614
  parameters[:device_data] = options[:device_data] if options[:device_data]
584
615
  parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
585
616
 
617
+ add_account_type(parameters, options) if options[:account_type]
586
618
  add_skip_options(parameters, options)
587
619
  add_merchant_account_id(parameters, options)
588
620
 
@@ -591,6 +623,7 @@ module ActiveMerchant #:nodoc:
591
623
  add_addresses(parameters, options)
592
624
 
593
625
  add_descriptor(parameters, options)
626
+ add_risk_data(parameters, options)
594
627
  add_travel_data(parameters, options) if options[:travel_data]
595
628
  add_lodging_data(parameters, options) if options[:lodging_data]
596
629
  add_channel(parameters, options)
@@ -609,6 +642,11 @@ module ActiveMerchant #:nodoc:
609
642
  parameters
610
643
  end
611
644
 
645
+ def add_account_type(parameters, options)
646
+ parameters[:options][:credit_card] = {}
647
+ parameters[:options][:credit_card][:account_type] = options[:account_type]
648
+ end
649
+
612
650
  def add_skip_options(parameters, options)
613
651
  parameters[:options][:skip_advanced_fraud_checking] = options[:skip_advanced_fraud_checking] if options[:skip_advanced_fraud_checking]
614
652
  parameters[:options][:skip_avs] = options[:skip_avs] if options[:skip_avs]
@@ -646,6 +684,15 @@ module ActiveMerchant #:nodoc:
646
684
  }
647
685
  end
648
686
 
687
+ def add_risk_data(parameters, options)
688
+ return unless options[:risk_data]
689
+
690
+ parameters[:risk_data] = {
691
+ customer_browser: options[:risk_data][:customer_browser],
692
+ customer_ip: options[:risk_data][:customer_ip]
693
+ }
694
+ end
695
+
649
696
  def add_level_2_data(parameters, options)
650
697
  parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
651
698
  parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
@@ -724,6 +771,8 @@ module ActiveMerchant #:nodoc:
724
771
  else
725
772
  parameters[:transaction_source] = stored_credential[:reason_type]
726
773
  end
774
+ elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
775
+ parameters[:transaction_source] = stored_credential[:reason_type]
727
776
  else
728
777
  parameters[:transaction_source] = ''
729
778
  end
@@ -755,7 +804,8 @@ module ActiveMerchant #:nodoc:
755
804
  eci_indicator: credit_card_or_vault_id.eci
756
805
  }
757
806
  elsif credit_card_or_vault_id.source == :android_pay || credit_card_or_vault_id.source == :google_pay
758
- parameters[:android_pay_card] = {
807
+ Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
808
+ parameters[pay_card] = {
759
809
  number: credit_card_or_vault_id.number,
760
810
  cryptogram: credit_card_or_vault_id.payment_cryptogram,
761
811
  expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
@@ -8,7 +8,7 @@ module ActiveMerchant #:nodoc:
8
8
 
9
9
  self.supported_countries = ['US']
10
10
  self.supported_cardtypes = %i[visa master american_express discover diners_club jcb]
11
- self.homepage_url = 'http://www.higherone.com/'
11
+ self.homepage_url = 'https://transactcampus.com'
12
12
  self.display_name = 'Cashnet'
13
13
  self.money_format = :dollars
14
14
  self.max_retries = 0
@@ -76,7 +76,7 @@ module ActiveMerchant #:nodoc:
76
76
 
77
77
  return unparsable_response(raw_response) unless parsed_response
78
78
 
79
- success = (parsed_response[:result] == '0')
79
+ success = success?(parsed_response)
80
80
  Response.new(
81
81
  success,
82
82
  CASHNET_CODES[parsed_response[:result]],
@@ -86,6 +86,10 @@ module ActiveMerchant #:nodoc:
86
86
  )
87
87
  end
88
88
 
89
+ def success?(response)
90
+ response[:result] == '0'
91
+ end
92
+
89
93
  def post_data(action, parameters = {})
90
94
  post = {}
91
95
  post[:command] = action
@@ -191,6 +195,7 @@ module ActiveMerchant #:nodoc:
191
195
  '215' => 'Old PIN does not validate ',
192
196
  '221' => 'Invalid credit card processor type specified in location or payment code',
193
197
  '222' => 'Credit card processor error',
198
+ '230' => 'Host Error (USE VOID OR REVERSAL TO REFUND UNSETTLED TRANSACTIONS)',
194
199
  '280' => 'SmartPay transaction not posted',
195
200
  '301' => 'Original transaction not found for this customer',
196
201
  '302' => 'Amount to refund exceeds original payment amount or is missing',
@@ -37,12 +37,15 @@ module ActiveMerchant #:nodoc:
37
37
  post = {}
38
38
  add_invoice(post, amount, options)
39
39
  add_customer_data(post, options)
40
+ add_metadata(post, options)
40
41
 
41
42
  commit(:capture, post, authorization)
42
43
  end
43
44
 
44
45
  def void(authorization, _options = {})
45
46
  post = {}
47
+ add_metadata(post, options)
48
+
46
49
  commit(:void, post, authorization)
47
50
  end
48
51
 
@@ -50,6 +53,7 @@ module ActiveMerchant #:nodoc:
50
53
  post = {}
51
54
  add_invoice(post, amount, options)
52
55
  add_customer_data(post, options)
56
+ add_metadata(post, options)
53
57
 
54
58
  commit(:refund, post, authorization)
55
59
  end
@@ -79,8 +83,10 @@ module ActiveMerchant #:nodoc:
79
83
  add_invoice(post, amount, options)
80
84
  add_payment_method(post, payment_method, options)
81
85
  add_customer_data(post, options)
86
+ add_stored_credential_options(post, options)
82
87
  add_transaction_data(post, options)
83
88
  add_3ds(post, options)
89
+ add_metadata(post, options)
84
90
  end
85
91
 
86
92
  def add_invoice(post, money, options)
@@ -96,6 +102,11 @@ module ActiveMerchant #:nodoc:
96
102
  post[:metadata][:udf5] = application_id || 'ActiveMerchant'
97
103
  end
98
104
 
105
+ def add_metadata(post, options)
106
+ post[:metadata] = {} unless post[:metadata]
107
+ post[:metadata].merge!(options[:metadata]) if options[:metadata]
108
+ end
109
+
99
110
  def add_payment_method(post, payment_method, options)
100
111
  post[:source] = {}
101
112
  if payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :network_token
@@ -138,6 +149,26 @@ module ActiveMerchant #:nodoc:
138
149
  post[:previous_payment_id] = options[:previous_charge_id] if options[:previous_charge_id]
139
150
  end
140
151
 
152
+ def add_stored_credential_options(post, options = {})
153
+ return unless options[:stored_credential]
154
+
155
+ case options[:stored_credential][:initial_transaction]
156
+ when true
157
+ post[:merchant_initiated] = false
158
+ when false
159
+ post[:'source.stored'] = true
160
+ post[:previous_payment_id] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
161
+ post[:merchant_initiated] = true
162
+ end
163
+
164
+ case options[:stored_credential][:reason_type]
165
+ when 'recurring' || 'installment'
166
+ post[:payment_type] = 'Recurring'
167
+ when 'unscheduled'
168
+ return
169
+ end
170
+ end
171
+
141
172
  def add_3ds(post, options)
142
173
  if options[:three_d_secure] || options[:execute_threed]
143
174
  post[:'3ds'] = {}
@@ -20,8 +20,9 @@ module ActiveMerchant #:nodoc:
20
20
  self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
21
21
 
22
22
  self.supported_countries = %w(AD AT BE BG HR CY CZ DK EE FR DE GI GR GG HU IS IE IM IT JE LV LI LT LU MT MC NO PL PT RO SM SK ES SE CH GB)
23
+
23
24
  self.default_currency = 'EUR'
24
- self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
25
+ self.currencies_without_fractions = %w(BIF CLP DJF GNF ISK JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
25
26
  self.currencies_with_three_decimal_places = %w(BHD IQD JOD KWD LYD OMR TND)
26
27
 
27
28
  self.money_format = :cents
@@ -331,8 +332,10 @@ module ActiveMerchant #:nodoc:
331
332
  three_ds_2_options = options[:three_ds_2]
332
333
  browser_info = three_ds_2_options[:browser_info]
333
334
  post[:'3ds_initiate'] = options[:three_ds_initiate] || '01'
335
+ post[:f23] = options[:f23] if options[:f23]
334
336
  post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
335
337
  options.dig(:stored_credential, :initiator) == 'merchant' ? post[:'3ds_channel'] = '03' : post[:'3ds_channel'] = '02'
338
+ post[:'3ds_reqchallengeind'] = options[:three_ds_reqchallengeind] if options[:three_ds_reqchallengeind]
336
339
  post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
337
340
  post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
338
341
  post[:d5] = browser_info[:user_agent]
@@ -344,14 +347,7 @@ module ActiveMerchant #:nodoc:
344
347
  post[:d6] = browser_info[:language]
345
348
  post[:'3ds_browserjavaenabled'] = browser_info[:java]
346
349
  post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
347
- if (shipping_address = options[:shipping_address])
348
- post[:'3ds_shipaddrstate'] = shipping_address[:state]
349
- post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
350
- post[:'3ds_shipaddrline2'] = shipping_address[:address2]
351
- post[:'3ds_shipaddrline1'] = shipping_address[:address1]
352
- post[:'3ds_shipaddrcountry'] = shipping_address[:country]
353
- post[:'3ds_shipaddrcity'] = shipping_address[:city]
354
- end
350
+ add_complete_shipping_address(post, options[:shipping_address]) if options[:shipping_address]
355
351
  elsif options[:three_d_secure]
356
352
  add_normalized_3d_secure_2_data(post, options)
357
353
  end
@@ -371,6 +367,17 @@ module ActiveMerchant #:nodoc:
371
367
  end
372
368
  end
373
369
 
370
+ def add_complete_shipping_address(post, shipping_address)
371
+ return if shipping_address.values.any?(&:blank?)
372
+
373
+ post[:'3ds_shipaddrstate'] = shipping_address[:state]
374
+ post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
375
+ post[:'3ds_shipaddrline2'] = shipping_address[:address2]
376
+ post[:'3ds_shipaddrline1'] = shipping_address[:address1]
377
+ post[:'3ds_shipaddrcountry'] = shipping_address[:country]
378
+ post[:'3ds_shipaddrcity'] = shipping_address[:city]
379
+ end
380
+
374
381
  def add_normalized_3d_secure_2_data(post, options)
375
382
  three_d_secure_options = options[:three_d_secure]
376
383