killbill 1.0.0

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.
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ build
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ .jbundler
21
+ Jarfile.lock
22
+ Gemfile.lock
23
+ *.swp
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+
3
+ notifications:
4
+ email:
5
+ - killbilling-dev@googlegroups.com
6
+
7
+ rvm:
8
+ - jruby-18mode
9
+ - jruby-19mode
10
+ - jruby-head
11
+
12
+ jdk:
13
+ - openjdk7
14
+ - oraclejdk7
15
+ - openjdk6
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: jruby-head
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Jarfile ADDED
@@ -0,0 +1,2 @@
1
+ jar 'com.ning.billing:killbill-api', '0.1.48'
2
+ jar 'com.ning.billing:killbill-util:tests', '0.1.48'
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ killbill-plugin-framework-ruby
2
+ ==============================
3
+
4
+ Framework to write Killbill plugins in Ruby.
5
+
6
+ There are various types of plugins one can write for Killbill:
7
+
8
+ 1. notifications plugins, which listen to external bus events and can react to it
9
+ 2. payment plugins, which are used to issue payments against a payment gateway
10
+
11
+ How to write a Notification plugin
12
+ ----------------------------------
13
+
14
+ require 'killbill'
15
+
16
+ class MyNotificationPlugin < Killbill::Plugin::Notification
17
+ # Overriding this method is optional, only if you need to do some initialization work
18
+ def start_plugin
19
+ puts "MyNotificationPlugin plugin starting"
20
+ super
21
+ puts "MyNotificationPlugin plugin started"
22
+ end
23
+
24
+ # Invoked each time an event is received
25
+ def on_event(event)
26
+ puts "Received Killbill event #{event}"
27
+ end
28
+
29
+ # Overriding this method is optional, only if you need to do some tear down work
30
+ def stop_plugin
31
+ puts "MyNotificationPlugin plugin stopping"
32
+ super
33
+ puts "MyNotificationPlugin plugin stopped"
34
+ end
35
+ end
36
+
37
+ Make sure to create the corresponding killbill.properties file:
38
+
39
+ mainClass=MyNotificationPlugin
40
+ pluginType=NOTIFICATION
41
+
42
+ How to write a Payment plugin
43
+ -----------------------------
44
+
45
+ require 'killbill'
46
+
47
+ class MyPaymentPlugin < Killbill::Plugin::Payment
48
+ def start_plugin
49
+ puts "MyPaymentPlugin plugin starting"
50
+ super
51
+ puts "MyPaymentPlugin plugin started"
52
+ end
53
+
54
+ def charge(killbill_account_id, killbill_payment_id, amount_in_cents, options = {})
55
+ end
56
+
57
+ def refund(killbill_account_id, killbill_payment_id, amount_in_cents, options = {})
58
+ end
59
+
60
+ def get_payment_info(killbill_payment_id, options = {})
61
+ end
62
+
63
+ def add_payment_method(payment_method, options = {})
64
+ end
65
+
66
+ def delete_payment_method(external_payment_method_id, options = {})
67
+ end
68
+
69
+ def update_payment_method(payment_method, options = {})
70
+ end
71
+
72
+ def set_default_payment_method(payment_method, options = {})
73
+ end
74
+
75
+ def create_account(killbill_account, options = {})
76
+ end
77
+
78
+ # Overriding this method is optional, only if you need to do some tear down work
79
+ def stop_plugin
80
+ puts "MyPaymentPlugin plugin stopping"
81
+ super
82
+ puts "MyPaymentPlugin plugin stopped"
83
+ end
84
+ end
85
+
86
+ Make sure to create the corresponding killbill.properties file:
87
+
88
+ mainClass=MyPaymentPlugin
89
+ pluginType=PAYMENT
90
+
91
+ Rake tasks
92
+ ----------
93
+
94
+ The killbill gem also ships helpful Rake tasks to package Killbill-ready plugins.
95
+
96
+ To access these tasks, add the following to your Rakefile:
97
+
98
+ # Install tasks to package the plugin for Killbill
99
+ require 'killbill/rake_task'
100
+ Killbill::PluginHelper.install_tasks
101
+
102
+ # (Optional) Install tasks to build and release your plugin gem
103
+ require 'bundler/setup'
104
+ Bundler::GemHelper.install_tasks
105
+
106
+ You can verify these tasks are available by running `rake -T`.
107
+
108
+ To build the artifacts into pkg/:
109
+
110
+ # Cleanup output directories
111
+ rake killbill:clean
112
+ # Build your plugin gem in the pkg/ directory
113
+ rake build
114
+ # Build the Killbill plugin in the pkg/ directory
115
+ # The <plugin_name>-<plugin-version>/ directory is used as a staging directory
116
+ rake killbill:package
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+
3
+ # Install tasks to build and release the plugin
4
+ require 'bundler/setup'
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ # Install test tasks
8
+ require 'rspec/core/rake_task'
9
+ desc "Run RSpec"
10
+ RSpec::Core::RakeTask.new
11
+
12
+ # Run tests by default
13
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/killbill.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'killbill'
5
+ s.version = version
6
+ s.summary = 'Framework to write Killbill plugins in Ruby.'
7
+ s.description = 'Base classes to write plugins.'
8
+
9
+ s.required_ruby_version = '>= 1.9.3'
10
+
11
+ s.license = 'Apache License (2.0)'
12
+
13
+ s.author = 'Killbill core team'
14
+ s.email = 'killbilling-users@googlegroups.com'
15
+ s.homepage = 'http://www.killbilling.org'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.bindir = 'bin'
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.rdoc_options << '--exclude' << '.'
24
+
25
+ s.add_development_dependency 'jbundler', '~> 0.4.1'
26
+ s.add_development_dependency 'rake', '>= 0.8.7'
27
+ s.add_development_dependency 'rspec', '~> 2.12.0'
28
+
29
+ s.requirements << "jar 'com.ning.billing:killbill-api', '0.1.48'"
30
+ # For testing only
31
+ s.requirements << "jar 'com.ning.billing:killbill-util:tests', '0.1.48'"
32
+ end
data/lib/killbill.rb ADDED
@@ -0,0 +1,46 @@
1
+ begin
2
+ require 'java'
3
+ rescue LoadError => e
4
+ warn 'You need JRuby to run Killbill plugins'
5
+ raise e
6
+ end
7
+
8
+ KILLBILL_APIS = %w(
9
+ com.ning.billing.account.api.AccountUserApi
10
+ com.ning.billing.analytics.api.sanity.AnalyticsSanityApi
11
+ com.ning.billing.analytics.api.user.AnalyticsUserApi
12
+ com.ning.billing.catalog.api.CatalogUserApi
13
+ com.ning.billing.entitlement.api.migration.EntitlementMigrationApi
14
+ com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi
15
+ com.ning.billing.entitlement.api.transfer.EntitlementTransferApi
16
+ com.ning.billing.entitlement.api.user.EntitlementUserApi
17
+ com.ning.billing.invoice.api.InvoiceMigrationApi
18
+ com.ning.billing.invoice.api.InvoicePaymentApi
19
+ com.ning.billing.invoice.api.InvoiceUserApi
20
+ com.ning.billing.meter.api.MeterUserApi
21
+ com.ning.billing.overdue.OverdueUserApi
22
+ com.ning.billing.payment.api.PaymentApi
23
+ com.ning.billing.tenant.api.TenantUserApi
24
+ com.ning.billing.usage.api.UsageUserApi
25
+ com.ning.billing.util.api.AuditUserApi
26
+ com.ning.billing.util.api.CustomFieldUserApi
27
+ com.ning.billing.util.api.ExportUserApi
28
+ com.ning.billing.util.api.TagUserApi
29
+ )
30
+
31
+ begin
32
+ KILLBILL_APIS.each { |api| java_import api }
33
+ rescue NameError
34
+ # killbill-api should be provided by the JRuby OSGI bundle. We default to using JBundler for development purposes only
35
+ begin
36
+ require 'jbundler'
37
+ KILLBILL_APIS.each { |api| java_import api }
38
+ warn 'Using JBundler to load killbill-api. This should only happen in development mode!'
39
+ warn "Classpath (see .jbundler/classpath.rb):\n\t#{JBUNDLER_CLASSPATH.join("\n\t")}"
40
+ rescue LoadError => e
41
+ warn 'Unable to load killbill-api and couldn\'t find JBundler. For development purposes, make sure to run: `bundle install && jbundle install\' from the killbill gem source tree'
42
+ end
43
+ end
44
+
45
+ require 'killbill/notification'
46
+ require 'killbill/payment'
@@ -0,0 +1,14 @@
1
+ require 'killbill/plugin'
2
+
3
+ module Killbill
4
+ module Plugin
5
+ class Notification < PluginBase
6
+
7
+ # Override this method in your plugin to act upon received events
8
+ def on_event(event)
9
+ # no-op
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ require 'killbill/plugin'
2
+
3
+ module Killbill
4
+ module Plugin
5
+ class Payment < PluginBase
6
+
7
+ class OperationUnsupportedByGatewayError < NotImplementedError
8
+ end
9
+
10
+ def charge(external_account_key, killbill_payment_id, amount_in_cents, options = {})
11
+ raise OperationUnsupportedByGatewayError
12
+ end
13
+
14
+ def refund(external_account_key, killbill_payment_id, amount_in_cents, options = {})
15
+ raise OperationUnsupportedByGatewayError
16
+ end
17
+
18
+ def get_payment_info(killbill_payment_id, options = {})
19
+ raise OperationUnsupportedByGatewayError
20
+ end
21
+
22
+ def add_payment_method(external_account_key, payment_method, options = {})
23
+ raise OperationUnsupportedByGatewayError
24
+ end
25
+
26
+ def delete_payment_method(external_account_key, external_payment_method_id, options = {})
27
+ raise OperationUnsupportedByGatewayError
28
+ end
29
+
30
+ def update_payment_method(external_account_key, payment_method, options = {})
31
+ raise OperationUnsupportedByGatewayError
32
+ end
33
+
34
+ def set_default_payment_method(external_account_key, payment_method, options = {})
35
+ raise OperationUnsupportedByGatewayError
36
+ end
37
+
38
+ def create_account(killbill_account, options = {})
39
+ raise OperationUnsupportedByGatewayError
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ module Killbill
2
+ # There are various types of plugins one can write for Killbill:
3
+ #
4
+ # 1) notifications plugins, which listen to external bus events and can react to it
5
+ # 2) payment plugins, which are used to issue payments against a payment gateway
6
+ module Plugin
7
+ class PluginBase
8
+
9
+ attr_reader :active
10
+
11
+ # Called by the Killbill lifecycle when initializing the plugin
12
+ def start_plugin
13
+ @active = true
14
+ end
15
+
16
+ # Called by the Killbill lifecycle when stopping the plugin
17
+ def stop_plugin
18
+ @active = false
19
+ end
20
+
21
+ attr_accessor :account_user_api,
22
+ :analytics_sanity_api,
23
+ :analytics_user_api,
24
+ :catalog_user_api,
25
+ :entitlement_migration_api,
26
+ :entitlement_timeline_api,
27
+ :entitlement_transfer_api,
28
+ :entitlement_user_api,
29
+ :invoice_migration_api,
30
+ :invoice_payment_api,
31
+ :invoice_user_api,
32
+ :meter_user_api,
33
+ :overdue_user_api,
34
+ :payment_api,
35
+ :tenant_user_api,
36
+ :usage_user_api,
37
+ :audit_user_api,
38
+ :custom_field_user_api,
39
+ :export_user_api,
40
+ :tag_user_api
41
+
42
+ # Called by the Killbill lifecycle when instantiating the plugin
43
+ def initialize(apis_map = {})
44
+ @active = false
45
+
46
+ apis_map.each do |api_name, api_instance|
47
+ begin
48
+ self.send("#{api_name}=", api_instance)
49
+ rescue NoMethodError
50
+ warn "Ignoring unsupported API: #{api_name}"
51
+ end
52
+ end
53
+ end
54
+
55
+ class APINotAvailableError < NotImplementedError
56
+ end
57
+
58
+ def method_missing(m, *args, &block)
59
+ raise APINotAvailableError.new("API #{m} is not available") if m =~ /_api$/
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,185 @@
1
+ require 'bundler'
2
+ require 'logger'
3
+ require 'pathname'
4
+ require 'rake'
5
+ require 'rake/packagetask'
6
+
7
+ module Killbill
8
+ class PluginHelper
9
+ include Rake::DSL
10
+
11
+ class << self
12
+ def install_tasks(opts = {})
13
+ new(opts[:base_name] || Dir.pwd, # Path to the plugin root directory (where the gempec and/or Gemfile should be)
14
+ opts[:plugin_name], # Plugin name, e.g. 'klogger'
15
+ opts[:gem_name], # Gem file name, e.g. 'klogger-1.0.0.gem'
16
+ opts[:gemfile_name] || "Gemfile", # Gemfile name
17
+ opts[:gemfile_lock_name] || "Gemfile.lock") # Gemfile.lock name
18
+ .install
19
+ end
20
+ end
21
+
22
+ def initialize(base_name, plugin_name, gem_name, gemfile_name, gemfile_lock_name)
23
+ @logger = Logger.new(STDOUT)
24
+ @logger.level = Logger::INFO
25
+
26
+ @base_name = base_name
27
+ @plugin_name = plugin_name
28
+ @gem_name = gem_name
29
+ @gemfile_name = gemfile_name
30
+ @gemfile_lock_name = gemfile_lock_name
31
+
32
+ # Plugin base directory
33
+ @base = Pathname.new(@base_name).expand_path
34
+
35
+ # Find the gemspec to determine name and version
36
+ @plugin_gemspec = find_plugin_gemspec
37
+
38
+ # Temporary build directory
39
+ # Don't use 'pkg' as it is used by Rake::PackageTask already: it will
40
+ # hard link all files from @package_dir to pkg to avoid tar'ing up symbolic links
41
+ @package_dir = Pathname.new(name).expand_path
42
+
43
+ # Staging area to install gem dependencies
44
+ # Note the Killbill friendly structure (which we will keep in the tarball)
45
+ @target_dir = @package_dir.join("#{version}/gems").expand_path
46
+
47
+ # Staging area to install the killbill.properties file
48
+ @killbill_properties_target_dir = @package_dir.join("#{version}").expand_path
49
+ end
50
+
51
+ def specs
52
+ # Rely on the Gemfile definition, if it exists, to get all dependencies
53
+ # (we assume the Gemfile includes the plugin gemspec, as it should).
54
+ # Otherwise, use only the plugin gemspec.
55
+ @specs ||= @gemfile_definition ? @gemfile_definition.specs : [@plugin_gemspec]
56
+ end
57
+
58
+ def install
59
+ namespace :killbill do
60
+ desc "Validate plugin tree"
61
+ task :validate => killbill_properties_file do
62
+ validate
63
+ end
64
+
65
+ # Build the .tar.gz and .zip packages
66
+ task :package => :stage
67
+ package_task = Rake::PackageTask.new(name, version) do |p|
68
+ p.need_tar_gz = true
69
+ p.need_zip = true
70
+ end
71
+
72
+ desc "Stage all dependencies"
73
+ task :stage => :validate do
74
+ stage_dependencies
75
+ stage_killbill_properties_file
76
+
77
+ # Small hack! Update the list of files to package (Rake::FileList is evaluated too early above)
78
+ package_task.package_files = Rake::FileList.new("#{@package_dir.basename}/**/*")
79
+ end
80
+
81
+ desc "List all dependencies"
82
+ task :dependency => :validate do
83
+ print_dependencies
84
+ end
85
+
86
+ desc "Delete #{@package_dir}"
87
+ task :clean => :clobber_package do
88
+ rm_rf @package_dir
89
+ end
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def validate
96
+ @plugin_gem_file = find_plugin_gem
97
+ @gemfile_definition = find_gemfile
98
+ end
99
+
100
+ def print_dependencies
101
+ puts "Gems to be staged:"
102
+ specs.each { |spec| puts " #{spec.name} (#{spec.version})" }
103
+ end
104
+
105
+ def name
106
+ @plugin_gemspec.name
107
+ end
108
+
109
+ def version
110
+ @plugin_gemspec.version
111
+ end
112
+
113
+ # Parse the <plugin_name>.gemspec file
114
+ def find_plugin_gemspec
115
+ gemspecs = @plugin_name ? [File.join(@base, "#{@plugin_name}.gemspec")] : Dir[File.join(@base, "{,*}.gemspec")]
116
+ raise "Unable to find your plugin gemspec in #{@base}" unless gemspecs.size == 1
117
+ spec_path = gemspecs.first
118
+ @logger.debug "Parsing #{spec_path}"
119
+ Bundler.load_gemspec(spec_path)
120
+ end
121
+
122
+ def find_plugin_gem
123
+ if @gem_name
124
+ # Absolute path?
125
+ plugin_gem_file = Pathname.new(@gem_name).expand_path
126
+ # Relative path to the base?
127
+ plugin_gem_file = @base.join(@gem_name).expand_path unless plugin_gem_file.file?
128
+ raise "Unable to find your plugin gem in #{@base}. Did you build it (`rake build')?" unless plugin_gem_file.file?
129
+ else
130
+ plugin_gem_files = Dir[File.join(@base, "**/#{name}-#{version}.gem")]
131
+ @logger.debug "Gem candidates found: #{plugin_gem_files}"
132
+ raise "Unable to find your plugin gem in #{@base}. Did you build it? (`rake build')" unless plugin_gem_files.size >= 1
133
+ # Take the first one, assume the other ones are from build directories (e.g. pkg)
134
+ plugin_gem_file = plugin_gem_files.first
135
+ end
136
+
137
+ @logger.debug "Found #{plugin_gem_file}"
138
+ Pathname.new(plugin_gem_file).expand_path
139
+ end
140
+
141
+ # Parse the existing Gemfile and Gemfile.lock files
142
+ def find_gemfile
143
+ gemfile = @base.join(@gemfile_name).expand_path
144
+ # Don't make the Gemfile a requirement, a gemspec should be enough
145
+ return nil unless gemfile.file?
146
+
147
+ # Make sure the developer ran `bundle install' first. We could probably run
148
+ # Bundler::Installer::install(@target_dir, @definition, {})
149
+ # but it may be better to make sure all dependencies are resolved first,
150
+ # before attempting to build the plugin
151
+ gemfile_lock = @base.join(@gemfile_lock_name).expand_path
152
+ raise "Unable to find the Gemfile.lock at #{gemfile_lock} for your plugin. Please run `bundle install' first" unless gemfile_lock.file?
153
+
154
+ @logger.debug "Parsing #{gemfile} and #{gemfile_lock}"
155
+ Bundler::Definition.build(gemfile, gemfile_lock, nil)
156
+ end
157
+
158
+ def stage_dependencies
159
+ # Create the target directory
160
+ mkdir_p @target_dir.to_s
161
+
162
+ @logger.debug "Installing all gem dependencies to #{@target_dir}"
163
+ # We can't simply use Bundler::Installer unfortunately, because we can't tell it to copy the gems for cached ones
164
+ # (it will default to using Bundler::Source::Path references to the gemspecs on "install").
165
+ specs.each do |spec|
166
+ # For the plugin itself, install it manually (the cache path is likely to be wrong)
167
+ next if spec.name == name and spec.version == version
168
+ @logger.debug "Staging #{spec.name} (#{spec.version}) from #{spec.cache_file}"
169
+ Gem::Installer.new(spec.cache_file, {:force => true, :install_dir => @target_dir}).install
170
+ end
171
+
172
+ @logger.debug "Staging #{name} (#{version}) from #{@plugin_gem_file}"
173
+ Gem::Installer.new(@plugin_gem_file, {:force => true, :install_dir => @target_dir}).install
174
+ end
175
+
176
+ def stage_killbill_properties_file
177
+ @logger.debug "Staging #{killbill_properties_file} to #{@killbill_properties_target_dir}"
178
+ cp killbill_properties_file, @killbill_properties_target_dir
179
+ end
180
+
181
+ def killbill_properties_file
182
+ @base.join("killbill.properties").expand_path.to_s
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ class LifecycleNotificationPlugin < Killbill::Plugin::PluginBase
4
+ attr_accessor :lifecycled
5
+
6
+ def start_plugin
7
+ @lifecycled = true
8
+ super
9
+ end
10
+
11
+ def stop_plugin
12
+ @lifecycled = true
13
+ super
14
+ end
15
+ end
16
+
17
+ describe Killbill::Plugin::PluginBase do
18
+ it 'should be able to register Killbill API instances' do
19
+ plugin = Killbill::Plugin::PluginBase.new(:account_user_api => MockAccountUserApi.new)
20
+
21
+ plugin.account_user_api.get_accounts(nil).size.should == 0
22
+ lambda { plugin.foobar_user_api.do_foo('with my bar') }.should raise_error Killbill::Plugin::PluginBase::APINotAvailableError
23
+ end
24
+
25
+ it 'should be able to add custom code in the startup/shutdown sequence' do
26
+ plugin = LifecycleNotificationPlugin.new
27
+
28
+ plugin.lifecycled = false
29
+ plugin.lifecycled.should be_false
30
+ plugin.active.should be_false
31
+
32
+ plugin.start_plugin
33
+ plugin.lifecycled.should be_true
34
+ plugin.active.should be_true
35
+
36
+ plugin.lifecycled = false
37
+ plugin.lifecycled.should be_false
38
+ plugin.active.should be_true
39
+
40
+ plugin.stop_plugin
41
+ plugin.lifecycled.should be_true
42
+ plugin.active.should be_false
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ java_import 'java.util.UUID'
4
+ java_import 'org.joda.time.DateTimeZone'
5
+ java_import 'com.ning.billing.catalog.api.Currency'
6
+ java_import 'com.ning.billing.mock.api.MockBillCycleDay'
7
+
8
+ describe Killbill::Plugin do
9
+ before(:each) do
10
+ @account_user_api = MockAccountUserApi.new
11
+ end
12
+
13
+ it 'should be able to access Killbill mock APIs' do
14
+ @account_user_api.createAccount(UUID.randomUUID,
15
+ 'externalKey',
16
+ 'email',
17
+ 'name',
18
+ 1,
19
+ Currency::USD,
20
+ MockBillCycleDay.new(12),
21
+ UUID.randomUUID,
22
+ DateTimeZone::UTC,
23
+ 'locale',
24
+ 'address1',
25
+ 'address2',
26
+ 'companyName',
27
+ 'city',
28
+ 'stateOrProvince',
29
+ 'country',
30
+ 'postalCode',
31
+ 'phone')
32
+ account = @account_user_api.getAccountByKey('externalKey', nil)
33
+ account.external_key.should == 'externalKey'
34
+ account.email.should == 'email'
35
+ account.name.should == 'name'
36
+ account.first_name_length.should == 1
37
+ account.currency.should == Currency::USD
38
+ account.payment_method_id.should_not be_nil
39
+ account.time_zone.should == DateTimeZone::UTC
40
+ account.locale.should == 'locale'
41
+ account.address1.should == 'address1'
42
+ account.address2.should == 'address2'
43
+ account.company_name.should == 'companyName'
44
+ account.city.should == 'city'
45
+ account.state_or_province.should == 'stateOrProvince'
46
+ account.country.should == 'country'
47
+ account.postal_code.should == 'postalCode'
48
+ account.phone.should == 'phone'
49
+ end
50
+ end
51
+
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyNotificationPlugin < Killbill::Plugin::Notification
4
+ end
5
+
6
+ class HoarderNotificationPlugin < Killbill::Plugin::Notification
7
+ attr_reader :events
8
+
9
+ def start_plugin
10
+ @events = []
11
+ super
12
+ end
13
+
14
+ def on_event(event)
15
+ @events << event
16
+ end
17
+
18
+ def stop_plugin
19
+ super
20
+ @events = []
21
+ end
22
+ end
23
+
24
+ describe Killbill::Plugin::Notification do
25
+ before(:each) do
26
+ @event = Hash.new(:account_id => SecureRandom.uuid)
27
+ end
28
+
29
+ it "should not raise exceptions by default" do
30
+ plugin = DummyNotificationPlugin.new
31
+ lambda { plugin.on_event(@event) }.should_not raise_error
32
+ end
33
+
34
+ it "should be able to receive all events" do
35
+ plugin = HoarderNotificationPlugin.new
36
+
37
+ plugin.start_plugin
38
+ plugin.events.size.should == 0
39
+
40
+ (1..100).each do |i|
41
+ plugin.on_event(@event)
42
+ plugin.events.size.should == i
43
+ plugin.events[-1].should == @event
44
+ end
45
+
46
+ plugin.stop_plugin
47
+ plugin.events.size.should == 0
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyPaymentPlugin < Killbill::Plugin::Payment
4
+ end
5
+
6
+ describe Killbill::Plugin::Payment do
7
+ before(:each) do
8
+ @external_account_key = SecureRandom.uuid
9
+ @killbill_payment_id = SecureRandom.uuid
10
+ @amount_in_cents = rand(100000)
11
+
12
+ @payment_method = Hash.new(:credit_card => SecureRandom.uuid)
13
+ @external_payment_method_id = SecureRandom.uuid
14
+
15
+ @killbill_account = Hash.new(:name => SecureRandom.uuid)
16
+
17
+ @plugin = DummyPaymentPlugin.new
18
+ end
19
+
20
+ it "should raise exceptions for unsupported operations" do
21
+ lambda { @plugin.charge(@external_account_key, @killbill_payment_id, @amount_in_cents) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
22
+ lambda { @plugin.refund(@external_account_key, @killbill_payment_id, @amount_in_cents) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
23
+ lambda { @plugin.get_payment_info(@killbill_payment_id) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
24
+ lambda { @plugin.add_payment_method(@external_account_key, @payment_method) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
25
+ lambda { @plugin.delete_payment_method(@external_account_key, @external_payment_method_id) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
26
+ lambda { @plugin.update_payment_method(@external_account_key, @payment_method) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
27
+ lambda { @plugin.set_default_payment_method(@external_account_key, @payment_method) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
28
+ lambda { @plugin.create_account(@killbill_account) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ require 'bundler'
2
+ require 'killbill'
3
+
4
+ %w(
5
+ MockAccountUserApi
6
+ MockEntitlementUserApi
7
+ ).each do |api|
8
+ begin
9
+ java_import "com.ning.billing.mock.api.#{api}"
10
+ rescue LoadError
11
+ end
12
+ end
13
+
14
+ require 'rspec'
15
+
16
+ RSpec.configure do |config|
17
+ config.color_enabled = true
18
+ config.tty = true
19
+ config.formatter = 'documentation'
20
+ end
21
+
22
+ begin
23
+ require 'securerandom'
24
+ SecureRandom.uuid
25
+ rescue LoadError, NoMethodError
26
+ # See http://jira.codehaus.org/browse/JRUBY-6176
27
+ module SecureRandom
28
+ def self.uuid
29
+ ary = self.random_bytes(16).unpack("NnnnnN")
30
+ ary[2] = (ary[2] & 0x0fff) | 0x4000
31
+ ary[3] = (ary[3] & 0x3fff) | 0x8000
32
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
33
+ end unless respond_to?(:uuid)
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: killbill
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Killbill core team
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: jbundler
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 0.4.1
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.1
27
+ none: false
28
+ prerelease: false
29
+ type: :development
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 0.8.7
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: 0.8.7
43
+ none: false
44
+ prerelease: false
45
+ type: :development
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: 2.12.0
53
+ none: false
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ version: 2.12.0
59
+ none: false
60
+ prerelease: false
61
+ type: :development
62
+ description: Base classes to write plugins.
63
+ email: killbilling-users@googlegroups.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .gitignore
69
+ - .travis.yml
70
+ - Gemfile
71
+ - Jarfile
72
+ - README.md
73
+ - Rakefile
74
+ - VERSION
75
+ - killbill.gemspec
76
+ - lib/killbill.rb
77
+ - lib/killbill/notification.rb
78
+ - lib/killbill/payment.rb
79
+ - lib/killbill/plugin.rb
80
+ - lib/killbill/rake_task.rb
81
+ - spec/killbill/base_plugin_spec.rb
82
+ - spec/killbill/killbill_integration_spec.rb
83
+ - spec/killbill/notification_plugin_spec.rb
84
+ - spec/killbill/payment_plugin_spec.rb
85
+ - spec/spec_helper.rb
86
+ homepage: http://www.killbilling.org
87
+ licenses:
88
+ - Apache License (2.0)
89
+ post_install_message:
90
+ rdoc_options:
91
+ - --exclude
92
+ - .
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: 1.9.3
100
+ none: false
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ hash: 2
108
+ version: !binary |-
109
+ MA==
110
+ none: false
111
+ requirements:
112
+ - jar 'com.ning.billing:killbill-api', '0.1.48'
113
+ - jar 'com.ning.billing:killbill-util:tests', '0.1.48'
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.24
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Framework to write Killbill plugins in Ruby.
119
+ test_files:
120
+ - spec/killbill/base_plugin_spec.rb
121
+ - spec/killbill/killbill_integration_spec.rb
122
+ - spec/killbill/notification_plugin_spec.rb
123
+ - spec/killbill/payment_plugin_spec.rb
124
+ - spec/spec_helper.rb