activemerchant 1.125.0 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +316 -0
  3. data/lib/active_merchant/billing/check.rb +40 -8
  4. data/lib/active_merchant/billing/credit_card.rb +28 -1
  5. data/lib/active_merchant/billing/credit_card_methods.rb +91 -23
  6. data/lib/active_merchant/billing/gateway.rb +2 -1
  7. data/lib/active_merchant/billing/gateways/adyen.rb +74 -12
  8. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  9. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
  12. data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +53 -22
  15. data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
  16. data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
  17. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
  18. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  19. data/lib/active_merchant/billing/gateways/braintree_blue.rb +151 -32
  20. data/lib/active_merchant/billing/gateways/card_connect.rb +28 -10
  21. data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
  22. data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
  23. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  24. data/lib/active_merchant/billing/gateways/credorax.rb +56 -26
  25. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  26. data/lib/active_merchant/billing/gateways/cyber_source.rb +112 -58
  27. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  28. data/lib/active_merchant/billing/gateways/d_local.rb +93 -5
  29. data/lib/active_merchant/billing/gateways/decidir.rb +32 -5
  30. data/lib/active_merchant/billing/gateways/decidir_plus.rb +185 -14
  31. data/lib/active_merchant/billing/gateways/ebanx.rb +39 -26
  32. data/lib/active_merchant/billing/gateways/element.rb +21 -1
  33. data/lib/active_merchant/billing/gateways/global_collect.rb +98 -37
  34. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  35. data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
  36. data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
  37. data/lib/active_merchant/billing/gateways/litle.rb +118 -6
  38. data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
  39. data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
  40. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
  41. data/lib/active_merchant/billing/gateways/monei.rb +2 -0
  42. data/lib/active_merchant/billing/gateways/moneris.rb +55 -13
  43. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
  44. data/lib/active_merchant/billing/gateways/nmi.rb +12 -7
  45. data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
  46. data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
  47. data/lib/active_merchant/billing/gateways/orbital.rb +378 -335
  48. data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
  49. data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
  50. data/lib/active_merchant/billing/gateways/payflow.rb +62 -0
  51. data/lib/active_merchant/billing/gateways/paymentez.rb +44 -13
  52. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  53. data/lib/active_merchant/billing/gateways/paysafe.rb +37 -29
  54. data/lib/active_merchant/billing/gateways/payu_latam.rb +28 -15
  55. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  56. data/lib/active_merchant/billing/gateways/priority.rb +185 -140
  57. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  58. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  59. data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
  60. data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -4
  61. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  62. data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
  63. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  64. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  65. data/lib/active_merchant/billing/gateways/stripe.rb +25 -3
  66. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +155 -70
  67. data/lib/active_merchant/billing/gateways/tns.rb +2 -5
  68. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  69. data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
  70. data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
  71. data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
  72. data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
  73. data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
  74. data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
  75. data/lib/active_merchant/billing/response.rb +15 -1
  76. data/lib/active_merchant/connection.rb +0 -2
  77. data/lib/active_merchant/country.rb +1 -0
  78. data/lib/active_merchant/errors.rb +4 -1
  79. data/lib/active_merchant/version.rb +1 -1
  80. metadata +28 -3
@@ -1,4 +1,5 @@
1
1
  require 'active_merchant/billing/gateways/braintree/braintree_common'
2
+ require 'active_merchant/billing/gateways/braintree/token_nonce'
2
3
  require 'active_support/core_ext/array/extract_options'
3
4
 
4
5
  begin
@@ -46,6 +47,8 @@ module ActiveMerchant #:nodoc:
46
47
  cannot_refund_if_unsettled: 91506
47
48
  }
48
49
 
50
+ DIRECT_BANK_ERROR = 'Direct bank account transactions are not supported. Bank accounts must be successfully stored before use.'.freeze
51
+
49
52
  def initialize(options = {})
50
53
  requires!(options, :merchant_id, :public_key, :private_key)
51
54
  @merchant_account_id = options[:merchant_account_id]
@@ -72,14 +75,29 @@ module ActiveMerchant #:nodoc:
72
75
  @braintree_gateway = Braintree::Gateway.new(@configuration)
73
76
  end
74
77
 
78
+ def setup_purchase
79
+ commit do
80
+ Response.new(true, 'Client token created', { client_token: @braintree_gateway.client_token.generate })
81
+ end
82
+ end
83
+
75
84
  def authorize(money, credit_card_or_vault_id, options = {})
85
+ return Response.new(false, DIRECT_BANK_ERROR) if credit_card_or_vault_id.is_a? Check
86
+
76
87
  create_transaction(:sale, money, credit_card_or_vault_id, options)
77
88
  end
78
89
 
79
90
  def capture(money, authorization, options = {})
80
- commit do
81
- result = @braintree_gateway.transaction.submit_for_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
82
- response_from_result(result)
91
+ if options[:partial_capture] == true
92
+ commit do
93
+ result = @braintree_gateway.transaction.submit_for_partial_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
94
+ response_from_result(result)
95
+ end
96
+ else
97
+ commit do
98
+ result = @braintree_gateway.transaction.submit_for_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
99
+ response_from_result(result)
100
+ end
83
101
  end
84
102
  end
85
103
 
@@ -148,21 +166,13 @@ module ActiveMerchant #:nodoc:
148
166
  end
149
167
  end
150
168
 
151
- def store(creditcard, options = {})
152
- if options[:customer].present?
153
- MultiResponse.new.tap do |r|
154
- customer_exists_response = nil
155
- r.process { customer_exists_response = check_customer_exists(options[:customer]) }
156
- r.process do
157
- if customer_exists_response.params['exists']
158
- add_credit_card_to_customer(creditcard, options)
159
- else
160
- add_customer_with_credit_card(creditcard, options)
161
- end
162
- end
163
- end
164
- else
165
- add_customer_with_credit_card(creditcard, options)
169
+ def store(payment_method, options = {})
170
+ return Response.new(false, bank_account_errors(payment_method, options)) if payment_method.is_a?(Check) && bank_account_errors(payment_method, options).present?
171
+
172
+ MultiResponse.run do |r|
173
+ r.process { check_customer_exists(options[:customer]) }
174
+ process_by = payment_method.is_a?(Check) ? :store_bank_account : :store_credit_card
175
+ send process_by, payment_method, options, r
166
176
  end
167
177
  end
168
178
 
@@ -227,6 +237,8 @@ module ActiveMerchant #:nodoc:
227
237
  private
228
238
 
229
239
  def check_customer_exists(customer_vault_id)
240
+ return Response.new true, 'Customer not found', { exists: false } if customer_vault_id.blank?
241
+
230
242
  commit do
231
243
  @braintree_gateway.customer.find(customer_vault_id)
232
244
  ActiveMerchant::Billing::Response.new(true, 'Customer found', { exists: true }, authorization: customer_vault_id)
@@ -468,16 +480,28 @@ module ActiveMerchant #:nodoc:
468
480
  end
469
481
  end
470
482
 
483
+ def additional_processor_response_from_result(result)
484
+ result.transaction&.additional_processor_response
485
+ end
486
+
471
487
  def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
472
488
  transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
473
489
  commit do
474
490
  result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
491
+ make_default_payment_method_token(result) if options.dig(:paypal, :paypal_flow_type) == 'checkout_with_vault' && result.success?
475
492
  response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
476
493
  response.cvv_result['message'] = ''
477
494
  response
478
495
  end
479
496
  end
480
497
 
498
+ def make_default_payment_method_token(result)
499
+ @braintree_gateway.customer.update(
500
+ result.transaction.customer_details.id,
501
+ default_payment_method_token: result.transaction.paypal_details.implicitly_vaulted_payment_method_token
502
+ )
503
+ end
504
+
481
505
  def extract_refund_args(args)
482
506
  options = args.extract_options!
483
507
 
@@ -517,7 +541,10 @@ module ActiveMerchant #:nodoc:
517
541
  end
518
542
 
519
543
  def transaction_hash(result)
520
- return { 'processor_response_code' => response_code_from_result(result) } unless result.success?
544
+ unless result.success?
545
+ return { 'processor_response_code' => response_code_from_result(result),
546
+ 'additional_processor_response' => additional_processor_response_from_result(result) }
547
+ end
521
548
 
522
549
  transaction = result.transaction
523
550
  if transaction.vault_customer
@@ -577,19 +604,20 @@ module ActiveMerchant #:nodoc:
577
604
  end
578
605
 
579
606
  {
580
- 'order_id' => transaction.order_id,
581
- 'amount' => transaction.amount.to_s,
582
- 'status' => transaction.status,
583
- 'credit_card_details' => credit_card_details,
584
- 'customer_details' => customer_details,
585
- 'billing_details' => billing_details,
586
- 'shipping_details' => shipping_details,
587
- 'vault_customer' => vault_customer,
588
- 'merchant_account_id' => transaction.merchant_account_id,
589
- 'risk_data' => risk_data,
590
- 'network_transaction_id' => transaction.network_transaction_id || nil,
591
- 'processor_response_code' => response_code_from_result(result),
592
- 'recurring' => transaction.recurring
607
+ 'order_id' => transaction.order_id,
608
+ 'amount' => transaction.amount.to_s,
609
+ 'status' => transaction.status,
610
+ 'credit_card_details' => credit_card_details,
611
+ 'customer_details' => customer_details,
612
+ 'billing_details' => billing_details,
613
+ 'shipping_details' => shipping_details,
614
+ 'vault_customer' => vault_customer,
615
+ 'merchant_account_id' => transaction.merchant_account_id,
616
+ 'risk_data' => risk_data,
617
+ 'network_transaction_id' => transaction.network_transaction_id || nil,
618
+ 'processor_response_code' => response_code_from_result(result),
619
+ 'processor_authorization_code' => transaction.processor_authorization_code,
620
+ 'recurring' => transaction.recurring
593
621
  }
594
622
  end
595
623
 
@@ -617,6 +645,7 @@ module ActiveMerchant #:nodoc:
617
645
  add_account_type(parameters, options) if options[:account_type]
618
646
  add_skip_options(parameters, options)
619
647
  add_merchant_account_id(parameters, options)
648
+ add_profile_id(parameters, options)
620
649
 
621
650
  add_payment_method(parameters, credit_card_or_vault_id, options)
622
651
  add_stored_credential_data(parameters, credit_card_or_vault_id, options)
@@ -624,6 +653,7 @@ module ActiveMerchant #:nodoc:
624
653
 
625
654
  add_descriptor(parameters, options)
626
655
  add_risk_data(parameters, options)
656
+ add_paypal_options(parameters, options)
627
657
  add_travel_data(parameters, options) if options[:travel_data]
628
658
  add_lodging_data(parameters, options) if options[:lodging_data]
629
659
  add_channel(parameters, options)
@@ -659,6 +689,13 @@ module ActiveMerchant #:nodoc:
659
689
  parameters[:merchant_account_id] = merchant_account_id
660
690
  end
661
691
 
692
+ def add_profile_id(parameters, options)
693
+ return unless profile_id = options[:venmo_profile_id]
694
+
695
+ parameters[:options][:venmo] = {}
696
+ parameters[:options][:venmo][:profile_id] = profile_id
697
+ end
698
+
662
699
  def add_transaction_source(parameters, options)
663
700
  parameters[:transaction_source] = options[:transaction_source] if options[:transaction_source]
664
701
  parameters[:transaction_source] = 'recurring' if options[:recurring]
@@ -693,6 +730,15 @@ module ActiveMerchant #:nodoc:
693
730
  }
694
731
  end
695
732
 
733
+ def add_paypal_options(parameters, options)
734
+ return unless options[:paypal_custom_field] || options[:paypal_description]
735
+
736
+ parameters[:options][:paypal] = {
737
+ custom_field: options[:paypal_custom_field],
738
+ description: options[:paypal_description]
739
+ }
740
+ end
741
+
696
742
  def add_level_2_data(parameters, options)
697
743
  parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
698
744
  parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
@@ -827,6 +873,79 @@ module ActiveMerchant #:nodoc:
827
873
  end
828
874
  end
829
875
  end
876
+
877
+ def bank_account_errors(payment_method, options)
878
+ if payment_method.validate.present?
879
+ payment_method.validate
880
+ elsif options[:billing_address].blank?
881
+ 'billing_address is required parameter to store and verify Bank accounts.'
882
+ elsif options[:ach_mandate].blank?
883
+ 'ach_mandate is a required parameter to process bank acccount transactions see (https://developer.paypal.com/braintree/docs/guides/ach/client-side#show-required-authorization-language)'
884
+ end
885
+ end
886
+
887
+ def add_bank_account_to_customer(payment_method, options)
888
+ bank_account_nonce, error_message = TokenNonce.new(@braintree_gateway, options).create_token_nonce_for_payment_method payment_method
889
+ return Response.new(false, error_message) unless bank_account_nonce.present?
890
+
891
+ result = @braintree_gateway.payment_method.create(
892
+ customer_id: options[:customer],
893
+ payment_method_nonce: bank_account_nonce,
894
+ options: {
895
+ us_bank_account_verification_method: 'network_check'
896
+ }
897
+ )
898
+
899
+ verified = result.success? && result.payment_method&.verified
900
+ message = message_from_result(result)
901
+ message = not_verified_reason(result.payment_method) unless verified
902
+
903
+ Response.new(verified, message,
904
+ {
905
+ customer_vault_id: options[:customer],
906
+ bank_account_token: result.payment_method&.token,
907
+ verified: verified
908
+ },
909
+ authorization: result.payment_method&.token)
910
+ end
911
+
912
+ def not_verified_reason(bank_account)
913
+ return unless bank_account.verifications.present?
914
+
915
+ verification = bank_account.verifications.first
916
+ "verification_status: [#{verification.status}], processor_response: [#{verification.processor_response_code}-#{verification.processor_response_text}]"
917
+ end
918
+
919
+ def store_bank_account(payment_method, options, multi_response)
920
+ multi_response.process { create_customer_from_bank_account payment_method, options } unless multi_response.params['exists']
921
+ multi_response.process { add_bank_account_to_customer payment_method, options }
922
+ end
923
+
924
+ def store_credit_card(payment_method, options, multi_response)
925
+ process_by = multi_response.params['exists'] ? :add_credit_card_to_customer : :add_customer_with_credit_card
926
+ multi_response.process { send process_by, payment_method, options }
927
+ end
928
+
929
+ def create_customer_from_bank_account(payment_method, options)
930
+ parameters = {
931
+ id: options[:customer],
932
+ first_name: payment_method.first_name,
933
+ last_name: payment_method.last_name,
934
+ email: scrub_email(options[:email]),
935
+ phone: options[:phone] || options.dig(:billing_address, :phone),
936
+ device_data: options[:device_data]
937
+ }.compact
938
+
939
+ result = @braintree_gateway.customer.create(parameters)
940
+ customer_id = result.customer.id if result.success?
941
+ options[:customer] = customer_id
942
+
943
+ Response.new(
944
+ result.success?,
945
+ message_from_result(result),
946
+ { customer_vault_id: customer_id, 'exists': true }
947
+ )
948
+ end
830
949
  end
831
950
  end
832
951
  end
@@ -1,8 +1,8 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class CardConnectGateway < Gateway
4
- self.test_url = 'https://fts.cardconnect.com:6443/cardconnect/rest/'
5
- self.live_url = 'https://fts.cardconnect.com:8443/cardconnect/rest/'
4
+ self.test_url = 'https://fts-uat.cardconnect.com/cardconnect/rest/'
5
+ self.live_url = 'https://fts.cardconnect.com/cardconnect/rest/'
6
6
 
7
7
  self.supported_countries = ['US']
8
8
  self.default_currency = 'USD'
@@ -61,6 +61,8 @@ module ActiveMerchant #:nodoc:
61
61
  '60' => STANDARD_ERROR_CODE[:pickup_card]
62
62
  }
63
63
 
64
+ SCHEDULED_PAYMENT_TYPES = %w(recurring installment)
65
+
64
66
  def initialize(options = {})
65
67
  requires!(options, :merchant_id, :username, :password)
66
68
  require_valid_domain!(options, :domain)
@@ -87,8 +89,9 @@ module ActiveMerchant #:nodoc:
87
89
  add_currency(post, money, options)
88
90
  add_address(post, options)
89
91
  add_customer_data(post, options)
90
- add_3DS(post, options)
92
+ add_three_ds_mpi_data(post, options)
91
93
  add_additional_data(post, options)
94
+ add_stored_credential(post, options)
92
95
  post[:capture] = 'Y'
93
96
  commit('auth', post)
94
97
  end
@@ -102,8 +105,9 @@ module ActiveMerchant #:nodoc:
102
105
  add_payment(post, payment)
103
106
  add_address(post, options)
104
107
  add_customer_data(post, options)
105
- add_3DS(post, options)
108
+ add_three_ds_mpi_data(post, options)
106
109
  add_additional_data(post, options)
110
+ add_stored_credential(post, options)
107
111
  commit('auth', post)
108
112
  end
109
113
 
@@ -169,7 +173,7 @@ module ActiveMerchant #:nodoc:
169
173
  def add_address(post, options)
170
174
  if address = options[:billing_address] || options[:address]
171
175
  post[:address] = address[:address1] if address[:address1]
172
- post[:address].concat(" #{address[:address2]}") if address[:address2]
176
+ post[:address2] = address[:address2] if address[:address2]
173
177
  post[:city] = address[:city] if address[:city]
174
178
  post[:region] = address[:state] if address[:state]
175
179
  post[:country] = address[:country] if address[:country]
@@ -188,7 +192,11 @@ module ActiveMerchant #:nodoc:
188
192
 
189
193
  def add_invoice(post, options)
190
194
  post[:orderid] = options[:order_id]
191
- post[:ecomind] = (options[:recurring] ? 'R' : 'E')
195
+ post[:ecomind] = if options[:ecomind]
196
+ options[:ecomind].capitalize
197
+ else
198
+ (options[:recurring] ? 'R' : 'E')
199
+ end
192
200
  end
193
201
 
194
202
  def add_payment(post, payment)
@@ -241,10 +249,20 @@ module ActiveMerchant #:nodoc:
241
249
  post[:userfields] = options[:user_fields] if options[:user_fields]
242
250
  end
243
251
 
244
- def add_3DS(post, options)
245
- post[:secureflag] = options[:secure_flag] if options[:secure_flag]
246
- post[:securevalue] = options[:secure_value] if options[:secure_value]
247
- post[:securexid] = options[:secure_xid] if options[:secure_xid]
252
+ def add_three_ds_mpi_data(post, options)
253
+ return unless three_d_secure = options[:three_d_secure]
254
+
255
+ post[:secureflag] = three_d_secure[:eci]
256
+ post[:securevalue] = three_d_secure[:cavv]
257
+ post[:securedstid] = three_d_secure[:ds_transaction_id]
258
+ end
259
+
260
+ def add_stored_credential(post, options)
261
+ return unless stored_credential = options[:stored_credential]
262
+
263
+ post[:cof] = stored_credential[:initiator] == 'merchant' ? 'M' : 'C'
264
+ post[:cofscheduled] = SCHEDULED_PAYMENT_TYPES.include?(stored_credential[:reason_type]) ? 'Y' : 'N'
265
+ post[:cofpermission] = stored_credential[:initial_transaction] ? 'Y' : 'N'
248
266
  end
249
267
 
250
268
  def headers
@@ -222,6 +222,7 @@ module ActiveMerchant #:nodoc:
222
222
  add_customer_data(post, options)
223
223
  add_remote_address(post, options)
224
224
  add_country_code(post, options)
225
+ add_threeds_fields(post, options)
225
226
  end
226
227
 
227
228
  def add_amount(post, money, options)
@@ -283,6 +284,20 @@ module ActiveMerchant #:nodoc:
283
284
  add_pair(post, :threeDSRequired, options[:threeds_required] || @threeds_required ? 'Y' : 'N')
284
285
  end
285
286
 
287
+ def add_threeds_fields(post, options)
288
+ return unless three_d_secure = options[:three_d_secure]
289
+
290
+ add_pair(post, :threeDSEnrolled, formatted_enrollment(three_d_secure[:enrolled]))
291
+ if three_d_secure[:enrolled] == 'true'
292
+ add_pair(post, :threeDSAuthenticated, three_d_secure[:authentication_response_status])
293
+ if three_d_secure[:authentication_response_status] == 'Y'
294
+ post[:threeDSECI] = three_d_secure[:eci]
295
+ post[:threeDSCAVV] = three_d_secure[:cavv]
296
+ post[:threeDSXID] = three_d_secure[:xid] || three_d_secure[:ds_transaction_id]
297
+ end
298
+ end
299
+ end
300
+
286
301
  def add_remote_address(post, options = {})
287
302
  add_pair(post, :remoteAddress, options[:ip] || '1.1.1.1')
288
303
  end
@@ -366,6 +381,14 @@ module ActiveMerchant #:nodoc:
366
381
  def add_pair(post, key, value, options = {})
367
382
  post[key] = value if !value.blank? || options[:required]
368
383
  end
384
+
385
+ def formatted_enrollment(val)
386
+ case val
387
+ when 'Y', 'N', 'U' then val
388
+ when true, 'true' then 'Y'
389
+ when false, 'false' then 'N'
390
+ end
391
+ end
369
392
  end
370
393
  end
371
394
  end