activemerchant 1.118.0 → 1.123.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +185 -0
  3. data/README.md +4 -2
  4. data/lib/active_merchant/billing/check.rb +19 -12
  5. data/lib/active_merchant/billing/credit_card.rb +4 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +44 -17
  8. data/lib/active_merchant/billing/gateways/adyen.rb +36 -19
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +52 -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 +15 -9
  17. data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -6
  18. data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/decidir.rb +15 -3
  20. data/lib/active_merchant/billing/gateways/elavon.rb +76 -25
  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/forte.rb +12 -0
  24. data/lib/active_merchant/billing/gateways/global_collect.rb +25 -16
  25. data/lib/active_merchant/billing/gateways/hps.rb +64 -1
  26. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  27. data/lib/active_merchant/billing/gateways/litle.rb +4 -4
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/moka.rb +277 -0
  31. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  32. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  33. data/lib/active_merchant/billing/gateways/netbanx.rb +37 -2
  34. data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
  35. data/lib/active_merchant/billing/gateways/orbital.rb +127 -64
  36. data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
  37. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  38. data/lib/active_merchant/billing/gateways/payeezy.rb +34 -6
  39. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  40. data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
  41. data/lib/active_merchant/billing/gateways/payment_express.rb +10 -5
  42. data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
  43. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  44. data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
  45. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  46. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  47. data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
  48. data/lib/active_merchant/billing/gateways/redsys.rb +44 -25
  49. data/lib/active_merchant/billing/gateways/safe_charge.rb +20 -11
  50. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  51. data/lib/active_merchant/billing/gateways/stripe.rb +8 -8
  52. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +79 -25
  53. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  54. data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
  55. data/lib/active_merchant/billing/gateways/worldpay.rb +64 -19
  56. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  57. data/lib/active_merchant/billing.rb +1 -0
  58. data/lib/active_merchant/version.rb +1 -1
  59. data/lib/certs/cacert.pem +1582 -2431
  60. 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 = {})
@@ -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
 
@@ -563,6 +563,8 @@ module ActiveMerchant #:nodoc:
563
563
 
564
564
  def build_get_customer_profile_request(xml, options)
565
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]
566
568
  xml.target!
567
569
  end
568
570
 
@@ -574,6 +576,7 @@ module ActiveMerchant #:nodoc:
574
576
  xml.tag!('customerProfileId', options[:customer_profile_id])
575
577
  xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id])
576
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]
577
580
  xml.target!
578
581
  end
579
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'
@@ -386,7 +386,7 @@ module ActiveMerchant
386
386
 
387
387
  def parse(response)
388
388
  return bad_authentication_response if response.code.to_i == 401
389
- 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)
390
390
 
391
391
  parsed = {}
392
392
  doc = Nokogiri::XML(response.body)
@@ -564,7 +564,7 @@ module ActiveMerchant
564
564
  { 'description' => 'Unable to authenticate. Please check your credentials.' }
565
565
  end
566
566
 
567
- def forbidden_response(body)
567
+ def generic_error_response(body)
568
568
  { 'description' => body }
569
569
  end
570
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
 
@@ -592,6 +623,7 @@ module ActiveMerchant #:nodoc:
592
623
  add_addresses(parameters, options)
593
624
 
594
625
  add_descriptor(parameters, options)
626
+ add_risk_data(parameters, options)
595
627
  add_travel_data(parameters, options) if options[:travel_data]
596
628
  add_lodging_data(parameters, options) if options[:lodging_data]
597
629
  add_channel(parameters, options)
@@ -652,6 +684,15 @@ module ActiveMerchant #:nodoc:
652
684
  }
653
685
  end
654
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
+
655
696
  def add_level_2_data(parameters, options)
656
697
  parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
657
698
  parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
@@ -730,6 +771,8 @@ module ActiveMerchant #:nodoc:
730
771
  else
731
772
  parameters[:transaction_source] = stored_credential[:reason_type]
732
773
  end
774
+ elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
775
+ parameters[:transaction_source] = stored_credential[:reason_type]
733
776
  else
734
777
  parameters[:transaction_source] = ''
735
778
  end
@@ -761,7 +804,8 @@ module ActiveMerchant #:nodoc:
761
804
  eci_indicator: credit_card_or_vault_id.eci
762
805
  }
763
806
  elsif credit_card_or_vault_id.source == :android_pay || credit_card_or_vault_id.source == :google_pay
764
- parameters[:android_pay_card] = {
807
+ Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
808
+ parameters[pay_card] = {
765
809
  number: credit_card_or_vault_id.number,
766
810
  cryptogram: credit_card_or_vault_id.payment_cryptogram,
767
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',