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
@@ -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