killbill 3.2.2 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -2
- data/Jarfile +7 -7
- data/README.md +16 -4
- data/VERSION +1 -1
- data/gen_config/api.conf +48 -47
- data/gen_config/plugin_api.conf +17 -16
- data/generators/active_merchant/templates/.gitignore.rb +2 -2
- data/generators/active_merchant/templates/lib/api.rb +8 -0
- data/generators/active_merchant/templates/plugin.gemspec.rb +1 -0
- data/generators/active_merchant/templates/spec/base_plugin_spec.rb +1 -0
- data/generators/active_merchant/templates/spec/integration_spec.rb +5 -1
- data/killbill.gemspec +1 -0
- data/lib/killbill/creator.rb +9 -0
- data/lib/killbill/currency.rb +6 -0
- data/lib/killbill/gen/api/account_audit_logs_for_object_type.rb +9 -7
- data/lib/killbill/gen/api/catalog_user_api.rb +37 -4
- data/lib/killbill/gen/api/payment_api.rb +104 -0
- data/lib/killbill/gen/api/payment_gateway_api.rb +6 -3
- data/lib/killbill/gen/api/plan_phase.rb +1 -8
- data/lib/killbill/gen/api/price_list_set.rb +9 -7
- data/lib/killbill/gen/api/subscription.rb +20 -1
- data/lib/killbill/gen/api/tenant_user_api.rb +3 -3
- data/lib/killbill/gen/plugin-api/currency_plugin_with_events_api.rb +207 -0
- data/lib/killbill/gen/plugin-api/ext_bus_event.rb +7 -1
- data/lib/killbill/gen/plugin-api/invoice_plugin_with_events_api.rb +103 -0
- data/lib/killbill/gen/plugin-api/payment_plugin_with_events_api.rb +782 -0
- data/lib/killbill/gen/plugin-api/require_gen.rb +3 -0
- data/lib/killbill/helpers/active_merchant/configuration.rb +116 -46
- data/lib/killbill/helpers/active_merchant/killbill_spec_helper.rb +49 -32
- data/lib/killbill/helpers/active_merchant/payment_plugin.rb +18 -6
- data/lib/killbill/helpers/active_merchant/private_payment_plugin.rb +3 -3
- data/lib/killbill/helpers/active_merchant/utils.rb +37 -70
- data/lib/killbill/invoice.rb +6 -0
- data/lib/killbill/payment.rb +6 -0
- data/lib/killbill/plugin.rb +1 -1
- data/lib/killbill/rake_task.rb +1 -1
- data/spec/killbill/helpers/configuration_spec.rb +41 -5
- data/spec/killbill/helpers/payment_plugin_spec.rb +4 -1
- data/spec/killbill/helpers/private_payment_plugin_spec.rb +4 -2
- data/spec/killbill/helpers/utils_spec.rb +6 -6
- data/spec/killbill/invoice_plugin_api_spec.rb +1 -1
- data/spec/killbill/notification_plugin_api_spec.rb +1 -1
- data/spec/killbill/payment_plugin_api_spec.rb +1 -1
- metadata +19 -3
- data/lib/killbill/jnotification.rb +0 -31
@@ -28,10 +28,13 @@
|
|
28
28
|
require 'killbill/gen/plugin-api/payment_method_info_plugin'
|
29
29
|
require 'killbill/gen/plugin-api/payment_plugin_api'
|
30
30
|
require 'killbill/gen/plugin-api/payment_plugin_api_exception'
|
31
|
+
require 'killbill/gen/plugin-api/payment_plugin_with_events_api'
|
31
32
|
require 'killbill/gen/plugin-api/ext_bus_event'
|
32
33
|
require 'killbill/gen/plugin-api/notification_plugin_api'
|
33
34
|
require 'killbill/gen/plugin-api/invoice_plugin_api'
|
35
|
+
require 'killbill/gen/plugin-api/invoice_plugin_with_events_api'
|
34
36
|
require 'killbill/gen/plugin-api/currency_plugin_api'
|
37
|
+
require 'killbill/gen/plugin-api/currency_plugin_with_events_api'
|
35
38
|
require 'killbill/gen/plugin-api/gateway_notification'
|
36
39
|
require 'killbill/gen/plugin-api/hosted_payment_page_form_descriptor'
|
37
40
|
require 'killbill/gen/plugin-api/payment_transaction_info_plugin'
|
@@ -1,73 +1,143 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'thread_safe'
|
2
3
|
|
3
4
|
module Killbill
|
4
5
|
module Plugin
|
5
6
|
module ActiveMerchant
|
6
|
-
|
7
|
-
mattr_reader :
|
8
|
-
mattr_reader :
|
7
|
+
|
8
|
+
mattr_reader :glob_config
|
9
|
+
mattr_reader :glob_currency_conversions
|
10
|
+
|
9
11
|
mattr_reader :initialized
|
10
12
|
mattr_reader :kb_apis
|
13
|
+
mattr_reader :gateway_name
|
14
|
+
mattr_reader :gateway_builder
|
11
15
|
mattr_reader :logger
|
16
|
+
mattr_reader :config_key_name
|
17
|
+
mattr_reader :per_tenant_config_cache
|
12
18
|
|
13
|
-
def self.initialize!(gateway_builder, gateway_name, logger, config_file, kb_apis)
|
14
|
-
@@config = Properties.new(config_file)
|
15
|
-
@@config.parse!
|
16
19
|
|
17
|
-
|
18
|
-
@@logger.log_level = Logger::DEBUG if (@@config[:logger] || {})[:debug]
|
20
|
+
class << self
|
19
21
|
|
20
|
-
|
21
|
-
@@kb_apis = kb_apis
|
22
|
+
def initialize!(gateway_builder, gateway_name, logger, config_key_name, config_file, kb_apis)
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
@@logger = logger
|
25
|
+
@@kb_apis = kb_apis
|
26
|
+
@@gateway_name = gateway_name
|
27
|
+
@@gateway_builder = gateway_builder
|
28
|
+
@@config_key_name = config_key_name
|
29
|
+
@@per_tenant_config_cache = ThreadSafe::Cache.new
|
30
|
+
|
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}"
|
34
38
|
end
|
35
39
|
end
|
36
|
-
|
37
|
-
|
38
|
-
@@gateways[:default] = Gateway.wrap(gateway_builder, logger, gateway_configs)
|
40
|
+
|
41
|
+
initialize_from_global_config!(gateway_builder, gateway_name, logger, config_file)
|
39
42
|
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
|
45
|
+
def gateways(kb_tenant_id=nil)
|
46
|
+
tenant_config = get_tenant_config(kb_tenant_id)
|
47
|
+
extract_gateway_config(tenant_config)
|
48
|
+
end
|
49
|
+
|
50
|
+
def currency_conversions(kb_tenant_id=nil)
|
51
|
+
tenant_config = get_tenant_config(kb_tenant_id)
|
52
|
+
if tenant_config
|
53
|
+
tenant_config[:currency_conversions]
|
54
|
+
else
|
55
|
+
@@glob_currency_conversions
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
51
|
-
|
52
|
-
|
53
|
-
::ActiveRecord::Base.establish_connection(@@config[:database])
|
54
|
-
::ActiveRecord::Base.logger = @@logger
|
55
|
-
rescue => e
|
56
|
-
@@logger.warn "Unable to establish a database connection: #{e}"
|
59
|
+
def config(kb_tenant_id=nil)
|
60
|
+
get_tenant_config(kb_tenant_id)
|
57
61
|
end
|
58
62
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
+
def converted_currency(currency, kb_tenant_id=nil)
|
64
|
+
currency_sym = currency.to_s.upcase.to_sym
|
65
|
+
tmp = currency_conversions(kb_tenant_id)
|
66
|
+
tmp && tmp[currency_sym]
|
63
67
|
end
|
64
68
|
|
65
|
-
|
66
|
-
|
69
|
+
def invalidate_tenant_config!(kb_tenant_id)
|
70
|
+
@@logger.info("Invalidate plugin key #{@@config_key_name}, tenant = #{kb_tenant_id}")
|
71
|
+
@@per_tenant_config_cache[kb_tenant_id] = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def extract_gateway_config(config)
|
77
|
+
gateways_config = {}
|
78
|
+
gateway_configs = config[@@gateway_name.to_sym]
|
79
|
+
if gateway_configs.is_a?(Array)
|
80
|
+
default_gateway = nil
|
81
|
+
gateway_configs.each_with_index do |gateway_config, idx|
|
82
|
+
gateway_account_id = gateway_config[:account_id]
|
83
|
+
if gateway_account_id.nil?
|
84
|
+
@@logger.warn "Skipping config #{gateway_config} -- missing :account_id"
|
85
|
+
else
|
86
|
+
gateways_config[gateway_account_id.to_sym] = Gateway.wrap(gateway_builder, logger, gateway_config)
|
87
|
+
default_gateway = gateways_config[gateway_account_id.to_sym] if idx == 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
gateways_config[:default] = default_gateway if gateways_config[:default].nil?
|
91
|
+
else
|
92
|
+
gateways_config[:default] = Gateway.wrap(@@gateway_builder, logger, gateway_configs)
|
93
|
+
end
|
94
|
+
gateways_config
|
95
|
+
end
|
67
96
|
|
68
|
-
|
69
|
-
|
70
|
-
|
97
|
+
def get_tenant_config(kb_tenant_id)
|
98
|
+
|
99
|
+
if @@per_tenant_config_cache[kb_tenant_id].nil?
|
100
|
+
# Make the api api to verify if there is a per tenant value
|
101
|
+
context = @@kb_apis.create_context(kb_tenant_id) if kb_tenant_id
|
102
|
+
values = @@kb_apis.tenant_user_api.get_tenant_values_for_key(@@config_key_name, context) if context
|
103
|
+
# If we have a per tenant value, insert it into the cache
|
104
|
+
if values && values[0]
|
105
|
+
parsed_config = YAML.load(values[0])
|
106
|
+
@@per_tenant_config_cache[kb_tenant_id] = parsed_config
|
107
|
+
# Otherwise, add global config so we don't have to make the tenant call on each operation
|
108
|
+
else
|
109
|
+
@@per_tenant_config_cache[kb_tenant_id] = @@glob_config
|
110
|
+
end
|
111
|
+
end
|
112
|
+
# Return value from cache in any case
|
113
|
+
@@per_tenant_config_cache[kb_tenant_id]
|
114
|
+
end
|
115
|
+
|
116
|
+
def initialize_from_global_config!(gateway_builder, gateway_name, logger, config_file)
|
117
|
+
# Look for global config
|
118
|
+
@@glob_config = Properties.new(config_file)
|
119
|
+
@@glob_config.parse!
|
120
|
+
|
121
|
+
@@logger.log_level = Logger::DEBUG if (@@glob_config[:logger] || {})[:debug]
|
122
|
+
|
123
|
+
@@glob_currency_conversions = @@glob_config[:currency_conversions]
|
124
|
+
|
125
|
+
begin
|
126
|
+
require 'active_record'
|
127
|
+
::ActiveRecord::Base.establish_connection(@@glob_config[:database])
|
128
|
+
::ActiveRecord::Base.logger = @@logger
|
129
|
+
rescue => e
|
130
|
+
@@logger.warn "Unable to establish a database connection: #{e}"
|
131
|
+
end
|
132
|
+
|
133
|
+
# Configure the ActiveMerchant HTTP backend
|
134
|
+
connection_type = (@@glob_config[:active_merchant] || {})[:connection_type]
|
135
|
+
if connection_type == :typhoeus
|
136
|
+
require 'killbill/ext/active_merchant/typhoeus_connection'
|
137
|
+
end
|
138
|
+
|
139
|
+
@@initialized = true
|
140
|
+
end
|
71
141
|
end
|
72
142
|
end
|
73
143
|
end
|
@@ -13,18 +13,18 @@ module Killbill
|
|
13
13
|
create_kb_account kb_account_id
|
14
14
|
end
|
15
15
|
|
16
|
-
context
|
17
|
-
account
|
16
|
+
context = @plugin.kb_apis.create_context(kb_tenant_id)
|
17
|
+
account = @plugin.kb_apis.account_user_api.get_account_by_id(kb_account_id, context)
|
18
18
|
|
19
19
|
# The rest is pure Ruby
|
20
|
-
context
|
20
|
+
context = context.to_ruby(context)
|
21
21
|
|
22
22
|
# Generate a token
|
23
23
|
pm_properties = build_pm_properties(account, options)
|
24
24
|
|
25
|
-
info
|
25
|
+
info = Killbill::Plugin::Model::PaymentMethodPlugin.new
|
26
26
|
info.properties = pm_properties
|
27
|
-
payment_method
|
27
|
+
payment_method = @plugin.add_payment_method(kb_account_id, kb_payment_method_id, info, true, properties, context)
|
28
28
|
|
29
29
|
pm = payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id)
|
30
30
|
pm.should == payment_method
|
@@ -35,19 +35,19 @@ module Killbill
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def build_pm_properties(account = nil, overrides = {})
|
38
|
-
cc_number
|
39
|
-
cc_first_name
|
40
|
-
cc_last_name
|
41
|
-
cc_type
|
42
|
-
cc_exp_month
|
43
|
-
cc_exp_year
|
44
|
-
cc_last_4
|
45
|
-
address1
|
46
|
-
address2
|
47
|
-
city
|
48
|
-
state
|
49
|
-
zip
|
50
|
-
country
|
38
|
+
cc_number = (overrides.delete(:cc_number) || '4242424242424242')
|
39
|
+
cc_first_name = (overrides.delete(:cc_first_name) || 'John')
|
40
|
+
cc_last_name = (overrides.delete(:cc_last_name) || 'Doe')
|
41
|
+
cc_type = (overrides.delete(:cc_type) || 'Visa')
|
42
|
+
cc_exp_month = (overrides.delete(:cc_exp_month) || 12)
|
43
|
+
cc_exp_year = (overrides.delete(:cc_exp_year) || 2017)
|
44
|
+
cc_last_4 = (overrides.delete(:cc_last_4) || 4242)
|
45
|
+
address1 = (overrides.delete(:address1) || '5, oakriu road')
|
46
|
+
address2 = (overrides.delete(:address2) || 'apt. 298')
|
47
|
+
city = (overrides.delete(:city) || 'Gdio Foia')
|
48
|
+
state = (overrides.delete(:state) || 'FL')
|
49
|
+
zip = (overrides.delete(:zip) || 49302)
|
50
|
+
country = (overrides.delete(:country) || 'US')
|
51
51
|
cc_verification_value = (overrides.delete(:cc_verification_value) || 1234)
|
52
52
|
|
53
53
|
properties = []
|
@@ -76,14 +76,14 @@ module Killbill
|
|
76
76
|
|
77
77
|
def create_kb_account(kb_account_id)
|
78
78
|
external_key = Time.now.to_i.to_s + '-test'
|
79
|
-
email
|
79
|
+
email = external_key + '@tester.com'
|
80
80
|
|
81
|
-
account
|
82
|
-
account.id
|
81
|
+
account = ::Killbill::Plugin::Model::Account.new
|
82
|
+
account.id = kb_account_id
|
83
83
|
account.external_key = external_key
|
84
|
-
account.email
|
85
|
-
account.name
|
86
|
-
account.currency
|
84
|
+
account.email = email
|
85
|
+
account.name = 'Integration spec'
|
86
|
+
account.currency = :USD
|
87
87
|
|
88
88
|
@account_api.accounts << account
|
89
89
|
|
@@ -91,8 +91,8 @@ module Killbill
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def create_pm_kv_info(key, value)
|
94
|
-
prop
|
95
|
-
prop.key
|
94
|
+
prop = ::Killbill::Plugin::Model::PluginProperty.new
|
95
|
+
prop.key = key
|
96
96
|
prop.value = value
|
97
97
|
prop
|
98
98
|
end
|
@@ -124,17 +124,17 @@ module Killbill
|
|
124
124
|
def add_payment(kb_payment_id=SecureRandom.uuid, kb_payment_transaction_id=SecureRandom.uuid, kb_payment_transaction_external_key=SecureRandom.uuid, transaction_type=:PURCHASE)
|
125
125
|
kb_payment = get_payment kb_payment_id
|
126
126
|
if kb_payment.nil?
|
127
|
-
kb_payment
|
128
|
-
kb_payment.id
|
127
|
+
kb_payment = ::Killbill::Plugin::Model::Payment.new
|
128
|
+
kb_payment.id = kb_payment_id
|
129
129
|
kb_payment.transactions = []
|
130
130
|
@payments << kb_payment
|
131
131
|
end
|
132
132
|
|
133
|
-
kb_payment_transaction
|
134
|
-
kb_payment_transaction.id
|
133
|
+
kb_payment_transaction = ::Killbill::Plugin::Model::PaymentTransaction.new
|
134
|
+
kb_payment_transaction.id = kb_payment_transaction_id
|
135
135
|
kb_payment_transaction.transaction_type = transaction_type
|
136
|
-
kb_payment_transaction.external_key
|
137
|
-
kb_payment_transaction.created_date
|
136
|
+
kb_payment_transaction.external_key = kb_payment_transaction_external_key
|
137
|
+
kb_payment_transaction.created_date = Java::org.joda.time.DateTime.new(Java::org.joda.time.DateTimeZone::UTC)
|
138
138
|
kb_payment.transactions << kb_payment_transaction
|
139
139
|
|
140
140
|
kb_payment
|
@@ -144,6 +144,23 @@ module Killbill
|
|
144
144
|
@payments.find { |payment| payment.id == id.to_s }
|
145
145
|
end
|
146
146
|
end
|
147
|
+
|
148
|
+
class FakeJavaTenantUserApi
|
149
|
+
|
150
|
+
attr_accessor :per_tenant_config
|
151
|
+
|
152
|
+
def initialize(per_tenant_config)
|
153
|
+
@per_tenant_config = per_tenant_config
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_tenant_values_for_key(key, context)
|
157
|
+
result = @per_tenant_config[context.tenant_id.to_s]
|
158
|
+
if result
|
159
|
+
return [result]
|
160
|
+
end
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
147
164
|
end
|
148
165
|
end
|
149
166
|
end
|
@@ -17,14 +17,18 @@ module Killbill
|
|
17
17
|
@payment_method_model = payment_method_model
|
18
18
|
@transaction_model = transaction_model
|
19
19
|
@response_model = response_model
|
20
|
+
|
20
21
|
end
|
21
22
|
|
22
23
|
def start_plugin
|
24
|
+
|
23
25
|
@logger.progname = "#{@identifier.to_s}-plugin"
|
24
26
|
|
27
|
+
@config_key_name = "PLUGIN_CONFIG_#{@plugin_name}".to_sym
|
25
28
|
::Killbill::Plugin::ActiveMerchant.initialize! @gateway_builder,
|
26
29
|
@identifier.to_sym,
|
27
30
|
@logger,
|
31
|
+
@config_key_name,
|
28
32
|
"#{@conf_dir}/#{@identifier.to_s}.yml",
|
29
33
|
@kb_apis
|
30
34
|
|
@@ -45,6 +49,14 @@ module Killbill
|
|
45
49
|
@logger.debug { "after_request: pool.active_connection? = #{pool.active_connection?}, connection.active? = #{connection.active?}, pool.connections.size = #{pool.connections.size}, connections = #{pool.connections.inspect}" }
|
46
50
|
end
|
47
51
|
|
52
|
+
|
53
|
+
def on_event(event)
|
54
|
+
if (event.event_type == :TENANT_CONFIG_CHANGE || event.event_type == :TENANT_CONFIG_DELETION) &&
|
55
|
+
event.meta_data.to_sym == @config_key_name
|
56
|
+
::Killbill::Plugin::ActiveMerchant.invalidate_tenant_config!(event.tenant_id)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
48
60
|
def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
49
61
|
gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
|
50
62
|
gateway.authorize(amount_in_cents, payment_source, options)
|
@@ -161,7 +173,7 @@ module Killbill
|
|
161
173
|
|
162
174
|
# Go to the gateway
|
163
175
|
payment_processor_account_id = options[:payment_processor_account_id] || :default
|
164
|
-
gateway = lookup_gateway(payment_processor_account_id)
|
176
|
+
gateway = lookup_gateway(payment_processor_account_id, context.tenant_id)
|
165
177
|
gw_response = gateway.store(payment_source, options)
|
166
178
|
response, transaction = save_response_and_transaction(gw_response, :add_payment_method, kb_account_id, context.tenant_id, payment_processor_account_id)
|
167
179
|
|
@@ -189,7 +201,7 @@ module Killbill
|
|
189
201
|
|
190
202
|
# Delete the card
|
191
203
|
payment_processor_account_id = options[:payment_processor_account_id] || :default
|
192
|
-
gateway = lookup_gateway(payment_processor_account_id)
|
204
|
+
gateway = lookup_gateway(payment_processor_account_id, context.tenant_id)
|
193
205
|
if options[:customer_id]
|
194
206
|
gw_response = gateway.unstore(options[:customer_id], pm.token, options)
|
195
207
|
else
|
@@ -395,7 +407,7 @@ module Killbill
|
|
395
407
|
payment_processor_account_ids = options[:payment_processor_account_ids].nil? ? [options[:payment_processor_account_id] || :default] : options[:payment_processor_account_ids].split(',')
|
396
408
|
payment_processor_account_ids.each do |payment_processor_account_id|
|
397
409
|
# Find the gateway
|
398
|
-
gateway = lookup_gateway(payment_processor_account_id)
|
410
|
+
gateway = lookup_gateway(payment_processor_account_id, context.tenant_id)
|
399
411
|
|
400
412
|
# Filter before each gateway call
|
401
413
|
before_gateway(gateway, kb_transaction, last_transaction, payment_source, amount_in_cents, currency, options)
|
@@ -523,9 +535,9 @@ module Killbill
|
|
523
535
|
return response, transaction
|
524
536
|
end
|
525
537
|
|
526
|
-
def lookup_gateway(payment_processor_account_id=:default)
|
527
|
-
gateway = ::Killbill::Plugin::ActiveMerchant.gateways[payment_processor_account_id.to_sym]
|
528
|
-
raise "Unable to lookup gateway for payment_processor_account_id #{payment_processor_account_id}, gateways: #{::Killbill::Plugin::ActiveMerchant.gateways}" if gateway.nil?
|
538
|
+
def lookup_gateway(payment_processor_account_id=:default, kb_tenant_id=nil)
|
539
|
+
gateway = ::Killbill::Plugin::ActiveMerchant.gateways(kb_tenant_id)[payment_processor_account_id.to_sym]
|
540
|
+
raise "Unable to lookup gateway for payment_processor_account_id #{payment_processor_account_id}, kb_tenant_id = #{kb_tenant_id}, gateways: #{::Killbill::Plugin::ActiveMerchant.gateways(kb_tenant_id)}" if gateway.nil?
|
529
541
|
gateway
|
530
542
|
end
|
531
543
|
|
@@ -85,9 +85,9 @@ module Killbill
|
|
85
85
|
::Killbill::Plugin::ActiveMerchant.kb_apis
|
86
86
|
end
|
87
87
|
|
88
|
-
def gateway(payment_processor_account_id=:default)
|
89
|
-
gateway = ::Killbill::Plugin::ActiveMerchant.gateways[payment_processor_account_id.to_sym]
|
90
|
-
raise "Unable to lookup gateway for payment_processor_account_id #{payment_processor_account_id}, gateways: #{::Killbill::Plugin::ActiveMerchant.gateways}" if gateway.nil?
|
88
|
+
def gateway(payment_processor_account_id=:default, kb_tenant_id=nil)
|
89
|
+
gateway = ::Killbill::Plugin::ActiveMerchant.gateways(kb_tenant_id)[payment_processor_account_id.to_sym]
|
90
|
+
raise "Unable to lookup gateway for payment_processor_account_id #{payment_processor_account_id}, , kb_tenant_id = #{kb_tenant_id}, gateways: #{::Killbill::Plugin::ActiveMerchant.gateways(kb_tenant_id)}" if gateway.nil?
|
91
91
|
gateway
|
92
92
|
end
|
93
93
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'thread_safe'
|
2
|
+
|
1
3
|
module Killbill
|
2
4
|
module Plugin
|
3
5
|
module ActiveMerchant
|
@@ -46,100 +48,65 @@ module Killbill
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
# Relies on the fact that hashes enumerate their values in the order that the corresponding keys were inserted (Ruby 1.9+)
|
50
51
|
class BoundedLRUCache
|
52
|
+
include ThreadSafe::Util::CheapLockable
|
51
53
|
|
52
|
-
def initialize(proc, max_size=10000)
|
53
|
-
@proc = proc
|
54
|
+
def initialize(proc, max_size = 10000)
|
54
55
|
@max_size = max_size
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
lru_cache = Class.new(java.util.LinkedHashMap) do
|
61
|
-
def initialize(max_size)
|
62
|
-
super(max_size, 1.0, true)
|
63
|
-
@max_size = max_size
|
64
|
-
end
|
65
|
-
|
66
|
-
# Note: renaming it to remove_eldest_entry won't work
|
67
|
-
def removeEldestEntry(eldest)
|
68
|
-
size > @max_size
|
69
|
-
end
|
70
|
-
end.new(@max_size)
|
71
|
-
@data = java.util.Collections.synchronizedMap(lru_cache)
|
72
|
-
else
|
73
|
-
@is_jruby = false
|
74
|
-
@semaphore = Mutex.new
|
75
|
-
# TODO Pre-allocate?
|
76
|
-
@data = {}
|
56
|
+
@data = ThreadSafe::Cache.new do |hash, key|
|
57
|
+
# mapping key -> value is constant for our purposes
|
58
|
+
set_value = hash.fetch_or_store key, value = proc.call(key)
|
59
|
+
store_key(key) if value.equal?(set_value) # very same object
|
60
|
+
set_value
|
77
61
|
end
|
62
|
+
@keys = []
|
78
63
|
end
|
79
64
|
|
80
|
-
def [](key)
|
81
|
-
@is_jruby ? jruby_get(key) : ruby_get(key)
|
82
|
-
end
|
65
|
+
def [](key); @data[key] end
|
83
66
|
|
84
67
|
def []=(key, val)
|
85
|
-
|
68
|
+
prev_val = @data.get_and_set(key, val)
|
69
|
+
prev_val.nil? ? store_key(key) : update_key(key)
|
70
|
+
val
|
86
71
|
end
|
87
72
|
|
88
|
-
#
|
73
|
+
# @private for testing
|
74
|
+
def size; @data.size end
|
89
75
|
|
90
|
-
|
91
|
-
|
76
|
+
# @private for testing
|
77
|
+
def keys
|
78
|
+
cheap_synchronize { @keys.dup }
|
92
79
|
end
|
93
80
|
|
94
|
-
|
95
|
-
|
81
|
+
# @private for testing
|
82
|
+
def values
|
83
|
+
cheap_synchronize { @keys.map { |key| self[key] } }
|
96
84
|
end
|
97
85
|
|
98
|
-
|
99
|
-
@is_jruby ? @data.values.to_a : @data.values
|
100
|
-
end
|
86
|
+
protected
|
101
87
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
if value.nil?
|
107
|
-
value = @proc.call(key)
|
108
|
-
# Somebody may have beaten us to it but the mapping key -> value is constant for our purposes
|
109
|
-
jruby_set(key, value)
|
88
|
+
def store_key(key)
|
89
|
+
cheap_synchronize do
|
90
|
+
@keys << key
|
91
|
+
remove_eldest_key_if_full
|
110
92
|
end
|
111
|
-
value
|
112
93
|
end
|
113
94
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
def ruby_get(key)
|
119
|
-
@semaphore.synchronize do
|
120
|
-
found = true
|
121
|
-
value = @data.delete(key) { found = false }
|
122
|
-
if found
|
123
|
-
@data[key] = value
|
124
|
-
else
|
125
|
-
value = @proc.call(key)
|
126
|
-
@data[key] = value
|
127
|
-
value
|
128
|
-
end
|
95
|
+
def update_key(key)
|
96
|
+
cheap_synchronize do
|
97
|
+
@keys.delete(key); @keys << key
|
98
|
+
remove_eldest_key_if_full
|
129
99
|
end
|
130
100
|
end
|
131
101
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
if @data.length > @max_size
|
137
|
-
@data.delete(@data.first[0])
|
138
|
-
end
|
139
|
-
val
|
140
|
-
end
|
102
|
+
private
|
103
|
+
|
104
|
+
def remove_eldest_key_if_full
|
105
|
+
@data.delete @keys.shift if @data.size > @max_size
|
141
106
|
end
|
107
|
+
|
142
108
|
end
|
109
|
+
|
143
110
|
end
|
144
111
|
end
|
145
112
|
end
|