killbill 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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