killbill 3.2.4 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.travis.yml +26 -5
  4. data/Gemfile +1 -1
  5. data/Gemfile.head +5 -0
  6. data/Gemfile.lock +125 -0
  7. data/Jarfile +9 -9
  8. data/Jarfile.lock +54 -0
  9. data/NEWS +3 -0
  10. data/README.md +13 -0
  11. data/VERSION +1 -1
  12. data/generators/active_merchant/templates/.gitignore.rb +2 -3
  13. data/generators/active_merchant/templates/.travis.yml.rb +22 -3
  14. data/generators/active_merchant/templates/Gemfile.head.rb +5 -0
  15. data/generators/active_merchant/templates/Gemfile.rb +1 -1
  16. data/generators/active_merchant/templates/Jarfile.rb +9 -8
  17. data/generators/active_merchant/templates/LICENSE.rb +2 -2
  18. data/generators/active_merchant/templates/config.yml.rb +16 -6
  19. data/generators/active_merchant/templates/lib/plugin.rb +0 -1
  20. data/generators/active_merchant/templates/plugin.gemspec.rb +17 -15
  21. data/generators/active_merchant/templates/pom.xml.rb +1 -1
  22. data/generators/active_merchant/templates/release.sh.rb +34 -14
  23. data/generators/active_merchant/templates/spec/base_plugin_spec.rb +5 -7
  24. data/generators/active_merchant/templates/spec/integration_spec.rb +7 -18
  25. data/killbill.gemspec +21 -15
  26. data/lib/killbill/ext/active_merchant/typhoeus_connection.rb +3 -4
  27. data/lib/killbill/gen/api/account.rb +1 -1
  28. data/lib/killbill/gen/api/account_data.rb +1 -1
  29. data/lib/killbill/gen/api/audit_log.rb +2 -2
  30. data/lib/killbill/gen/api/audit_user_api.rb +3 -3
  31. data/lib/killbill/gen/api/block.rb +1 -1
  32. data/lib/killbill/gen/api/blocking_state.rb +1 -1
  33. data/lib/killbill/gen/api/call_context.rb +2 -2
  34. data/lib/killbill/gen/api/control_tag.rb +2 -2
  35. data/lib/killbill/gen/api/currency_conversion.rb +1 -1
  36. data/lib/killbill/gen/api/currency_conversion_api.rb +2 -2
  37. data/lib/killbill/gen/api/custom_field.rb +1 -1
  38. data/lib/killbill/gen/api/custom_field_user_api.rb +2 -2
  39. data/lib/killbill/gen/api/dry_run_arguments.rb +22 -3
  40. data/lib/killbill/gen/api/duration.rb +1 -1
  41. data/lib/killbill/gen/api/entitlement.rb +3 -3
  42. data/lib/killbill/gen/api/entitlement_ao_status_dry_run.rb +3 -3
  43. data/lib/killbill/gen/api/entitlement_api.rb +25 -7
  44. data/lib/killbill/gen/api/fixed.rb +1 -1
  45. data/lib/killbill/gen/api/invoice.rb +1 -1
  46. data/lib/killbill/gen/api/invoice_formatter.rb +2 -2
  47. data/lib/killbill/gen/api/invoice_item.rb +2 -2
  48. data/lib/killbill/gen/api/invoice_item_formatter.rb +2 -2
  49. data/lib/killbill/gen/api/invoice_payment.rb +3 -3
  50. data/lib/killbill/gen/api/invoice_user_api.rb +2 -2
  51. data/lib/killbill/gen/api/migration_plan.rb +1 -1
  52. data/lib/killbill/gen/api/mutable_account_data.rb +1 -1
  53. data/lib/killbill/gen/api/payment.rb +1 -1
  54. data/lib/killbill/gen/api/payment_api.rb +11 -11
  55. data/lib/killbill/gen/api/payment_transaction.rb +4 -4
  56. data/lib/killbill/gen/api/plan.rb +1 -1
  57. data/lib/killbill/gen/api/plan_change_result.rb +2 -2
  58. data/lib/killbill/gen/api/plan_phase.rb +1 -1
  59. data/lib/killbill/gen/api/plan_phase_price_override.rb +93 -0
  60. data/lib/killbill/gen/api/plan_phase_price_overrides_with_call_context.rb +77 -0
  61. data/lib/killbill/gen/api/plan_phase_specifier.rb +3 -3
  62. data/lib/killbill/gen/api/plan_specifier.rb +2 -2
  63. data/lib/killbill/gen/api/price.rb +1 -1
  64. data/lib/killbill/gen/api/product.rb +1 -1
  65. data/lib/killbill/gen/api/rate.rb +2 -2
  66. data/lib/killbill/gen/api/record_id_api.rb +1 -1
  67. data/lib/killbill/gen/api/recurring.rb +1 -1
  68. data/lib/killbill/gen/api/refund.rb +2 -2
  69. data/lib/killbill/gen/api/require_gen.rb +2 -0
  70. data/lib/killbill/gen/api/static_catalog.rb +2 -2
  71. data/lib/killbill/gen/api/subscription.rb +3 -3
  72. data/lib/killbill/gen/api/subscription_event.rb +3 -3
  73. data/lib/killbill/gen/api/tag.rb +1 -1
  74. data/lib/killbill/gen/api/tag_definition.rb +1 -1
  75. data/lib/killbill/gen/api/tag_user_api.rb +6 -6
  76. data/lib/killbill/gen/api/tiered_block.rb +1 -1
  77. data/lib/killbill/gen/api/usage.rb +3 -3
  78. data/lib/killbill/gen/plugin-api/currency_plugin_api.rb +1 -1
  79. data/lib/killbill/gen/plugin-api/ext_bus_event.rb +2 -2
  80. data/lib/killbill/gen/plugin-api/payment_transaction_info_plugin.rb +3 -3
  81. data/lib/killbill/helpers/active_merchant.rb +2 -2
  82. data/lib/killbill/helpers/active_merchant/active_record.rb +1 -1
  83. data/lib/killbill/helpers/active_merchant/active_record/active_record_helper.rb +14 -0
  84. data/lib/killbill/helpers/active_merchant/active_record/models/helpers.rb +8 -0
  85. data/lib/killbill/helpers/active_merchant/active_record/models/payment_method.rb +10 -8
  86. data/lib/killbill/helpers/active_merchant/active_record/models/response.rb +16 -3
  87. data/lib/killbill/helpers/active_merchant/active_record/models/streamy_result_set.rb +1 -3
  88. data/lib/killbill/helpers/active_merchant/active_record/models/transaction.rb +2 -0
  89. data/lib/killbill/helpers/active_merchant/configuration.rb +119 -27
  90. data/lib/killbill/helpers/active_merchant/gateway.rb +40 -27
  91. data/lib/killbill/helpers/active_merchant/killbill_spec_helper.rb +63 -45
  92. data/lib/killbill/helpers/active_merchant/payment_plugin.rb +121 -95
  93. data/lib/killbill/helpers/active_merchant/private_payment_plugin.rb +1 -1
  94. data/lib/killbill/helpers/active_merchant/properties.rb +9 -2
  95. data/lib/killbill/helpers/active_merchant/sinatra.rb +4 -8
  96. data/lib/killbill/helpers/active_merchant/utils.rb +44 -0
  97. data/lib/killbill/helpers/properties_helper.rb +41 -0
  98. data/lib/killbill/http_servlet.rb +11 -4
  99. data/lib/killbill/killbill_api.rb +6 -4
  100. data/lib/killbill/rake_task.rb +542 -102
  101. data/spec/killbill/helpers/configuration_spec.rb +117 -33
  102. data/spec/killbill/helpers/payment_method_spec.rb +20 -17
  103. data/spec/killbill/helpers/payment_plugin_spec.rb +401 -201
  104. data/spec/killbill/helpers/private_payment_plugin_spec.rb +3 -16
  105. data/spec/killbill/helpers/response_spec.rb +92 -22
  106. data/spec/killbill/helpers/streamy_result_set_spec.rb +3 -2
  107. data/spec/killbill/helpers/test_payment_method.rb +9 -0
  108. data/spec/killbill/helpers/test_response.rb +11 -0
  109. data/spec/killbill/helpers/test_schema.rb +6 -6
  110. data/spec/killbill/helpers/test_transaction.rb +11 -0
  111. data/spec/killbill/helpers/transaction_spec.rb +3 -13
  112. data/spec/killbill/helpers/utils_spec.rb +127 -69
  113. data/spec/spec_helper.rb +69 -18
  114. metadata +77 -71
  115. data/lib/killbill/ext/active_merchant/jdbc_connection.rb +0 -92
  116. data/lib/killbill/ext/active_merchant/proxy_support.rb +0 -58
  117. data/spec/killbill/helpers/gateway_spec.rb +0 -36
@@ -41,7 +41,7 @@ module Killbill
41
41
 
42
42
  def to_java()
43
43
  # conversion for type [type = org.killbill.billing.catalog.api.BlockType]
44
- @type = Java::org.killbill.billing.catalog.api.BlockType.value_of("#{@type.to_s}") unless @type.nil?
44
+ @type = Java::org.killbill.billing.catalog.api.BlockType.value_of( @type.to_s ) unless @type.nil?
45
45
 
46
46
  # conversion for unit [type = org.killbill.billing.catalog.api.Unit]
47
47
  @unit = @unit.to_java unless @unit.nil?
@@ -44,13 +44,13 @@ module Killbill
44
44
  @name = @name.to_s unless @name.nil?
45
45
 
46
46
  # conversion for billing_mode [type = org.killbill.billing.catalog.api.BillingMode]
47
- @billing_mode = Java::org.killbill.billing.catalog.api.BillingMode.value_of("#{@billing_mode.to_s}") unless @billing_mode.nil?
47
+ @billing_mode = Java::org.killbill.billing.catalog.api.BillingMode.value_of( @billing_mode.to_s ) unless @billing_mode.nil?
48
48
 
49
49
  # conversion for usage_type [type = org.killbill.billing.catalog.api.UsageType]
50
- @usage_type = Java::org.killbill.billing.catalog.api.UsageType.value_of("#{@usage_type.to_s}") unless @usage_type.nil?
50
+ @usage_type = Java::org.killbill.billing.catalog.api.UsageType.value_of( @usage_type.to_s ) unless @usage_type.nil?
51
51
 
52
52
  # conversion for billing_period [type = org.killbill.billing.catalog.api.BillingPeriod]
53
- @billing_period = Java::org.killbill.billing.catalog.api.BillingPeriod.value_of("#{@billing_period.to_s}") unless @billing_period.nil?
53
+ @billing_period = Java::org.killbill.billing.catalog.api.BillingPeriod.value_of( @billing_period.to_s ) unless @billing_period.nil?
54
54
 
55
55
  # conversion for limits [type = org.killbill.billing.catalog.api.Limit[]]
56
56
  tmp = java.util.ArrayList.new
@@ -48,7 +48,7 @@ module Killbill
48
48
  tmp = java.util.TreeSet.new
49
49
  (res || []).each do |m|
50
50
  # conversion for m [type = org.killbill.billing.catalog.api.Currency]
51
- m = Java::org.killbill.billing.catalog.api.Currency.value_of("#{m.to_s}") unless m.nil?
51
+ m = Java::org.killbill.billing.catalog.api.Currency.value_of( m.to_s ) unless m.nil?
52
52
  tmp.add(m)
53
53
  end
54
54
  res = tmp
@@ -41,10 +41,10 @@ module Killbill
41
41
 
42
42
  def to_java()
43
43
  # conversion for event_type [type = org.killbill.billing.notification.plugin.api.ExtBusEventType]
44
- @event_type = Java::org.killbill.billing.notification.plugin.api.ExtBusEventType.value_of("#{@event_type.to_s}") unless @event_type.nil?
44
+ @event_type = Java::org.killbill.billing.notification.plugin.api.ExtBusEventType.value_of( @event_type.to_s ) unless @event_type.nil?
45
45
 
46
46
  # conversion for object_type [type = org.killbill.billing.ObjectType]
47
- @object_type = Java::org.killbill.billing.ObjectType.value_of("#{@object_type.to_s}") unless @object_type.nil?
47
+ @object_type = Java::org.killbill.billing.ObjectType.value_of( @object_type.to_s ) unless @object_type.nil?
48
48
 
49
49
  # conversion for object_id [type = java.util.UUID]
50
50
  @object_id = java.util.UUID.fromString(@object_id.to_s) unless @object_id.nil?
@@ -47,7 +47,7 @@ module Killbill
47
47
  @kb_transaction_payment_id = java.util.UUID.fromString(@kb_transaction_payment_id.to_s) unless @kb_transaction_payment_id.nil?
48
48
 
49
49
  # conversion for transaction_type [type = org.killbill.billing.payment.api.TransactionType]
50
- @transaction_type = Java::org.killbill.billing.payment.api.TransactionType.value_of("#{@transaction_type.to_s}") unless @transaction_type.nil?
50
+ @transaction_type = Java::org.killbill.billing.payment.api.TransactionType.value_of( @transaction_type.to_s ) unless @transaction_type.nil?
51
51
 
52
52
  # conversion for amount [type = java.math.BigDecimal]
53
53
  if @amount.nil?
@@ -57,7 +57,7 @@ module Killbill
57
57
  end
58
58
 
59
59
  # conversion for currency [type = org.killbill.billing.catalog.api.Currency]
60
- @currency = Java::org.killbill.billing.catalog.api.Currency.value_of("#{@currency.to_s}") unless @currency.nil?
60
+ @currency = Java::org.killbill.billing.catalog.api.Currency.value_of( @currency.to_s ) unless @currency.nil?
61
61
 
62
62
  # conversion for created_date [type = org.joda.time.DateTime]
63
63
  if !@created_date.nil?
@@ -72,7 +72,7 @@ module Killbill
72
72
  end
73
73
 
74
74
  # conversion for status [type = org.killbill.billing.payment.plugin.api.PaymentPluginStatus]
75
- @status = Java::org.killbill.billing.payment.plugin.api.PaymentPluginStatus.value_of("#{@status.to_s}") unless @status.nil?
75
+ @status = Java::org.killbill.billing.payment.plugin.api.PaymentPluginStatus.value_of( @status.to_s ) unless @status.nil?
76
76
 
77
77
  # conversion for gateway_error [type = java.lang.String]
78
78
  @gateway_error = @gateway_error.to_s unless @gateway_error.nil?
@@ -3,8 +3,8 @@ module Killbill
3
3
  module ActiveMerchant
4
4
  require 'killbill'
5
5
 
6
- require 'killbill/ext/active_merchant/jdbc_connection'
7
- require 'killbill/ext/active_merchant/proxy_support'
6
+ require File.dirname(__FILE__) + '/properties_helper.rb'
7
+ require File.dirname(__FILE__) + '/active_merchant/active_record/active_record_helper.rb'
8
8
 
9
9
  require 'active_support/core_ext'
10
10
  require File.dirname(__FILE__) + '/active_merchant/core_ext.rb'
@@ -14,4 +14,4 @@ module Killbill
14
14
  end
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Killbill
2
+ module Plugin
3
+ module ActiveMerchant
4
+ module ActiveRecordHelper
5
+
6
+ def close_connection(logger = nil)
7
+ pool = ::ActiveRecord::Base.connection_pool
8
+ logger.debug { "after_request: pool.active_connection? = #{pool.active_connection?}, pool.connections.size = #{pool.connections.size}, connections = #{pool.connections.inspect}" } if logger
9
+ ::ActiveRecord::Base.connection.close if pool.active_connection? # check-in to pool
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -34,6 +34,14 @@ module Killbill
34
34
  }
35
35
  end
36
36
 
37
+ def with_connection(&block)
38
+ self.connection_pool.with_connection(&block)
39
+ end
40
+
41
+ def with_connection_and_transaction(&block)
42
+ with_connection { self.transaction(&block) }
43
+ end
44
+
37
45
  # Useful helper to extract params from AM response objects, e.g. extract(response, 'card', 'address_country')
38
46
  def extract(response, key1, key2=nil, key3=nil)
39
47
  return nil if response.nil? || response.params.nil?
@@ -12,6 +12,8 @@ module Killbill
12
12
  extend ::Killbill::Plugin::ActiveMerchant::Helpers
13
13
 
14
14
  self.abstract_class = true
15
+ # See Response#from_response
16
+ self.record_timestamps = false
15
17
 
16
18
  @@quotes_cache = build_quotes_cache
17
19
 
@@ -23,12 +25,12 @@ module Killbill
23
25
  :kb_payment_method_id => kb_payment_method_id,
24
26
  :kb_tenant_id => kb_tenant_id,
25
27
  :token => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? response.authorization : (cc_or_token || response.authorization),
26
- :cc_first_name => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.first_name : nil,
27
- :cc_last_name => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.last_name : nil,
28
- :cc_type => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.brand : nil,
29
- :cc_exp_month => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.month : nil,
30
- :cc_exp_year => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.year : nil,
31
- :cc_last_4 => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.last_digits : nil,
28
+ :cc_first_name => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.first_name : extra_params[:cc_first_name],
29
+ :cc_last_name => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.last_name : extra_params[:cc_last_name],
30
+ :cc_type => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.brand : extra_params[:cc_type],
31
+ :cc_exp_month => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.month : extra_params[:cc_exp_month],
32
+ :cc_exp_year => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.year : extra_params[:cc_exp_year],
33
+ :cc_last_4 => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.last_digits : extra_params[:cc_last_4],
32
34
  :cc_number => cc_or_token.kind_of?(::ActiveMerchant::Billing::CreditCard) ? cc_or_token.number : nil,
33
35
  :address1 => (options[:billing_address] || {})[:address1],
34
36
  :address2 => (options[:billing_address] || {})[:address2],
@@ -38,7 +40,7 @@ module Killbill
38
40
  :country => (options[:billing_address] || {})[:country],
39
41
  :created_at => current_time,
40
42
  :updated_at => current_time
41
- }.merge!(extra_params))
43
+ }.merge!(extra_params.compact)) # Don't override with nil values
42
44
  end
43
45
 
44
46
  def self.from_kb_account_id(kb_account_id, kb_tenant_id)
@@ -59,7 +61,7 @@ module Killbill
59
61
  else
60
62
  payment_methods = where("kb_payment_method_id = #{@@quotes_cache[kb_payment_method_id]} AND kb_tenant_id = #{@@quotes_cache[kb_tenant_id]} AND is_deleted = #{@@quotes_cache[false]}")
61
63
  end
62
- raise "No payment method found for payment method #{kb_payment_method_id}" if payment_methods.empty?
64
+ raise "No payment method found for payment method #{kb_payment_method_id} and tenant #{kb_tenant_id}" if payment_methods.empty?
63
65
  raise "Kill Bill payment method #{kb_payment_method_id} mapping to multiple active plugin payment methods" if payment_methods.size > 1
64
66
  payment_methods[0]
65
67
  end
@@ -13,11 +13,14 @@ module Killbill
13
13
  extend ::Killbill::Plugin::ActiveMerchant::Helpers
14
14
 
15
15
  self.abstract_class = true
16
+ self.record_timestamps = false
16
17
 
17
18
  @@quotes_cache = build_quotes_cache
18
19
 
19
20
  def self.from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, payment_processor_account_id, kb_tenant_id, response, extra_params = {}, model = Response)
20
21
  # Under high load, Rails sometimes fails to set timestamps. Unclear why...
22
+ # But regardless, for performance reasons, we want to set these timestamps ourselves
23
+ # See ActiveRecord::Timestamp
21
24
  current_time = Time.now.utc
22
25
  model.new({
23
26
  :api_call => api_call,
@@ -40,7 +43,7 @@ module Killbill
40
43
  :success => response.success?,
41
44
  :created_at => current_time,
42
45
  :updated_at => current_time
43
- }.merge!(extra_params))
46
+ }.merge!(extra_params.compact)) # Don't override with nil values
44
47
  end
45
48
 
46
49
  def self.create_response_and_transaction(identifier, transaction_model, api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, payment_processor_account_id, kb_tenant_id, gw_response, amount_in_cents, currency, extra_params = {}, model = Response)
@@ -48,7 +51,7 @@ module Killbill
48
51
 
49
52
  # Rails wraps all create/save calls in a transaction. To speed things up, create a single transaction for both rows.
50
53
  # This has a small gotcha in the unhappy path though (see below).
51
- transaction do
54
+ with_connection_and_transaction do
52
55
  # Save the response to our logs
53
56
  response = from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, payment_processor_account_id, kb_tenant_id, gw_response, extra_params, model)
54
57
  response.save!(shared_activerecord_options)
@@ -87,15 +90,25 @@ module Killbill
87
90
  return response, transaction
88
91
  end
89
92
 
93
+ def self.from_kb_payment_id(transaction_model, kb_payment_id, kb_tenant_id)
94
+ association = transaction_model.table_name.singularize.to_sym
95
+ # Use eager_load to force Rails to issue a single query (see https://github.com/killbill/killbill-plugin-framework-ruby/issues/32)
96
+ eager_load(association)
97
+ .where(:kb_payment_id => kb_payment_id, :kb_tenant_id => kb_tenant_id)
98
+ .order(:created_at)
99
+ end
100
+
90
101
  def to_transaction_info_plugin(transaction=nil)
91
102
  if transaction.nil?
92
103
  amount_in_cents = nil
93
104
  currency = nil
94
105
  created_date = created_at
106
+ status = :UNDEFINED # Likely pending
95
107
  else
96
108
  amount_in_cents = transaction.amount_in_cents
97
109
  currency = transaction.currency
98
110
  created_date = transaction.created_at
111
+ status = success ? :PROCESSED : :ERROR
99
112
  end
100
113
 
101
114
  t_info_plugin = Killbill::Plugin::Model::PaymentTransactionInfoPlugin.new
@@ -106,7 +119,7 @@ module Killbill
106
119
  t_info_plugin.currency = currency
107
120
  t_info_plugin.created_date = created_date
108
121
  t_info_plugin.effective_date = effective_date
109
- t_info_plugin.status = (success ? :PROCESSED : :ERROR)
122
+ t_info_plugin.status = status
110
123
  t_info_plugin.gateway_error = gateway_error
111
124
  t_info_plugin.gateway_error_code = gateway_error_code
112
125
  t_info_plugin.first_payment_reference_id = first_reference_id
@@ -36,9 +36,7 @@ module Killbill
36
36
  pool = ::ActiveRecord::Base.connection_pool
37
37
  return unless pool.active_connection?
38
38
 
39
- connection = ::ActiveRecord::Base.connection
40
- pool.remove(connection)
41
- connection.disconnect!
39
+ ::ActiveRecord::Base.connection.close # check-in to pool
42
40
  end
43
41
  end
44
42
  end
@@ -9,6 +9,8 @@ module Killbill
9
9
  extend ::Killbill::Plugin::ActiveMerchant::Helpers
10
10
 
11
11
  self.abstract_class = true
12
+ # See Response#from_response
13
+ self.record_timestamps = false
12
14
 
13
15
  @@quotes_cache = build_quotes_cache
14
16
 
@@ -1,4 +1,5 @@
1
1
  require 'logger'
2
+ require 'pathname'
2
3
  require 'thread_safe'
3
4
 
4
5
  module Killbill
@@ -12,39 +13,31 @@ module Killbill
12
13
  mattr_reader :kb_apis
13
14
  mattr_reader :gateway_name
14
15
  mattr_reader :gateway_builder
16
+ # To be kept in sync with sinatra.rb
15
17
  mattr_reader :logger
16
18
  mattr_reader :config_key_name
17
19
  mattr_reader :per_tenant_config_cache
18
20
 
19
-
20
21
  class << self
21
22
 
22
23
  def initialize!(gateway_builder, gateway_name, logger, config_key_name, config_file, kb_apis)
23
-
24
24
  @@logger = logger
25
25
  @@kb_apis = kb_apis
26
26
  @@gateway_name = gateway_name
27
27
  @@gateway_builder = gateway_builder
28
28
  @@config_key_name = config_key_name
29
29
  @@per_tenant_config_cache = ThreadSafe::Cache.new
30
+ @@per_tenant_gateways_cache = ThreadSafe::Cache.new
30
31
 
31
- if defined?(JRUBY_VERSION)
32
- begin
33
- # See https://github.com/jruby/activerecord-jdbc-adapter/issues/302
34
- require 'jdbc/mysql'
35
- ::Jdbc::MySQL.load_driver(:require) if ::Jdbc::MySQL.respond_to?(:load_driver)
36
- rescue => e
37
- @@logger.warn "Unable to load the JDBC driver: #{e}"
38
- end
39
- end
40
-
41
- initialize_from_global_config!(gateway_builder, gateway_name, logger, config_file)
32
+ initialize_from_global_config!(config_file)
42
33
  end
43
34
 
44
-
45
35
  def gateways(kb_tenant_id=nil)
46
- tenant_config = get_tenant_config(kb_tenant_id)
47
- extract_gateway_config(tenant_config)
36
+ if @@per_tenant_gateways_cache[kb_tenant_id].nil?
37
+ tenant_config = get_tenant_config(kb_tenant_id)
38
+ @@per_tenant_gateways_cache[kb_tenant_id] = extract_gateway_config(tenant_config)
39
+ end
40
+ @@per_tenant_gateways_cache[kb_tenant_id]
48
41
  end
49
42
 
50
43
  def currency_conversions(kb_tenant_id=nil)
@@ -56,8 +49,9 @@ module Killbill
56
49
  end
57
50
  end
58
51
 
52
+ # To be kept in sync with sinatra.rb
59
53
  def config(kb_tenant_id=nil)
60
- get_tenant_config(kb_tenant_id)
54
+ @@glob_config.merge(get_tenant_config(kb_tenant_id) || {})
61
55
  end
62
56
 
63
57
  def converted_currency(currency, kb_tenant_id=nil)
@@ -69,6 +63,7 @@ module Killbill
69
63
  def invalidate_tenant_config!(kb_tenant_id)
70
64
  @@logger.info("Invalidate plugin key #{@@config_key_name}, tenant = #{kb_tenant_id}")
71
65
  @@per_tenant_config_cache[kb_tenant_id] = nil
66
+ @@per_tenant_gateways_cache[kb_tenant_id] = nil
72
67
  end
73
68
 
74
69
  private
@@ -83,19 +78,18 @@ module Killbill
83
78
  if gateway_account_id.nil?
84
79
  @@logger.warn "Skipping config #{gateway_config} -- missing :account_id"
85
80
  else
86
- gateways_config[gateway_account_id.to_sym] = Gateway.wrap(gateway_builder, logger, gateway_config)
81
+ gateways_config[gateway_account_id.to_sym] = Gateway.wrap(gateway_builder, gateway_config)
87
82
  default_gateway = gateways_config[gateway_account_id.to_sym] if idx == 0
88
83
  end
89
84
  end
90
85
  gateways_config[:default] = default_gateway if gateways_config[:default].nil?
91
86
  else
92
- gateways_config[:default] = Gateway.wrap(@@gateway_builder, logger, gateway_configs)
87
+ gateways_config[:default] = Gateway.wrap(@@gateway_builder, gateway_configs)
93
88
  end
94
89
  gateways_config
95
90
  end
96
91
 
97
92
  def get_tenant_config(kb_tenant_id)
98
-
99
93
  if @@per_tenant_config_cache[kb_tenant_id].nil?
100
94
  # Make the api api to verify if there is a per tenant value
101
95
  context = @@kb_apis.create_context(kb_tenant_id) if kb_tenant_id
@@ -113,30 +107,128 @@ module Killbill
113
107
  @@per_tenant_config_cache[kb_tenant_id]
114
108
  end
115
109
 
116
- def initialize_from_global_config!(gateway_builder, gateway_name, logger, config_file)
110
+ def initialize_from_global_config!(config_file)
117
111
  # Look for global config
118
- @@glob_config = Properties.new(config_file)
119
- @@glob_config.parse!
112
+ if !config_file.blank? && Pathname.new(config_file).file?
113
+ @@glob_config = Properties.new(config_file)
114
+ @@glob_config.parse!
115
+ @@glob_config = @@glob_config.to_hash
116
+ else
117
+ @@glob_config = {}
118
+ end
120
119
 
121
120
  @@logger.log_level = Logger::DEBUG if (@@glob_config[:logger] || {})[:debug]
122
121
 
123
122
  @@glob_currency_conversions = @@glob_config[:currency_conversions]
124
123
 
124
+ initialize_active_record
125
+
126
+ initialize_active_merchant
127
+
128
+ @@initialized = true
129
+ end
130
+
131
+ def initialize_active_record
125
132
  begin
126
133
  require 'active_record'
127
- ::ActiveRecord::Base.establish_connection(@@glob_config[:database])
134
+ require 'arjdbc' if defined?(JRUBY_VERSION)
135
+ db_config = @@glob_config[:database]
136
+
137
+ if db_config.nil?
138
+ # Sane defaults for running as a Kill Bill plugin
139
+ db_config = {
140
+ :adapter => :mysql,
141
+ # See KillbillActivator#KILLBILL_OSGI_JDBC_JNDI_NAME
142
+ :jndi => 'killbill/osgi/jdbc',
143
+ # See https://github.com/kares/activerecord-bogacs
144
+ :pool => false,
145
+ # Since AR-JDBC 1.4, to disable session configuration
146
+ :configure_connection => false
147
+ }
148
+ end
149
+
150
+ if defined?(JRUBY_VERSION) && db_config.is_a?(Hash)
151
+ if db_config[:jndi]
152
+ # Lookup the DataSource object once, for performance reasons
153
+ begin
154
+ db_config[:data_source] = Java::JavaxNaming::InitialContext.new.lookup(db_config[:jndi].to_s)
155
+ db_config.delete(:jndi)
156
+ rescue Java::javax.naming.NamingException => e
157
+ # See https://github.com/killbill/killbill-plugin-framework-ruby/issues/39
158
+ @@logger.warn "Unable to lookup JNDI DataSource (yet?): #{e}" unless defined?(JBUNDLER_CLASSPATH)
159
+ end
160
+ end
161
+
162
+ # we accept a **pool: false** configuration in which case we
163
+ # the built-in pool is replaced with a false one (under JNDI) :
164
+ if db_config[:pool] == false && ( db_config[:jndi] || db_config[:data_source] )
165
+ begin; require 'active_record/bogacs'
166
+ pool_class = ::ActiveRecord::Bogacs::FalsePool
167
+ ::ActiveRecord::ConnectionAdapters::ConnectionHandler.connection_pool_class = pool_class
168
+ rescue LoadError
169
+ db_config.delete(:pool) # do not confuse AR's built-in pool
170
+ @@logger.warn "ActiveRecord-Bogacs missing, will use default (built-in) AR pool."
171
+ end
172
+ end
173
+ end
174
+ ::ActiveRecord::Base.establish_connection(db_config)
128
175
  ::ActiveRecord::Base.logger = @@logger
129
176
  rescue => e
130
177
  @@logger.warn "Unable to establish a database connection: #{e}"
131
178
  end
179
+ end
180
+
181
+ # Configure global properties
182
+ # It would be nice to fix ActiveMerchant to make these configurable on a per instance basis
183
+ def initialize_active_merchant
184
+ require 'active_merchant'
185
+
186
+ ::ActiveMerchant::Billing::Gateway.logger = @@logger
187
+
188
+ am_config = @@glob_config[@@gateway_name.to_sym]
189
+ if am_config.is_a?(Array)
190
+ default_gateway_config = {}
191
+ am_config.each_with_index do |gateway_config, idx|
192
+ gateway_account_id = gateway_config[:account_id]
193
+ if gateway_account_id.nil?
194
+ @@logger.warn "Skipping config #{gateway_config} -- missing :account_id"
195
+ else
196
+ default_gateway_config = gateway_config if idx == 0 || gateway_account_id == :default
197
+ end
198
+ end
199
+ am_config = default_gateway_config
200
+ end
201
+ am_config ||= {
202
+ # Sane defaults
203
+ :test => true
204
+ }
205
+
206
+ if am_config[:test]
207
+ ::ActiveMerchant::Billing::Base.mode = :test
208
+ end
209
+
210
+ if am_config[:log_file]
211
+ ::ActiveMerchant::Billing::Gateway.wiredump_device = File.open(am_config[:log_file], 'w')
212
+ else
213
+ log_method = am_config[:quiet] ? :debug : :info
214
+ ::ActiveMerchant::Billing::Gateway.wiredump_device = ::Killbill::Plugin::ActiveMerchant::Utils::KBWiredumpDevice.new(@@logger, log_method)
215
+ end
216
+ ::ActiveMerchant::Billing::Gateway.wiredump_device.sync = true
217
+
218
+ ::ActiveMerchant::Billing::Gateway.open_timeout = am_config[:open_timeout] unless am_config[:open_timeout].nil?
219
+ ::ActiveMerchant::Billing::Gateway.read_timeout = am_config[:read_timeout] unless am_config[:read_timeout].nil?
220
+ ::ActiveMerchant::Billing::Gateway.retry_safe = am_config[:retry_safe] unless am_config[:retry_safe].nil?
221
+ ::ActiveMerchant::Billing::Gateway.ssl_strict = am_config[:ssl_strict] unless am_config[:ssl_strict].nil?
222
+ ::ActiveMerchant::Billing::Gateway.ssl_version = am_config[:ssl_version] unless am_config[:ssl_version].nil?
223
+ ::ActiveMerchant::Billing::Gateway.max_retries = am_config[:max_retries] unless am_config[:max_retries].nil?
224
+ ::ActiveMerchant::Billing::Gateway.proxy_address = am_config[:proxy_address] unless am_config[:proxy_address].nil?
225
+ ::ActiveMerchant::Billing::Gateway.proxy_port = am_config[:proxy_port] unless am_config[:proxy_port].nil?
132
226
 
133
227
  # Configure the ActiveMerchant HTTP backend
134
- connection_type = (@@glob_config[:active_merchant] || {})[:connection_type]
228
+ connection_type = (@@glob_config[:active_merchant] || am_config)[:connection_type]
135
229
  if connection_type == :typhoeus
136
230
  require 'killbill/ext/active_merchant/typhoeus_connection'
137
231
  end
138
-
139
- @@initialized = true
140
232
  end
141
233
  end
142
234
  end