killbill 3.0.0 → 3.1.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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Jarfile +5 -5
  4. data/NEWS +4 -0
  5. data/README.md +45 -8
  6. data/VERSION +1 -1
  7. data/generators/active_merchant/active_merchant_generator.rb +38 -0
  8. data/generators/active_merchant/templates/.gitignore.rb +36 -0
  9. data/generators/active_merchant/templates/.travis.yml.rb +19 -0
  10. data/generators/active_merchant/templates/Gemfile.rb +3 -0
  11. data/generators/active_merchant/templates/Jarfile.rb +6 -0
  12. data/generators/active_merchant/templates/LICENSE.rb +201 -0
  13. data/generators/active_merchant/templates/NEWS.rb +2 -0
  14. data/generators/active_merchant/templates/Rakefile.rb +30 -0
  15. data/generators/active_merchant/templates/VERSION.rb +1 -0
  16. data/generators/active_merchant/templates/config.ru.rb +4 -0
  17. data/generators/active_merchant/templates/config.yml.rb +13 -0
  18. data/generators/active_merchant/templates/db/ddl.sql.rb +64 -0
  19. data/generators/active_merchant/templates/db/schema.rb +64 -0
  20. data/generators/active_merchant/templates/killbill.properties.rb +3 -0
  21. data/generators/active_merchant/templates/lib/api.rb +119 -0
  22. data/generators/active_merchant/templates/lib/application.rb +84 -0
  23. data/generators/active_merchant/templates/lib/models/payment_method.rb +22 -0
  24. data/generators/active_merchant/templates/lib/models/response.rb +22 -0
  25. data/generators/active_merchant/templates/lib/models/transaction.rb +11 -0
  26. data/generators/active_merchant/templates/lib/plugin.rb +23 -0
  27. data/generators/active_merchant/templates/lib/private_api.rb +6 -0
  28. data/generators/active_merchant/templates/lib/views/form.erb +8 -0
  29. data/generators/active_merchant/templates/plugin.gemspec.rb +48 -0
  30. data/generators/active_merchant/templates/pom.xml.rb +44 -0
  31. data/generators/active_merchant/templates/release.sh.rb +41 -0
  32. data/generators/active_merchant/templates/spec/base_plugin_spec.rb +30 -0
  33. data/generators/active_merchant/templates/spec/integration_spec.rb +31 -0
  34. data/generators/active_merchant/templates/spec/spec_helper.rb +24 -0
  35. data/generators/killbill_generator.rb +38 -0
  36. data/killbill.gemspec +10 -2
  37. data/lib/killbill/gen/api/block.rb +82 -0
  38. data/lib/killbill/gen/api/direct_payment.rb +176 -0
  39. data/lib/killbill/gen/api/direct_payment_api.rb +329 -0
  40. data/lib/killbill/gen/api/direct_payment_transaction.rb +156 -0
  41. data/lib/killbill/gen/api/fixed.rb +63 -0
  42. data/lib/killbill/gen/api/invoice_item.rb +7 -1
  43. data/lib/killbill/gen/api/invoice_item_formatter.rb +7 -1
  44. data/lib/killbill/gen/api/invoice_user_api.rb +18 -136
  45. data/lib/killbill/gen/api/migration_plan.rb +6 -6
  46. data/lib/killbill/gen/api/payment_api.rb +216 -54
  47. data/lib/killbill/gen/api/payment_method_plugin.rb +3 -3
  48. data/lib/killbill/gen/api/plan.rb +6 -6
  49. data/lib/killbill/gen/api/plan_phase.rb +16 -23
  50. data/lib/killbill/gen/api/plugin_property.rb +71 -0
  51. data/lib/killbill/gen/api/recurring.rb +63 -0
  52. data/lib/killbill/gen/api/require_gen.rb +10 -1
  53. data/lib/killbill/gen/api/static_catalog.rb +8 -1
  54. data/lib/killbill/gen/api/tier.rb +77 -0
  55. data/lib/killbill/gen/api/tiered_block.rb +88 -0
  56. data/lib/killbill/gen/api/usage.rb +111 -0
  57. data/lib/killbill/gen/api/usage_user_api.rb +59 -3
  58. data/lib/killbill/gen/plugin-api/billing_address.rb +85 -0
  59. data/lib/killbill/gen/plugin-api/customer.rb +73 -0
  60. data/lib/killbill/gen/plugin-api/hosted_payment_page_descriptor_fields.rb +145 -0
  61. data/lib/killbill/gen/plugin-api/hosted_payment_page_form_descriptor.rb +80 -0
  62. data/lib/killbill/gen/plugin-api/hosted_payment_page_notification.rb +129 -0
  63. data/lib/killbill/gen/plugin-api/payment_info_plugin.rb +20 -1
  64. data/lib/killbill/gen/plugin-api/payment_plugin_api.rb +358 -39
  65. data/lib/killbill/gen/plugin-api/refund_info_plugin.rb +20 -1
  66. data/lib/killbill/gen/plugin-api/require_gen.rb +3 -0
  67. data/lib/killbill/helpers/active_merchant.rb +21 -0
  68. data/lib/killbill/helpers/active_merchant/active_record.rb +17 -0
  69. data/lib/killbill/helpers/active_merchant/active_record/models/helpers.rb +25 -0
  70. data/lib/killbill/helpers/active_merchant/active_record/models/payment_method.rb +195 -0
  71. data/lib/killbill/helpers/active_merchant/active_record/models/response.rb +178 -0
  72. data/lib/killbill/helpers/active_merchant/active_record/models/streamy_result_set.rb +35 -0
  73. data/lib/killbill/helpers/active_merchant/active_record/models/transaction.rb +63 -0
  74. data/lib/killbill/helpers/active_merchant/configuration.rb +54 -0
  75. data/lib/killbill/helpers/active_merchant/core_ext.rb +41 -0
  76. data/lib/killbill/helpers/active_merchant/gateway.rb +35 -0
  77. data/lib/killbill/helpers/active_merchant/killbill_spec_helper.rb +117 -0
  78. data/lib/killbill/helpers/active_merchant/payment_plugin.rb +365 -0
  79. data/lib/killbill/helpers/active_merchant/private_payment_plugin.rb +119 -0
  80. data/lib/killbill/helpers/active_merchant/properties.rb +20 -0
  81. data/lib/killbill/helpers/active_merchant/sinatra.rb +30 -0
  82. data/lib/killbill/helpers/active_merchant/utils.rb +23 -0
  83. data/lib/killbill/payment.rb +22 -10
  84. data/script/generate +15 -0
  85. data/spec/killbill/helpers/payment_method_spec.rb +101 -0
  86. data/spec/killbill/helpers/response_spec.rb +74 -0
  87. data/spec/killbill/helpers/test_schema.rb +57 -0
  88. data/spec/killbill/helpers/utils_spec.rb +22 -0
  89. data/spec/killbill/payment_plugin_api_spec.rb +23 -18
  90. data/spec/killbill/payment_plugin_spec.rb +11 -10
  91. data/spec/killbill/payment_test.rb +9 -9
  92. data/spec/spec_helper.rb +8 -3
  93. metadata +130 -5
@@ -0,0 +1,119 @@
1
+ module Killbill
2
+ module Plugin
3
+ module ActiveMerchant
4
+ require 'action_controller'
5
+ require 'action_view'
6
+ require 'active_support'
7
+ require 'cgi'
8
+
9
+ class PrivatePaymentPlugin < ::Killbill::Plugin::Payment
10
+
11
+ # Implicit dependencies for form_tag helpers
12
+ include ::ActiveSupport::Configurable
13
+ include ::ActionController::RequestForgeryProtection
14
+ include ::ActionView::Context
15
+ include ::ActionView::Helpers::FormTagHelper
16
+ include ::ActiveMerchant::Billing::Integrations::ActionViewHelper
17
+
18
+ # For RequestForgeryProtection
19
+ attr_reader :session
20
+
21
+ def initialize(identifier, payment_method_model, transaction_model, response_model, session = {})
22
+ @identifier = identifier
23
+ @payment_method_model = payment_method_model
24
+ @transaction_model = transaction_model
25
+ @response_model = response_model
26
+
27
+ @session = session
28
+ reset_output_buffer
29
+ end
30
+
31
+ # Valid options: :amount, :currency, :test, :credential2, :credential3, :credential4, :country, :account_name,
32
+ # :transaction_type, :authcode, :notify_url, :return_url, :redirect_param, :forward_url
33
+ #
34
+ # Additionally, you can have a :html key which will be passed through to the link_to helper
35
+ def payment_link_for(name, order_id, account_id, service, options = {})
36
+ integration_module = ::ActiveMerchant::Billing::Integrations.const_get(service.to_s.camelize)
37
+ service_class = integration_module.const_get('Helper')
38
+
39
+ link_options = options.delete(:html) || {}
40
+ service = service_class.new(order_id, account_id, options)
41
+
42
+ service_url = service.respond_to?(:credential_based_url) ? service.credential_based_url : integration_module.service_url
43
+
44
+ # Hack for QIWI which requires 'id' to be the first query parameter...
45
+ params = service.form_fields
46
+ order_key = service.mappings[:order]
47
+ url = service_url + '?' + "#{CGI.escape(order_key.to_param)}=#{CGI.escape(params[order_key].to_s)}"
48
+ params.delete order_key
49
+ url += '&' + params.to_query
50
+
51
+ # service.form_fields are query parameters
52
+ link_to name, url, link_options.merge(service.form_fields)
53
+ end
54
+
55
+ # Valid options: :amount, :currency, :test, :credential2, :credential3, :credential4, :country, :account_name,
56
+ # :transaction_type, :authcode, :notify_url, :return_url, :redirect_param, :forward_url
57
+ #
58
+ # Additionally, you can have a :html key which will be passed through to the form_tag helper
59
+ def payment_form_for(order_id, account_id, service, options = {}, &proc)
60
+ # For ActiveMerchant routing
61
+ options[:service] = service
62
+
63
+ options[:html] ||= {}
64
+ options[:html][:disable_authenticity_token] ||= true
65
+ options[:html][:enforce_utf8] ||= false
66
+
67
+ payment_service_for(order_id, account_id, options, &proc)
68
+
69
+ output_buffer
70
+ end
71
+
72
+ protected
73
+
74
+ def reset_output_buffer
75
+ @output_buffer = ''
76
+ end
77
+
78
+ def save_response(response, api_call)
79
+ save_response_and_transaction(response, api_call)[0]
80
+ end
81
+
82
+ def save_response_and_transaction(response, api_call, kb_payment_id=nil, amount_in_cents=0, currency=nil)
83
+ logger.warn "Unsuccessful #{api_call}: #{response.message}" unless response.success?
84
+
85
+ # Save the response to our logs
86
+ response = @response_model.from_response(api_call, kb_payment_id, response)
87
+ response.save!
88
+
89
+ transaction = nil
90
+ txn_id = response.txn_id
91
+ if response.success and !kb_payment_id.blank? and !txn_id.blank?
92
+ # Record the transaction
93
+ transaction = response.send("create_#{@identifier}_transaction!",
94
+ :amount_in_cents => amount_in_cents,
95
+ :currency => currency,
96
+ :api_call => api_call,
97
+ :kb_payment_id => kb_payment_id,
98
+ :txn_id => txn_id)
99
+
100
+ logger.debug "Recorded transaction: #{transaction.inspect}"
101
+ end
102
+ return response, transaction
103
+ end
104
+
105
+ def kb_apis
106
+ ::Killbill::Plugin::ActiveMerchant.kb_apis
107
+ end
108
+
109
+ def gateway
110
+ ::Killbill::Plugin::ActiveMerchant.gateway
111
+ end
112
+
113
+ def logger
114
+ ::Killbill::Plugin::ActiveMerchant.logger
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,20 @@
1
+ module Killbill
2
+ module Plugin
3
+ module ActiveMerchant
4
+ class Properties
5
+ def initialize(file)
6
+ @config_file = Pathname.new(file).expand_path
7
+ end
8
+
9
+ def parse!
10
+ raise "#{@config_file} is not a valid file" unless @config_file.file?
11
+ @config = YAML.load_file(@config_file.to_s)
12
+ end
13
+
14
+ def [](key)
15
+ @config[key]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ module Killbill
2
+ module Plugin
3
+ module ActiveMerchant
4
+ module Sinatra
5
+ enable :sessions
6
+
7
+ include ::ActionView::Helpers::FormTagHelper
8
+
9
+ helpers do
10
+ def config
11
+ ::Killbill::Plugin::ActiveMerchant.config
12
+ end
13
+
14
+ def logger
15
+ ::Killbill::Plugin::ActiveMerchant.logger
16
+ end
17
+
18
+ def required_parameter!(parameter_name, parameter_value, message='must be specified!')
19
+ halt 400, "#{parameter_name} #{message}" if parameter_value.blank?
20
+ end
21
+ end
22
+
23
+ after do
24
+ # return DB connections to the Pool if required
25
+ ::ActiveRecord::Base.connection.close
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ module Killbill
2
+ module Plugin
3
+ module ActiveMerchant
4
+ class Utils
5
+ # Use base 62 to be safe
6
+ BASE62 = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a
7
+
8
+ def self.compact_uuid(uuid)
9
+ uuid = uuid.gsub(/-/, '')
10
+ uuid.hex.base(62).map{ |i| BASE62[i].chr } * ''
11
+ end
12
+
13
+ def self.unpack_uuid(base62_uuid)
14
+ as_hex = base62_uuid.split(//).inject(0) { |i,e| i*62 + BASE62.index(e[0]) }
15
+ no_hyphens = "%x" % as_hex
16
+ no_hyphens = '0' * (32 - no_hyphens.size) + no_hyphens
17
+ no_hyphens.insert(8, "-").insert(13, "-").insert(18, "-").insert(23, "-")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -7,43 +7,55 @@ 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_in_cents, currency, call_context, options = {})
10
+ def process_payment(kb_account_id, kb_payment_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, tenant_context, options = {})
14
+ def get_payment_info(kb_account_id, kb_payment_id, properties, context)
15
15
  raise OperationUnsupportedByGatewayError
16
16
  end
17
17
 
18
- def process_refund(kb_account_id, kb_payment_id, amount_in_cents, currency, call_context, options = {})
18
+ def search_payments(search_key, offset, limit, properties, context)
19
19
  raise OperationUnsupportedByGatewayError
20
20
  end
21
21
 
22
- def get_refund_info(kb_account_id, kb_payment_id, tenant_context, options = {})
22
+ def process_refund(kb_account_id, kb_payment_id, refund_amount, currency, properties, context)
23
23
  raise OperationUnsupportedByGatewayError
24
24
  end
25
25
 
26
- def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, call_context, options = {})
26
+ def get_refund_info(kb_account_id, kb_payment_id, properties, context)
27
27
  raise OperationUnsupportedByGatewayError
28
28
  end
29
29
 
30
- def delete_payment_method(kb_account_id, kb_payment_method_id, call_context, options = {})
30
+ def search_refunds(search_key, offset, limit, properties, context)
31
31
  raise OperationUnsupportedByGatewayError
32
32
  end
33
33
 
34
- def get_payment_method_detail(kb_account_id, kb_payment_method_id, tenant_context, options = {})
34
+ def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
35
35
  raise OperationUnsupportedByGatewayError
36
36
  end
37
37
 
38
- def set_default_payment_method(kb_account_id, kb_payment_method_id, call_context, options = {})
38
+ def delete_payment_method(kb_account_id, kb_payment_method_id, properties, context)
39
39
  raise OperationUnsupportedByGatewayError
40
40
  end
41
41
 
42
- def get_payment_methods(kb_account_id, refresh_from_gateway, call_context, options = {})
42
+ def get_payment_method_detail(kb_account_id, kb_payment_method_id, properties, context)
43
43
  raise OperationUnsupportedByGatewayError
44
44
  end
45
45
 
46
- def reset_payment_methods(kb_account_id, payment_methods)
46
+ def set_default_payment_method(kb_account_id, kb_payment_method_id, properties, context)
47
+ raise OperationUnsupportedByGatewayError
48
+ end
49
+
50
+ def get_payment_methods(kb_account_id, refresh_from_gateway, properties, context)
51
+ raise OperationUnsupportedByGatewayError
52
+ end
53
+
54
+ def search_payment_methods(search_key, offset, limit, properties, context)
55
+ raise OperationUnsupportedByGatewayError
56
+ end
57
+
58
+ def reset_payment_methods(kb_account_id, payment_methods, properties)
47
59
  raise OperationUnsupportedByGatewayError
48
60
  end
49
61
  end
data/script/generate ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'thor'
4
+
5
+ require File.expand_path('../../generators/killbill_generator', __FILE__)
6
+
7
+ Dir[File.expand_path('../..', __FILE__) + '/generators/*/*.rb'].each do |generator|
8
+ require generator
9
+ end
10
+
11
+ class Generate < Thor
12
+ register(ActiveMerchantGenerator, 'active_merchant', 'active_merchant NAME DIR', 'Generates a new active_merchant plugin for Kill Bill.')
13
+ end
14
+
15
+ Generate.start
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ module Killbill #:nodoc:
4
+ module Test #:nodoc:
5
+ class TestPaymentMethod < ::Killbill::Plugin::ActiveMerchant::ActiveRecord::PaymentMethod
6
+
7
+ self.table_name = 'test_payment_methods'
8
+
9
+ end
10
+ end
11
+ end
12
+
13
+ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::PaymentMethod do
14
+
15
+ before :all do
16
+ ::Killbill::Test::TestPaymentMethod.delete_all
17
+ end
18
+
19
+ it 'should generate the right SQL query' do
20
+ # Check count query (search query numeric)
21
+ 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) ORDER BY \"test_payment_methods\".\"id\""
22
+ # Note that Kill Bill will pass a String, even for numeric types
23
+ ::Killbill::Test::TestPaymentMethod.search_query('1234').to_sql.should == expected_query
24
+
25
+ # Check query with results (search query numeric)
26
+ expected_query = "SELECT DISTINCT \"test_payment_methods\".* 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) ORDER BY \"test_payment_methods\".\"id\" LIMIT 10 OFFSET 0"
27
+ # Note that Kill Bill will pass a String, even for numeric types
28
+ ::Killbill::Test::TestPaymentMethod.search_query('1234', 0, 10).to_sql.should == expected_query
29
+
30
+ # Check count query (search query string)
31
+ expected_query = "SELECT COUNT(DISTINCT \"test_payment_methods\".\"id\") FROM \"test_payment_methods\" WHERE (((((((((((\"test_payment_methods\".\"kb_account_id\" = 'XXX' OR \"test_payment_methods\".\"kb_payment_method_id\" = 'XXX') OR \"test_payment_methods\".\"token\" = 'XXX') OR \"test_payment_methods\".\"cc_type\" = 'XXX') OR \"test_payment_methods\".\"state\" = 'XXX') OR \"test_payment_methods\".\"zip\" = 'XXX') OR \"test_payment_methods\".\"cc_first_name\" LIKE '%XXX%') OR \"test_payment_methods\".\"cc_last_name\" LIKE '%XXX%') OR \"test_payment_methods\".\"address1\" LIKE '%XXX%') OR \"test_payment_methods\".\"address2\" LIKE '%XXX%') OR \"test_payment_methods\".\"city\" LIKE '%XXX%') OR \"test_payment_methods\".\"country\" LIKE '%XXX%') ORDER BY \"test_payment_methods\".\"id\""
32
+ ::Killbill::Test::TestPaymentMethod.search_query('XXX').to_sql.should == expected_query
33
+
34
+ # Check query with results (search query string)
35
+ expected_query = "SELECT DISTINCT \"test_payment_methods\".* FROM \"test_payment_methods\" WHERE (((((((((((\"test_payment_methods\".\"kb_account_id\" = 'XXX' OR \"test_payment_methods\".\"kb_payment_method_id\" = 'XXX') OR \"test_payment_methods\".\"token\" = 'XXX') OR \"test_payment_methods\".\"cc_type\" = 'XXX') OR \"test_payment_methods\".\"state\" = 'XXX') OR \"test_payment_methods\".\"zip\" = 'XXX') OR \"test_payment_methods\".\"cc_first_name\" LIKE '%XXX%') OR \"test_payment_methods\".\"cc_last_name\" LIKE '%XXX%') OR \"test_payment_methods\".\"address1\" LIKE '%XXX%') OR \"test_payment_methods\".\"address2\" LIKE '%XXX%') OR \"test_payment_methods\".\"city\" LIKE '%XXX%') OR \"test_payment_methods\".\"country\" LIKE '%XXX%') ORDER BY \"test_payment_methods\".\"id\" LIMIT 10 OFFSET 0"
36
+ ::Killbill::Test::TestPaymentMethod.search_query('XXX', 0, 10).to_sql.should == expected_query
37
+ end
38
+
39
+ it 'should search all fields' do
40
+ do_search('foo').size.should == 0
41
+
42
+ pm = ::Killbill::Test::TestPaymentMethod.create :kb_account_id => '11-22-33-44',
43
+ :kb_payment_method_id => '55-66-77-88',
44
+ :cc_first_name => 'ccFirstName',
45
+ :cc_last_name => 'ccLastName',
46
+ :cc_type => 'ccType',
47
+ :cc_exp_month => 10,
48
+ :cc_exp_year => 11,
49
+ :cc_last_4 => 1234,
50
+ :address1 => 'address1',
51
+ :address2 => 'address2',
52
+ :city => 'city',
53
+ :state => 'state',
54
+ :zip => 'zip',
55
+ :country => 'country'
56
+
57
+ do_search('foo').size.should == 0
58
+ do_search('ccType').size.should == 1
59
+ # Exact match only for cc_last_4
60
+ do_search('123').size.should == 0
61
+ do_search('1234').size.should == 1
62
+ # Test partial match
63
+ do_search('address').size.should == 1
64
+ do_search('Name').size.should == 1
65
+
66
+ pm2 = ::Killbill::Test::TestPaymentMethod.create :kb_account_id => '22-33-44-55',
67
+ :kb_payment_method_id => '66-77-88-99',
68
+ :cc_first_name => 'ccFirstName',
69
+ :cc_last_name => 'ccLastName',
70
+ :cc_type => 'ccType',
71
+ :cc_exp_month => 10,
72
+ :cc_exp_year => 11,
73
+ :cc_last_4 => 1234,
74
+ :address1 => 'address1',
75
+ :address2 => 'address2',
76
+ :city => 'city',
77
+ :state => 'state',
78
+ :zip => 'zip',
79
+ :country => 'country'
80
+
81
+ do_search('foo').size.should == 0
82
+ do_search('ccType').size.should == 2
83
+ # Exact match only for cc_last_4
84
+ do_search('123').size.should == 0
85
+ do_search('1234').size.should == 2
86
+ # Test partial match
87
+ do_search('cc').size.should == 2
88
+ do_search('address').size.should == 2
89
+ do_search('Name').size.should == 2
90
+ end
91
+
92
+ private
93
+
94
+ def do_search(search_key)
95
+ pagination = ::Killbill::Test::TestPaymentMethod.search(search_key)
96
+ pagination.current_offset.should == 0
97
+ results = pagination.iterator.to_a
98
+ pagination.total_nb_records.should == results.size
99
+ results
100
+ end
101
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ module Killbill #:nodoc:
4
+ module Test #:nodoc:
5
+ class TestResponse < ::Killbill::Plugin::ActiveMerchant::ActiveRecord::Response
6
+
7
+ self.table_name = 'test_responses'
8
+
9
+ end
10
+ end
11
+ end
12
+
13
+ describe Killbill::Plugin::ActiveMerchant::ActiveRecord::Response do
14
+
15
+ before :all do
16
+ ::Killbill::Test::TestResponse.delete_all
17
+ end
18
+
19
+ it 'should generate the right SQL query' do
20
+ # 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' ORDER BY \"test_responses\".\"id\""
22
+ # Note that Kill Bill will pass a String, even for numeric types
23
+ ::Killbill::Test::TestResponse.search_query('charge', '1234').to_sql.should == expected_query
24
+
25
+ # 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' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
27
+ # Note that Kill Bill will pass a String, even for numeric types
28
+ ::Killbill::Test::TestResponse.search_query('charge', '1234', 0, 10).to_sql.should == expected_query
29
+
30
+ # 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' ORDER BY \"test_responses\".\"id\""
32
+ ::Killbill::Test::TestResponse.search_query('charge', 'XXX').to_sql.should == expected_query
33
+
34
+ # 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' ORDER BY \"test_responses\".\"id\" LIMIT 10 OFFSET 0"
36
+ ::Killbill::Test::TestResponse.search_query('charge', 'XXX', 0, 10).to_sql.should == expected_query
37
+ end
38
+
39
+ it 'should search all fields' do
40
+ do_search('foo').size.should == 0
41
+
42
+ pm = ::Killbill::Test::TestResponse.create :api_call => 'charge',
43
+ :kb_payment_id => '11-22-33-44',
44
+ :success => true
45
+
46
+ # Wrong api_call
47
+ ignored1 = ::Killbill::Test::TestResponse.create :api_call => 'add_payment_method',
48
+ :kb_payment_id => pm.kb_payment_id,
49
+ :success => true
50
+
51
+ # Not successful
52
+ ignored2 = ::Killbill::Test::TestResponse.create :api_call => 'charge',
53
+ :kb_payment_id => pm.kb_payment_id,
54
+ :success => false
55
+
56
+ do_search(pm.kb_payment_id).size.should == 1
57
+
58
+ pm2 = ::Killbill::Test::TestResponse.create :api_call => 'charge',
59
+ :kb_payment_id => pm.kb_payment_id,
60
+ :success => true
61
+
62
+ do_search(pm.kb_payment_id).size.should == 2
63
+ end
64
+
65
+ private
66
+
67
+ def do_search(search_key)
68
+ pagination = ::Killbill::Test::TestResponse.search(search_key)
69
+ pagination.current_offset.should == 0
70
+ results = pagination.iterator.to_a
71
+ pagination.total_nb_records.should == results.size
72
+ results
73
+ end
74
+ end