killbill 3.1.3 → 3.1.4

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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/Jarfile +7 -5
  3. data/NEWS +3 -0
  4. data/README.md +41 -17
  5. data/VERSION +1 -1
  6. data/generators/active_merchant/templates/Jarfile.rb +7 -5
  7. data/generators/active_merchant/templates/config.yml.rb +3 -3
  8. data/generators/active_merchant/templates/db/ddl.sql.rb +4 -0
  9. data/generators/active_merchant/templates/db/schema.rb +4 -0
  10. data/generators/active_merchant/templates/lib/api.rb +42 -22
  11. data/generators/active_merchant/templates/lib/models/response.rb +3 -1
  12. data/generators/active_merchant/templates/plugin.gemspec.rb +1 -1
  13. data/lib/killbill.rb +7 -4
  14. data/lib/killbill/gen/api/account.rb +4 -3
  15. data/lib/killbill/gen/api/account_api_exception.rb +4 -3
  16. data/lib/killbill/gen/api/account_audit_logs.rb +12 -68
  17. data/lib/killbill/gen/api/account_audit_logs_for_object_type.rb +4 -3
  18. data/lib/killbill/gen/api/account_data.rb +4 -3
  19. data/lib/killbill/gen/api/account_email.rb +4 -3
  20. data/lib/killbill/gen/api/account_user_api.rb +4 -3
  21. data/lib/killbill/gen/api/audit_log.rb +4 -3
  22. data/lib/killbill/gen/api/audit_user_api.rb +4 -3
  23. data/lib/killbill/gen/api/billing_exception_base.rb +4 -3
  24. data/lib/killbill/gen/api/block.rb +4 -3
  25. data/lib/killbill/gen/api/blockable.rb +4 -3
  26. data/lib/killbill/gen/api/blocking_api_exception.rb +4 -3
  27. data/lib/killbill/gen/api/blocking_state.rb +4 -3
  28. data/lib/killbill/gen/api/call_context.rb +4 -3
  29. data/lib/killbill/gen/api/catalog.rb +4 -3
  30. data/lib/killbill/gen/api/catalog_api_exception.rb +4 -3
  31. data/lib/killbill/gen/api/catalog_user_api.rb +4 -3
  32. data/lib/killbill/gen/api/column_info.rb +4 -3
  33. data/lib/killbill/gen/api/control_tag.rb +4 -3
  34. data/lib/killbill/gen/api/currency_conversion.rb +4 -3
  35. data/lib/killbill/gen/api/currency_conversion_api.rb +4 -3
  36. data/lib/killbill/gen/api/currency_conversion_exception.rb +4 -3
  37. data/lib/killbill/gen/api/currency_value_null.rb +4 -3
  38. data/lib/killbill/gen/api/custom_field.rb +4 -3
  39. data/lib/killbill/gen/api/custom_field_api_exception.rb +4 -3
  40. data/lib/killbill/gen/api/custom_field_user_api.rb +4 -3
  41. data/lib/killbill/gen/api/database_export_output_stream.rb +4 -3
  42. data/lib/killbill/gen/api/direct_payment.rb +39 -11
  43. data/lib/killbill/gen/api/direct_payment_api.rb +643 -31
  44. data/lib/killbill/gen/api/direct_payment_transaction.rb +37 -12
  45. data/lib/killbill/gen/api/duration.rb +4 -3
  46. data/lib/killbill/gen/api/entitlement.rb +4 -3
  47. data/lib/killbill/gen/api/entitlement_ao_status_dry_run.rb +4 -3
  48. data/lib/killbill/gen/api/entitlement_api.rb +4 -3
  49. data/lib/killbill/gen/api/entitlement_api_exception.rb +4 -3
  50. data/lib/killbill/gen/api/entity.rb +4 -3
  51. data/lib/killbill/gen/api/fixed.rb +4 -3
  52. data/lib/killbill/gen/api/illegal_plan_change.rb +4 -3
  53. data/lib/killbill/gen/api/international_price.rb +4 -3
  54. data/lib/killbill/gen/api/invalid_config_exception.rb +4 -3
  55. data/lib/killbill/gen/api/invoice.rb +4 -3
  56. data/lib/killbill/gen/api/invoice_api_exception.rb +4 -3
  57. data/lib/killbill/gen/api/invoice_creation_event.rb +4 -3
  58. data/lib/killbill/gen/api/invoice_formatter.rb +4 -3
  59. data/lib/killbill/gen/api/invoice_item.rb +4 -3
  60. data/lib/killbill/gen/api/invoice_item_formatter.rb +4 -3
  61. data/lib/killbill/gen/api/invoice_payment.rb +7 -7
  62. data/lib/killbill/gen/api/invoice_payment_api.rb +7 -153
  63. data/lib/killbill/gen/api/invoice_user_api.rb +22 -3
  64. data/lib/killbill/gen/api/limit.rb +4 -3
  65. data/lib/killbill/gen/api/listing.rb +4 -3
  66. data/lib/killbill/gen/api/migration_plan.rb +4 -3
  67. data/lib/killbill/gen/api/mutable_account_data.rb +4 -3
  68. data/lib/killbill/gen/api/osgi_killbill.rb +15 -7
  69. data/lib/killbill/gen/api/osgi_plugin_properties.rb +4 -3
  70. data/lib/killbill/gen/api/pagination.rb +4 -3
  71. data/lib/killbill/gen/api/payment_api_exception.rb +4 -3
  72. data/lib/killbill/gen/api/payment_gateway_api.rb +4 -3
  73. data/lib/killbill/gen/api/payment_method.rb +11 -4
  74. data/lib/killbill/gen/api/payment_method_plugin.rb +5 -76
  75. data/lib/killbill/gen/api/payment_options.rb +68 -0
  76. data/lib/killbill/gen/api/plan.rb +4 -3
  77. data/lib/killbill/gen/api/plan_change_result.rb +4 -3
  78. data/lib/killbill/gen/api/plan_phase.rb +4 -3
  79. data/lib/killbill/gen/api/plan_phase_specifier.rb +4 -3
  80. data/lib/killbill/gen/api/plan_specifier.rb +4 -3
  81. data/lib/killbill/gen/api/plugin_config_service_api.rb +4 -3
  82. data/lib/killbill/gen/api/plugin_property.rb +4 -3
  83. data/lib/killbill/gen/api/price.rb +4 -3
  84. data/lib/killbill/gen/api/price_list.rb +4 -3
  85. data/lib/killbill/gen/api/price_list_set.rb +4 -3
  86. data/lib/killbill/gen/api/product.rb +4 -3
  87. data/lib/killbill/gen/api/rate.rb +4 -3
  88. data/lib/killbill/gen/api/record_id_api.rb +4 -3
  89. data/lib/killbill/gen/api/recurring.rb +4 -3
  90. data/lib/killbill/gen/api/refund.rb +7 -6
  91. data/lib/killbill/gen/api/require_gen.rb +5 -6
  92. data/lib/killbill/gen/api/rolled_up_usage.rb +4 -3
  93. data/lib/killbill/gen/api/security_api_exception.rb +4 -3
  94. data/lib/killbill/gen/api/static_catalog.rb +4 -3
  95. data/lib/killbill/gen/api/subscription.rb +4 -3
  96. data/lib/killbill/gen/api/subscription_api.rb +4 -3
  97. data/lib/killbill/gen/api/subscription_api_exception.rb +4 -3
  98. data/lib/killbill/gen/api/subscription_bundle.rb +4 -3
  99. data/lib/killbill/gen/api/subscription_bundle_timeline.rb +4 -3
  100. data/lib/killbill/gen/api/subscription_event.rb +4 -3
  101. data/lib/killbill/gen/api/tag.rb +4 -3
  102. data/lib/killbill/gen/api/tag_api_exception.rb +4 -3
  103. data/lib/killbill/gen/api/tag_definition.rb +4 -3
  104. data/lib/killbill/gen/api/tag_definition_api_exception.rb +4 -3
  105. data/lib/killbill/gen/api/tag_user_api.rb +4 -3
  106. data/lib/killbill/gen/api/tenant.rb +4 -3
  107. data/lib/killbill/gen/api/tenant_api_exception.rb +4 -3
  108. data/lib/killbill/gen/api/tenant_context.rb +4 -3
  109. data/lib/killbill/gen/api/tenant_data.rb +4 -3
  110. data/lib/killbill/gen/api/tenant_kv.rb +4 -3
  111. data/lib/killbill/gen/api/tenant_user_api.rb +4 -3
  112. data/lib/killbill/gen/api/tier.rb +4 -3
  113. data/lib/killbill/gen/api/tiered_block.rb +4 -3
  114. data/lib/killbill/gen/api/unit.rb +4 -3
  115. data/lib/killbill/gen/api/usage.rb +4 -3
  116. data/lib/killbill/gen/api/usage_user_api.rb +4 -3
  117. data/lib/killbill/gen/plugin-api/currency_plugin_api.rb +4 -3
  118. data/lib/killbill/gen/plugin-api/ext_bus_event.rb +4 -3
  119. data/lib/killbill/gen/plugin-api/gateway_notification.rb +4 -3
  120. data/lib/killbill/gen/plugin-api/hosted_payment_page_form_descriptor.rb +4 -3
  121. data/lib/killbill/gen/plugin-api/notification_plugin_api.rb +4 -3
  122. data/lib/killbill/gen/plugin-api/payment_method_info_plugin.rb +4 -3
  123. data/lib/killbill/gen/plugin-api/payment_plugin_api.rb +75 -81
  124. data/lib/killbill/gen/plugin-api/payment_plugin_api_exception.rb +4 -3
  125. data/lib/killbill/gen/plugin-api/{payment_info_plugin.rb → payment_transaction_info_plugin.rb} +21 -6
  126. data/lib/killbill/gen/plugin-api/require_gen.rb +5 -5
  127. data/lib/killbill/helpers/active_merchant/active_record/models/payment_method.rb +20 -36
  128. data/lib/killbill/helpers/active_merchant/active_record/models/response.rb +72 -81
  129. data/lib/killbill/helpers/active_merchant/active_record/models/transaction.rb +62 -43
  130. data/lib/killbill/helpers/active_merchant/killbill_spec_helper.rb +0 -13
  131. data/lib/killbill/helpers/active_merchant/payment_plugin.rb +127 -125
  132. data/lib/killbill/http_servlet.rb +16 -1
  133. data/lib/killbill/killbill_api.rb +0 -3
  134. data/lib/killbill/payment.rb +22 -6
  135. data/lib/killbill/rake_task.rb +93 -31
  136. data/spec/killbill/helpers/payment_method_spec.rb +153 -0
  137. data/spec/killbill/helpers/response_spec.rb +58 -15
  138. data/spec/killbill/helpers/test_schema.rb +12 -8
  139. data/spec/killbill/helpers/transaction_spec.rb +134 -0
  140. data/spec/killbill/payment_plugin_api_spec.rb +18 -18
  141. data/spec/killbill/payment_plugin_spec.rb +26 -15
  142. data/spec/killbill/payment_test.rb +6 -7
  143. data/spec/spec_helper.rb +3 -0
  144. metadata +6 -5
  145. data/lib/killbill/gen/api/payment.rb +0 -187
  146. data/lib/killbill/gen/plugin-api/refund_info_plugin.rb +0 -152
@@ -7,27 +7,35 @@ module Killbill
7
7
  class OperationUnsupportedByGatewayError < NotImplementedError
8
8
  end
9
9
 
10
- def process_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
10
+ def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
11
11
  raise OperationUnsupportedByGatewayError
12
12
  end
13
13
 
14
- def get_payment_info(kb_account_id, kb_payment_id, properties, context)
14
+ def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
15
15
  raise OperationUnsupportedByGatewayError
16
16
  end
17
17
 
18
- def search_payments(search_key, offset, limit, properties, context)
18
+ def purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
19
+ raise OperationUnsupportedByGatewayError
20
+ end
21
+
22
+ def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
23
+ raise OperationUnsupportedByGatewayError
24
+ end
25
+
26
+ def credit_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
19
27
  raise OperationUnsupportedByGatewayError
20
28
  end
21
29
 
22
- def process_refund(kb_account_id, kb_payment_id, refund_amount, currency, properties, context)
30
+ def refund_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
23
31
  raise OperationUnsupportedByGatewayError
24
32
  end
25
33
 
26
- def get_refund_info(kb_account_id, kb_payment_id, properties, context)
34
+ def get_payment_info(kb_account_id, kb_payment_id, properties, context)
27
35
  raise OperationUnsupportedByGatewayError
28
36
  end
29
37
 
30
- def search_refunds(search_key, offset, limit, properties, context)
38
+ def search_payments(search_key, offset, limit, properties, context)
31
39
  raise OperationUnsupportedByGatewayError
32
40
  end
33
41
 
@@ -58,6 +66,14 @@ module Killbill
58
66
  def reset_payment_methods(kb_account_id, payment_methods, properties, context)
59
67
  raise OperationUnsupportedByGatewayError
60
68
  end
69
+
70
+ def build_form_descriptor(kb_account_id, descriptor_fields, properties, context)
71
+ raise OperationUnsupportedByGatewayError
72
+ end
73
+
74
+ def process_notification(notification, properties, context)
75
+ raise OperationUnsupportedByGatewayError
76
+ end
61
77
  end
62
78
  end
63
79
  end
@@ -15,14 +15,17 @@ module Killbill
15
15
  opts[:plugin_name], # Plugin name, e.g. 'klogger'
16
16
  opts[:gem_name], # Gem file name, e.g. 'klogger-1.0.0.gem'
17
17
  opts[:gemfile_name] || "Gemfile", # Gemfile name
18
- opts[:gemfile_lock_name] || "Gemfile.lock") # Gemfile.lock name
18
+ opts[:gemfile_lock_name] || "Gemfile.lock", # Gemfile.lock name
19
+ opts[:verbose] || false)
19
20
  .install
20
21
  end
21
22
  end
22
23
 
23
- def initialize(base_name, plugin_name, gem_name, gemfile_name, gemfile_lock_name)
24
+ def initialize(base_name, plugin_name, gem_name, gemfile_name, gemfile_lock_name, verbose)
25
+ @verbose = verbose
26
+
24
27
  @logger = Logger.new(STDOUT)
25
- @logger.level = Logger::INFO
28
+ @logger.level = @verbose ? Logger::DEBUG : Logger::INFO
26
29
 
27
30
  @base_name = base_name
28
31
  @plugin_name = plugin_name
@@ -53,26 +56,30 @@ module Killbill
53
56
  # Rely on the Gemfile definition, if it exists, to get all dependencies
54
57
  # (we assume the Gemfile includes the plugin gemspec, as it should).
55
58
  # Otherwise, use only the plugin gemspec.
56
- @specs ||= @gemfile_definition ? @gemfile_definition.specs : [@plugin_gemspec]
59
+ # When using the Gemfile definition, don't include the :development group -- should this be configurable?
60
+ @specs ||= @gemfile_definition ? @gemfile_definition.specs_for([:default]) : [@plugin_gemspec]
57
61
  end
58
62
 
59
63
  def install
60
64
  namespace :killbill do
61
65
  desc "Validate plugin tree"
62
66
  # The killbill.properties file is required, but not the config.ru one
63
- task :validate => killbill_properties_file do
67
+ task :validate, [:verbose] => killbill_properties_file do |t, args|
68
+ set_verbosity(args)
64
69
  validate
65
70
  end
66
71
 
67
72
  # Build the .tar.gz and .zip packages
68
- task :package => :stage
73
+ task :package, [:verbose] => :stage
69
74
  package_task = Rake::PackageTask.new(name, version) do |p|
70
75
  p.need_tar_gz = true
71
76
  p.need_zip = true
72
77
  end
73
78
 
74
79
  desc "Stage all dependencies"
75
- task :stage => :validate do
80
+ task :stage, [:verbose] => :validate do |t, args|
81
+ set_verbosity(args)
82
+
76
83
  stage_dependencies
77
84
  stage_extra_files
78
85
 
@@ -80,6 +87,32 @@ module Killbill
80
87
  package_task.package_files = Rake::FileList.new("#{@package_dir.basename}/**/*")
81
88
  end
82
89
 
90
+ desc "Deploy the plugin to Kill Bill"
91
+ task :deploy, [:force, :plugin_dir, :verbose] => :stage do |t, args|
92
+ set_verbosity(args)
93
+
94
+ plugins_dir = Pathname.new("#{args.plugin_dir || '/var/tmp/bundles/plugins/ruby'}").expand_path
95
+ mkdir_p plugins_dir, :verbose => @verbose
96
+
97
+ plugin_path = Pathname.new("#{plugins_dir}/#{name}")
98
+ if plugin_path.exist?
99
+ if args.force == "true"
100
+ @logger.info "Deleting previous plugin deployment #{plugin_path}"
101
+ rm_rf plugin_path, :verbose => @verbose
102
+ else
103
+ raise "Cowardly not deleting previous plugin deployment #{plugin_path} - override with rake killbill:deploy[true]"
104
+ end
105
+ end
106
+
107
+ cp_r @package_dir, plugins_dir, :verbose => @verbose
108
+
109
+ Rake::FileList.new("#{@base}/*.yml").each do |config_file|
110
+ config_file_path = Pathname.new("#{plugin_path}/#{version}/#{File.basename(config_file)}").expand_path
111
+ @logger.info "Deploying #{config_file} to #{config_file_path}"
112
+ cp config_file, config_file_path, :verbose => @verbose
113
+ end
114
+ end
115
+
83
116
  desc "List all dependencies"
84
117
  task :dependency => :validate do
85
118
  print_dependencies
@@ -94,8 +127,13 @@ module Killbill
94
127
 
95
128
  private
96
129
 
130
+ def set_verbosity(args)
131
+ return unless args.verbose == 'true'
132
+ @verbose = true
133
+ @logger.level = Logger::DEBUG
134
+ end
135
+
97
136
  def validate
98
- @plugin_gem_file = find_plugin_gem
99
137
  @gemfile_definition = find_gemfile
100
138
  end
101
139
 
@@ -121,21 +159,25 @@ module Killbill
121
159
  Bundler.load_gemspec(spec_path)
122
160
  end
123
161
 
124
- def find_plugin_gem
125
- if @gem_name
126
- # Absolute path?
127
- plugin_gem_file = Pathname.new(@gem_name).expand_path
128
- # Relative path to the base?
129
- plugin_gem_file = @base.join(@gem_name).expand_path unless plugin_gem_file.file?
130
- raise "Unable to find your plugin gem in #{@base}. Did you build it (`rake build')?" unless plugin_gem_file.file?
131
- else
132
- plugin_gem_files = Dir[File.join(@base, "**/#{name}-#{version}.gem")]
162
+ def find_plugin_gem(spec)
163
+ gem_name = spec.file_name
164
+ # spec.loaded_from is the path to the gemspec file
165
+ base = Pathname.new(File.dirname(spec.loaded_from)).expand_path
166
+
167
+ # Try in the base directory first
168
+ plugin_gem_file = Pathname.new(gem_name).expand_path
169
+ plugin_gem_file = base.join(gem_name).expand_path unless plugin_gem_file.file?
170
+
171
+ # Try in subdirectories next
172
+ unless plugin_gem_file.file?
173
+ plugin_gem_files = Dir[File.join(base, "**/#{spec.file_name}")]
133
174
  @logger.debug "Gem candidates found: #{plugin_gem_files}"
134
- raise "Unable to find your plugin gem in #{@base}. Did you build it? (`rake build')" unless plugin_gem_files.size >= 1
135
175
  # Take the first one, assume the other ones are from build directories (e.g. pkg)
136
- plugin_gem_file = plugin_gem_files.first
176
+ plugin_gem_file = Pathname.new(plugin_gem_files.first).expand_path unless plugin_gem_files.empty?
137
177
  end
138
178
 
179
+ raise "Unable to find #{gem_name} in #{base}. Did you build it? (`rake build')" unless plugin_gem_file.file?
180
+
139
181
  @logger.debug "Found #{plugin_gem_file}"
140
182
  Pathname.new(plugin_gem_file).expand_path
141
183
  end
@@ -159,34 +201,54 @@ module Killbill
159
201
 
160
202
  def stage_dependencies
161
203
  # Create the target directory
162
- mkdir_p @target_dir.to_s
204
+ mkdir_p @target_dir.to_s, :verbose => @verbose
163
205
 
164
206
  @logger.debug "Installing all gem dependencies to #{@target_dir}"
165
207
  # We can't simply use Bundler::Installer unfortunately, because we can't tell it to copy the gems for cached ones
166
208
  # (it will default to using Bundler::Source::Path references to the gemspecs on "install").
167
209
  specs.each do |spec|
168
- # For the plugin itself, install it manually (the cache path is likely to be wrong)
169
- next if spec.name == name and spec.version == version
170
- @logger.debug "Staging #{spec.name} (#{spec.version}) from #{spec.cache_file}"
171
- begin
172
- Gem::Installer.new(spec.cache_file, {:force => true, :install_dir => @target_dir}).install
173
- rescue => e
174
- @logger.warn "Unable to stage #{spec.name} (#{spec.version}) from #{spec.cache_file}: #{e}"
210
+ plugin_gem_file = Pathname.new(spec.cache_file).expand_path
211
+ if plugin_gem_file.file?
212
+ @logger.debug "Staging #{spec.name} (#{spec.version}) from #{plugin_gem_file}"
213
+ else
214
+ plugin_gem_file = find_plugin_gem(spec)
215
+ @logger.info "Staging custom gem #{spec.full_name} from #{plugin_gem_file}"
175
216
  end
217
+
218
+ do_install_gem(plugin_gem_file, spec.name, spec.version)
176
219
  end
220
+ end
177
221
 
178
- @logger.debug "Staging #{name} (#{version}) from #{@plugin_gem_file}"
179
- Gem::Installer.new(@plugin_gem_file, {:force => true, :install_dir => @target_dir}).install
222
+ def do_install_gem(path, name, version)
223
+ gem_installer = Gem::Installer.new(path,
224
+ {
225
+ :force => true,
226
+ :install_dir => @target_dir,
227
+ # Should be redundant with the tweaks below
228
+ :development => false,
229
+ :wrappers => true
230
+ })
231
+
232
+ # Tweak the spec file as there are a lot of things we don't care about
233
+ gem_installer.spec.executables = nil
234
+ gem_installer.spec.extensions = nil
235
+ gem_installer.spec.extra_rdoc_files = nil
236
+ gem_installer.spec.test_files = nil
237
+
238
+ gem_installer.install
239
+ rescue => e
240
+ @logger.warn "Unable to stage #{name} (#{version}) from #{path}: #{e}"
241
+ raise e
180
242
  end
181
243
 
182
244
  def stage_extra_files
183
245
  unless killbill_properties_file.nil?
184
246
  @logger.debug "Staging #{killbill_properties_file} to #{@plugin_root_target_dir}"
185
- cp killbill_properties_file, @plugin_root_target_dir
247
+ cp killbill_properties_file, @plugin_root_target_dir, :verbose => @verbose
186
248
  end
187
249
  unless config_ru_file.nil?
188
250
  @logger.debug "Staging #{config_ru_file} to #{@plugin_root_target_dir}"
189
- cp config_ru_file, @plugin_root_target_dir
251
+ cp config_ru_file, @plugin_root_target_dir, :verbose => @verbose
190
252
  end
191
253
  end
192
254
 
@@ -16,6 +16,145 @@ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::PaymentMethod do
16
16
  ::Killbill::Test::TestPaymentMethod.delete_all
17
17
  end
18
18
 
19
+ it 'should construct payment methods correctly' do
20
+ kb_account_id = SecureRandom.uuid
21
+ kb_payment_method_id = SecureRandom.uuid
22
+ kb_tenant_id = SecureRandom.uuid
23
+ response = ::ActiveMerchant::Billing::Response.new(true, nil, {}, {:authorization => SecureRandom.uuid})
24
+ options = {
25
+ :billing_address => {
26
+ :address1 => SecureRandom.uuid,
27
+ :address2 => SecureRandom.uuid,
28
+ :city => SecureRandom.uuid,
29
+ :state => SecureRandom.uuid,
30
+ :zip => SecureRandom.uuid,
31
+ :country => SecureRandom.uuid
32
+ }
33
+ }
34
+ cc = ::ActiveMerchant::Billing::CreditCard.new(
35
+ :first_name => 'Steve',
36
+ :last_name => 'Smith',
37
+ :month => '9',
38
+ :year => '2010',
39
+ :brand => 'visa',
40
+ :number => '4242424242424242'
41
+ )
42
+ token = SecureRandom.uuid
43
+
44
+ # Test storage of CC details
45
+ pm = ::Killbill::Test::TestPaymentMethod.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, cc, response, options, {}, ::Killbill::Test::TestPaymentMethod)
46
+ pm.kb_account_id.should == kb_account_id
47
+ pm.kb_payment_method_id.should == kb_payment_method_id
48
+ pm.kb_tenant_id.should == kb_tenant_id
49
+ pm.token.should == response.authorization
50
+ pm.cc_first_name.should == cc.first_name
51
+ pm.cc_last_name.should == cc.last_name
52
+ pm.cc_type.should == cc.brand
53
+ pm.cc_exp_month.should == cc.month.to_i
54
+ pm.cc_exp_year.should == cc.year.to_i
55
+ pm.cc_last_4.should == cc.last_digits.to_i
56
+ pm.address1.should == options[:billing_address][:address1]
57
+ pm.address2.should == options[:billing_address][:address2]
58
+ pm.city.should == options[:billing_address][:city]
59
+ pm.state.should == options[:billing_address][:state]
60
+ pm.zip.should == options[:billing_address][:zip]
61
+ pm.country.should == options[:billing_address][:country]
62
+ # Verify conversions
63
+ verify_conversion_to_kb_objects(pm, kb_account_id, kb_payment_method_id, response.authorization)
64
+
65
+ # Test storage of CC details with no billing address
66
+ pm = ::Killbill::Test::TestPaymentMethod.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, cc, response, {}, {}, ::Killbill::Test::TestPaymentMethod)
67
+ pm.kb_account_id.should == kb_account_id
68
+ pm.kb_payment_method_id.should == kb_payment_method_id
69
+ pm.kb_tenant_id.should == kb_tenant_id
70
+ pm.token.should == response.authorization
71
+ pm.cc_first_name.should == cc.first_name
72
+ pm.cc_last_name.should == cc.last_name
73
+ pm.cc_type.should == cc.brand
74
+ pm.cc_exp_month.should == cc.month.to_i
75
+ pm.cc_exp_year.should == cc.year.to_i
76
+ pm.cc_last_4.should == cc.last_digits.to_i
77
+ pm.address1.should be_nil
78
+ pm.address2.should be_nil
79
+ pm.city.should be_nil
80
+ pm.state.should be_nil
81
+ pm.zip.should be_nil
82
+ pm.country.should be_nil
83
+ # Verify conversions
84
+ verify_conversion_to_kb_objects(pm, kb_account_id, kb_payment_method_id, response.authorization)
85
+
86
+ # Test storage of token
87
+ pm = ::Killbill::Test::TestPaymentMethod.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, token, response, options, {}, ::Killbill::Test::TestPaymentMethod)
88
+ pm.kb_account_id.should == kb_account_id
89
+ pm.kb_payment_method_id.should == kb_payment_method_id
90
+ pm.kb_tenant_id.should == kb_tenant_id
91
+ pm.token.should == token
92
+ pm.cc_first_name.should be_nil
93
+ pm.cc_last_name.should be_nil
94
+ pm.cc_type.should be_nil
95
+ pm.cc_exp_month.should be_nil
96
+ pm.cc_exp_year.should be_nil
97
+ pm.cc_last_4.should be_nil
98
+ pm.address1.should == options[:billing_address][:address1]
99
+ pm.address2.should == options[:billing_address][:address2]
100
+ pm.city.should == options[:billing_address][:city]
101
+ pm.state.should == options[:billing_address][:state]
102
+ pm.zip.should == options[:billing_address][:zip]
103
+ pm.country.should == options[:billing_address][:country]
104
+ # Verify conversions
105
+ verify_conversion_to_kb_objects(pm, kb_account_id, kb_payment_method_id, token)
106
+
107
+ # Test storage of token with no billing address
108
+ pm = ::Killbill::Test::TestPaymentMethod.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, token, response, {}, {}, ::Killbill::Test::TestPaymentMethod)
109
+ pm.kb_account_id.should == kb_account_id
110
+ pm.kb_payment_method_id.should == kb_payment_method_id
111
+ pm.kb_tenant_id.should == kb_tenant_id
112
+ pm.token.should == token
113
+ pm.cc_first_name.should be_nil
114
+ pm.cc_last_name.should be_nil
115
+ pm.cc_type.should be_nil
116
+ pm.cc_exp_month.should be_nil
117
+ pm.cc_exp_year.should be_nil
118
+ pm.cc_last_4.should be_nil
119
+ pm.address1.should be_nil
120
+ pm.address2.should be_nil
121
+ pm.city.should be_nil
122
+ pm.state.should be_nil
123
+ pm.zip.should be_nil
124
+ pm.country.should be_nil
125
+ # Verify conversions
126
+ verify_conversion_to_kb_objects(pm, kb_account_id, kb_payment_method_id, token)
127
+ end
128
+
129
+ it 'should store and retrieve payment methods correctly' do
130
+ kb_account_id = SecureRandom.uuid
131
+ kb_payment_method_id = SecureRandom.uuid
132
+ kb_tenant_id = SecureRandom.uuid
133
+ response = ::ActiveMerchant::Billing::Response.new(true, nil, {}, {:authorization => SecureRandom.uuid})
134
+ token = SecureRandom.uuid
135
+ pm = ::Killbill::Test::TestPaymentMethod.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, token, response, {}, {}, ::Killbill::Test::TestPaymentMethod)
136
+ pm.save!
137
+
138
+ # Retrieve by account id
139
+ ::Killbill::Test::TestPaymentMethod.from_kb_account_id(kb_account_id, nil).size.should == 0
140
+ ::Killbill::Test::TestPaymentMethod.from_kb_account_id(kb_account_id, SecureRandom.uuid).size.should == 0
141
+ ::Killbill::Test::TestPaymentMethod.from_kb_account_id(SecureRandom.uuid, kb_tenant_id).size.should == 0
142
+ pms = ::Killbill::Test::TestPaymentMethod.from_kb_account_id(kb_account_id, kb_tenant_id)
143
+ pms.size.should == 1
144
+ pms[0].kb_payment_method_id.should == kb_payment_method_id
145
+
146
+ # Retrieve by payment method id
147
+ expect { ::Killbill::Test::TestPaymentMethod.from_kb_payment_method_id(kb_payment_method_id, nil) }.to raise_error
148
+ expect { ::Killbill::Test::TestPaymentMethod.from_kb_payment_method_id(kb_payment_method_id, SecureRandom.uuid) }.to raise_error
149
+ expect { ::Killbill::Test::TestPaymentMethod.from_kb_payment_method_id(SecureRandom.uuid, kb_tenant_id) }.to raise_error
150
+ ::Killbill::Test::TestPaymentMethod.from_kb_payment_method_id(kb_payment_method_id, kb_tenant_id).kb_payment_method_id.should == kb_payment_method_id
151
+
152
+ # Delete the payment method and verify we cannot find it anymore
153
+ ::Killbill::Test::TestPaymentMethod.mark_as_deleted!(kb_payment_method_id, kb_tenant_id)
154
+ ::Killbill::Test::TestPaymentMethod.from_kb_account_id(kb_account_id, kb_tenant_id).size.should == 0
155
+ expect { ::Killbill::Test::TestPaymentMethod.from_kb_payment_method_id(kb_payment_method_id, kb_tenant_id) }.to raise_error
156
+ end
157
+
19
158
  it 'should generate the right SQL query' do
20
159
  # Check count query (search query numeric)
21
160
  expected_query = "SELECT COUNT(DISTINCT \"test_payment_methods\".\"id\") FROM \"test_payment_methods\" WHERE ((((((((((((((\"test_payment_methods\".\"kb_account_id\" = '1234' OR \"test_payment_methods\".\"kb_payment_method_id\" = '1234') OR \"test_payment_methods\".\"token\" = '1234') OR \"test_payment_methods\".\"cc_type\" = '1234') OR \"test_payment_methods\".\"state\" = '1234') OR \"test_payment_methods\".\"zip\" = '1234') OR \"test_payment_methods\".\"cc_first_name\" LIKE '%1234%') OR \"test_payment_methods\".\"cc_last_name\" LIKE '%1234%') OR \"test_payment_methods\".\"address1\" LIKE '%1234%') OR \"test_payment_methods\".\"address2\" LIKE '%1234%') OR \"test_payment_methods\".\"city\" LIKE '%1234%') OR \"test_payment_methods\".\"country\" LIKE '%1234%') OR \"test_payment_methods\".\"cc_exp_month\" = 1234) OR \"test_payment_methods\".\"cc_exp_year\" = 1234) OR \"test_payment_methods\".\"cc_last_4\" = 1234) AND \"test_payment_methods\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_payment_methods\".\"id\""
@@ -100,4 +239,18 @@ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::PaymentMethod do
100
239
  pagination.total_nb_records.should == results.size
101
240
  results
102
241
  end
242
+
243
+ def verify_conversion_to_kb_objects(pm, kb_account_id, kb_payment_method_id, external_payment_method_id)
244
+ # Verify conversion to PaymentMethodPlugin
245
+ pmp = pm.to_payment_method_plugin
246
+ pmp.kb_payment_method_id.should == kb_payment_method_id
247
+ pmp.external_payment_method_id.should == external_payment_method_id
248
+ pmp.properties.size.should == 12
249
+
250
+ # Verify conversion to PaymentMethodInfoPlugin
251
+ pmip = pm.to_payment_method_info_plugin
252
+ pmip.account_id.should == kb_account_id
253
+ pmip.payment_method_id.should == kb_payment_method_id
254
+ pmip.external_payment_method_id.should == external_payment_method_id
255
+ end
103
256
  end
@@ -16,24 +16,74 @@ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::Response do
16
16
  ::Killbill::Test::TestResponse.delete_all
17
17
  end
18
18
 
19
+ it 'should construct responses correctly' do
20
+ api_call = 'for debugging only'
21
+ kb_account_id = SecureRandom.uuid
22
+ kb_payment_id = SecureRandom.uuid
23
+ kb_payment_transaction_id = SecureRandom.uuid
24
+ transaction_type = :PURCHASE
25
+ kb_tenant_id = SecureRandom.uuid
26
+ response = ::ActiveMerchant::Billing::Response.new(true, 'Message', {}, {
27
+ :authorization => SecureRandom.uuid,
28
+ :avs_result => ::ActiveMerchant::Billing::AVSResult.new(:code => 'P')
29
+ })
30
+
31
+ r = ::Killbill::Test::TestResponse.from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id, response, {}, ::Killbill::Test::TestResponse)
32
+ r.api_call.should == api_call
33
+ r.kb_account_id.should ==kb_account_id
34
+ r.kb_payment_id.should ==kb_payment_id
35
+ r.kb_payment_transaction_id.should ==kb_payment_transaction_id
36
+ r.transaction_type.should ==transaction_type
37
+ r.kb_tenant_id.should ==kb_tenant_id
38
+ r.message.should == response.message
39
+ r.authorization.should == response.authorization
40
+ r.fraud_review.should == response.fraud_review?
41
+ r.test.should == response.test
42
+ r.avs_result_code.should == 'P'
43
+ r.avs_result_message.should == 'Postal code matches, but street address not verified.'
44
+ r.avs_result_street_match.should be_nil
45
+ r.avs_result_postal_match.should == 'Y'
46
+ r.cvv_result_code.should be_nil
47
+ r.cvv_result_message.should be_nil
48
+ r.success.should == response.success?
49
+
50
+ # Verify conversion to PaymentTransactionInfoPlugin
51
+ ptip = r.to_transaction_info_plugin
52
+ ptip.kb_payment_id.should == kb_payment_id
53
+ ptip.kb_transaction_payment_id.should == kb_payment_transaction_id
54
+ ptip.transaction_type.should == transaction_type
55
+ # No associated transaction
56
+ ptip.amount.should be_nil
57
+ ptip.currency.should be_nil
58
+ # Row not created
59
+ ptip.created_date.should be_nil
60
+ ptip.effective_date.should be_nil
61
+ ptip.status.should == :PROCESSED
62
+ ptip.gateway_error.should == 'Message'
63
+ ptip.gateway_error_code.should be_nil
64
+ ptip.first_payment_reference_id.should be_nil
65
+ ptip.second_payment_reference_id.should be_nil
66
+ ptip.properties.size.should == 11
67
+ end
68
+
19
69
  it 'should generate the right SQL query' do
20
70
  # Check count query (search query numeric)
21
- expected_query = "SELECT COUNT(DISTINCT \"test_responses\".\"id\") FROM \"test_responses\" WHERE (((\"test_responses\".\"kb_payment_id\" = '1234' OR \"test_responses\".\"message\" = '1234') OR \"test_responses\".\"authorization\" = '1234') OR \"test_responses\".\"fraud_review\" = '1234') AND \"test_responses\".\"api_call\" = 'charge' AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\""
71
+ expected_query = "SELECT COUNT(DISTINCT \"test_responses\".\"id\") FROM \"test_responses\" WHERE ((((\"test_responses\".\"kb_payment_id\" = '1234' OR \"test_responses\".\"kb_payment_transaction_id\" = '1234') OR \"test_responses\".\"message\" = '1234') OR \"test_responses\".\"authorization\" = '1234') OR \"test_responses\".\"fraud_review\" = '1234') AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\""
22
72
  # Note that Kill Bill will pass a String, even for numeric types
23
- ::Killbill::Test::TestResponse.search_query('charge', '1234', '11-22-33').to_sql.should == expected_query
73
+ ::Killbill::Test::TestResponse.search_query('1234', '11-22-33').to_sql.should == expected_query
24
74
 
25
75
  # Check query with results (search query numeric)
26
- expected_query = "SELECT DISTINCT \"test_responses\".* FROM \"test_responses\" WHERE (((\"test_responses\".\"kb_payment_id\" = '1234' OR \"test_responses\".\"message\" = '1234') OR \"test_responses\".\"authorization\" = '1234') OR \"test_responses\".\"fraud_review\" = '1234') AND \"test_responses\".\"api_call\" = 'charge' AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
76
+ expected_query = "SELECT DISTINCT \"test_responses\".* FROM \"test_responses\" WHERE ((((\"test_responses\".\"kb_payment_id\" = '1234' OR \"test_responses\".\"kb_payment_transaction_id\" = '1234') OR \"test_responses\".\"message\" = '1234') OR \"test_responses\".\"authorization\" = '1234') OR \"test_responses\".\"fraud_review\" = '1234') AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
27
77
  # Note that Kill Bill will pass a String, even for numeric types
28
- ::Killbill::Test::TestResponse.search_query('charge', '1234', '11-22-33', 0, 10).to_sql.should == expected_query
78
+ ::Killbill::Test::TestResponse.search_query('1234', '11-22-33', 0, 10).to_sql.should == expected_query
29
79
 
30
80
  # Check count query (search query string)
31
- expected_query = "SELECT COUNT(DISTINCT \"test_responses\".\"id\") FROM \"test_responses\" WHERE (((\"test_responses\".\"kb_payment_id\" = 'XXX' OR \"test_responses\".\"message\" = 'XXX') OR \"test_responses\".\"authorization\" = 'XXX') OR \"test_responses\".\"fraud_review\" = 'XXX') AND \"test_responses\".\"api_call\" = 'charge' AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\""
32
- ::Killbill::Test::TestResponse.search_query('charge', 'XXX', '11-22-33').to_sql.should == expected_query
81
+ expected_query = "SELECT COUNT(DISTINCT \"test_responses\".\"id\") FROM \"test_responses\" WHERE ((((\"test_responses\".\"kb_payment_id\" = 'XXX' OR \"test_responses\".\"kb_payment_transaction_id\" = 'XXX') OR \"test_responses\".\"message\" = 'XXX') OR \"test_responses\".\"authorization\" = 'XXX') OR \"test_responses\".\"fraud_review\" = 'XXX') AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\""
82
+ ::Killbill::Test::TestResponse.search_query('XXX', '11-22-33').to_sql.should == expected_query
33
83
 
34
84
  # Check query with results (search query string)
35
- expected_query = "SELECT DISTINCT \"test_responses\".* FROM \"test_responses\" WHERE (((\"test_responses\".\"kb_payment_id\" = 'XXX' OR \"test_responses\".\"message\" = 'XXX') OR \"test_responses\".\"authorization\" = 'XXX') OR \"test_responses\".\"fraud_review\" = 'XXX') AND \"test_responses\".\"api_call\" = 'charge' AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
36
- ::Killbill::Test::TestResponse.search_query('charge', 'XXX', '11-22-33', 0, 10).to_sql.should == expected_query
85
+ expected_query = "SELECT DISTINCT \"test_responses\".* FROM \"test_responses\" WHERE ((((\"test_responses\".\"kb_payment_id\" = 'XXX' OR \"test_responses\".\"kb_payment_transaction_id\" = 'XXX') OR \"test_responses\".\"message\" = 'XXX') OR \"test_responses\".\"authorization\" = 'XXX') OR \"test_responses\".\"fraud_review\" = 'XXX') AND \"test_responses\".\"success\" = 't' AND \"test_responses\".\"kb_tenant_id\" = '11-22-33' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
86
+ ::Killbill::Test::TestResponse.search_query('XXX', '11-22-33', 0, 10).to_sql.should == expected_query
37
87
  end
38
88
 
39
89
  it 'should search all fields' do
@@ -45,13 +95,6 @@ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::Response do
45
95
  :kb_tenant_id => '11-22-33',
46
96
  :success => true
47
97
 
48
- # Wrong api_call
49
- ignored1 = ::Killbill::Test::TestResponse.create :api_call => 'add_payment_method',
50
- :kb_account_id => '55-66-77-88',
51
- :kb_payment_id => pm.kb_payment_id,
52
- :kb_tenant_id => '11-22-33',
53
- :success => true
54
-
55
98
  # Not successful
56
99
  ignored2 = ::Killbill::Test::TestResponse.create :api_call => 'charge',
57
100
  :kb_account_id => '55-66-77-88',