killbill 3.1.7 → 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS +7 -0
- data/Rakefile +16 -3
- data/VERSION +1 -1
- data/generators/active_merchant/templates/db/ddl.sql.rb +3 -3
- data/generators/active_merchant/templates/db/schema.rb +3 -2
- data/generators/active_merchant/templates/lib/models/payment_method.rb +2 -2
- data/generators/active_merchant/templates/plugin.gemspec.rb +1 -1
- data/killbill.gemspec +5 -1
- data/lib/killbill/ext/active_merchant/typhoeus_connection.rb +82 -0
- data/lib/killbill/helpers/active_merchant/active_record/models/response.rb +3 -3
- data/lib/killbill/helpers/active_merchant/configuration.rb +7 -1
- data/lib/killbill/helpers/active_merchant/gateway.rb +11 -2
- data/lib/killbill/helpers/active_merchant/payment_plugin.rb +15 -7
- data/spec/killbill/helpers/payment_plugin_spec.rb +115 -0
- data/spec/killbill/helpers/test_schema.rb +2 -2
- data/spec/killbill/payment_plugin_spec.rb +3 -4
- data/spec/killbill/remote/active_merchant_typhoeus_connection_spec.rb +53 -0
- data/spec/spec_helper.rb +3 -0
- metadata +63 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1564801f1c0cf35922d6784c77c6bad9a0e16cb0
|
4
|
+
data.tar.gz: f3f0d953fb91af7b5bf848ed44bad0d12f485c0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 287c4cbadcce9715807704728cc7a718e521bf4ec2ef807749c81a036b381a8ed680ccb21aa4d6c280cb93dfd4be369426534ff11bd35b87a2bd71060435adb3
|
7
|
+
data.tar.gz: 22c5ca459cf77f5e096f76688c5fb0283076255a641ef2259be3c52e71dc8d7bdca31a6f8ea6ca11a7e25bd310460091cbd2d002ab4a3ba9e51080b72fc4de35
|
data/NEWS
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
3.1.8
|
2
|
+
Make ActiveMerchant HTTP backend configurable, add support for Typhoeus
|
3
|
+
generator:
|
4
|
+
- Remove transactions.txn_id, transactions.amount_in_cents and transactions.currency NOT NULL constraint
|
5
|
+
- Update PaymentMethod.from_response signature
|
6
|
+
- Add :skip_gw option to skip the gateway entirely
|
7
|
+
|
1
8
|
3.1.7
|
2
9
|
Support more Logger APIs
|
3
10
|
|
data/Rakefile
CHANGED
@@ -6,8 +6,21 @@ Bundler::GemHelper.install_tasks
|
|
6
6
|
|
7
7
|
# Install test tasks
|
8
8
|
require 'rspec/core/rake_task'
|
9
|
-
|
10
|
-
RSpec
|
9
|
+
namespace :test do
|
10
|
+
desc 'Run RSpec tests'
|
11
|
+
RSpec::Core::RakeTask.new do |task|
|
12
|
+
task.name = 'spec'
|
13
|
+
task.pattern = './spec/*/{,helpers/}*_spec.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :remote do
|
17
|
+
desc 'Run RSpec remote tests'
|
18
|
+
RSpec::Core::RakeTask.new do |task|
|
19
|
+
task.name = 'spec'
|
20
|
+
task.pattern = './spec/*/remote/*_spec.rb'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
11
24
|
|
12
25
|
# Run tests by default
|
13
|
-
task :default => :spec
|
26
|
+
task :default => 'test:spec'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.8
|
@@ -37,9 +37,9 @@ CREATE TABLE `<%= identifier %>_transactions` (
|
|
37
37
|
`kb_payment_id` varchar(255) NOT NULL,
|
38
38
|
`kb_payment_transaction_id` varchar(255) NOT NULL,
|
39
39
|
`transaction_type` varchar(255) NOT NULL,
|
40
|
-
`txn_id` varchar(255)
|
41
|
-
`amount_in_cents` int(11)
|
42
|
-
`currency` varchar(255)
|
40
|
+
`txn_id` varchar(255) DEFAULT NULL,
|
41
|
+
`amount_in_cents` int(11) DEFAULT NULL,
|
42
|
+
`currency` varchar(255) DEFAULT NULL,
|
43
43
|
`created_at` datetime NOT NULL,
|
44
44
|
`updated_at` datetime NOT NULL,
|
45
45
|
`kb_account_id` varchar(255) NOT NULL,
|
@@ -39,8 +39,9 @@ ActiveRecord::Schema.define(:version => 20140410153635) do
|
|
39
39
|
t.string "kb_payment_transaction_id", :null => false
|
40
40
|
t.string "transaction_type", :null => false
|
41
41
|
t.string "txn_id" # <%= identifier %> transaction id
|
42
|
-
|
43
|
-
t.
|
42
|
+
# Both null for void
|
43
|
+
t.integer "amount_in_cents"
|
44
|
+
t.string "currency"
|
44
45
|
t.datetime "created_at", :null => false
|
45
46
|
t.datetime "updated_at", :null => false
|
46
47
|
t.string "kb_account_id", :null => false
|
@@ -4,7 +4,7 @@ module Killbill #:nodoc:
|
|
4
4
|
|
5
5
|
self.table_name = '<%= identifier %>_payment_methods'
|
6
6
|
|
7
|
-
def self.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, cc_or_token, response, options, extra_params = {})
|
7
|
+
def self.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, cc_or_token, response, options, extra_params = {}, model = ::Killbill::<%= class_name %>::<%= class_name %>PaymentMethod)
|
8
8
|
super(kb_account_id,
|
9
9
|
kb_payment_method_id,
|
10
10
|
kb_tenant_id,
|
@@ -16,7 +16,7 @@ module Killbill #:nodoc:
|
|
16
16
|
#:params_id => extract(response, 'id'),
|
17
17
|
#:params_card_id => extract(response, 'card', 'id')
|
18
18
|
}.merge!(extra_params),
|
19
|
-
|
19
|
+
model)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.rdoc_options << '--exclude' << '.'
|
24
24
|
|
25
|
-
s.add_dependency 'killbill', '~> 3.1.
|
25
|
+
s.add_dependency 'killbill', '~> 3.1.8'
|
26
26
|
s.add_dependency 'activemerchant', '~> 1.42.9'
|
27
27
|
s.add_dependency 'activerecord', '~> 4.1.0'
|
28
28
|
s.add_dependency 'actionpack', '~> 4.1.0'
|
data/killbill.gemspec
CHANGED
@@ -17,21 +17,25 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.bindir = 'bin'
|
20
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
|
23
23
|
s.rdoc_options << '--exclude' << '.'
|
24
24
|
|
25
25
|
s.add_dependency 'sinatra', '~> 1.3.4'
|
26
|
+
s.add_dependency 'typhoeus', '~> 0.6.9'
|
26
27
|
s.add_dependency 'tzinfo', '~> 1.1.0'
|
27
28
|
|
28
29
|
s.add_development_dependency 'activerecord', '~> 4.1.0'
|
29
30
|
if defined?(JRUBY_VERSION)
|
31
|
+
s.add_development_dependency 'activerecord-jdbcmysql-adapter', '~> 1.3.7'
|
30
32
|
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.3.7'
|
31
33
|
else
|
32
34
|
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
33
35
|
end
|
34
36
|
s.add_development_dependency 'activemerchant', '~> 1.42.0'
|
37
|
+
s.add_development_dependency 'monetize', '~> 0.3.0'
|
38
|
+
s.add_development_dependency 'money', '~> 6.1.1'
|
35
39
|
s.add_development_dependency 'jbundler', '~> 0.4.3'
|
36
40
|
s.add_development_dependency 'rack', '>= 1.5.2'
|
37
41
|
s.add_development_dependency 'rake', '>= 0.8.7'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'active_utils/common/error'
|
3
|
+
require 'active_utils/common/network_connection_retries'
|
4
|
+
require 'active_utils/common/connection'
|
5
|
+
require 'typhoeus'
|
6
|
+
|
7
|
+
module ActiveMerchant
|
8
|
+
class Connection
|
9
|
+
|
10
|
+
def request(method, body, headers = {})
|
11
|
+
request_start = Time.now.to_f
|
12
|
+
|
13
|
+
retry_exceptions(:max_retries => max_retries, :logger => logger, :tag => tag) do
|
14
|
+
begin
|
15
|
+
debug "connection_http_method=#{method.to_s.upcase} connection_uri=#{endpoint}", tag
|
16
|
+
|
17
|
+
result = nil
|
18
|
+
realtime = Benchmark.realtime do
|
19
|
+
options = {:method => method, :headers => headers}
|
20
|
+
options[:body] = body if body
|
21
|
+
result = http(endpoint.to_s, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
debug '--> response_code=%d (body_length=%d total_time=%.4fs realtime=%.4fs)' % [result.code, result.body ? result.body.length : 0, result.total_time, realtime], tag
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
ensure
|
29
|
+
debug 'connection_request_total_time=%.4fs' % [Time.now.to_f - request_start], tag
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def http(endpoint, options = {})
|
35
|
+
configure_ssl(options)
|
36
|
+
|
37
|
+
request = ::Typhoeus::Request.new(endpoint, options)
|
38
|
+
configure_debugging(request)
|
39
|
+
|
40
|
+
hydra = ::Typhoeus::Hydra.hydra
|
41
|
+
hydra.queue request
|
42
|
+
hydra.run
|
43
|
+
|
44
|
+
request.response
|
45
|
+
end
|
46
|
+
|
47
|
+
def configure_debugging(request)
|
48
|
+
request.on_complete do |response|
|
49
|
+
wiredump_device << 'Request: '
|
50
|
+
wiredump_device << response.request.base_url
|
51
|
+
wiredump_device << ' '
|
52
|
+
wiredump_device << response.request.options
|
53
|
+
wiredump_device << "\nResponse: "
|
54
|
+
wiredump_device << response.return_code
|
55
|
+
wiredump_device << ' '
|
56
|
+
wiredump_device << response.return_message
|
57
|
+
wiredump_device << ' '
|
58
|
+
wiredump_device << response.response_headers
|
59
|
+
wiredump_device << ' '
|
60
|
+
wiredump_device << response.response_body
|
61
|
+
wiredump_device << "\n\n"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def configure_ssl(options)
|
66
|
+
return unless endpoint.scheme == 'https'
|
67
|
+
|
68
|
+
if verify_peer
|
69
|
+
options[:ssl_verifypeer] ||= true
|
70
|
+
options[:ssl_verifyhost] ||= 2
|
71
|
+
# ca_file / ca_path configured in libcurl
|
72
|
+
else
|
73
|
+
options[:ssl_verifypeer] ||= false
|
74
|
+
options[:ssl_verifyhost] ||= 0
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def log_with_retry_details(logger, attempts, time, message, tag)
|
79
|
+
NetworkConnectionRetries.log(logger, :debug, "connection_attempt=%d connection_request_time=%.4fs connection_msg=\"%s\"" % [attempts, time, message], tag)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -35,19 +35,19 @@ module Killbill
|
|
35
35
|
}.merge!(extra_params))
|
36
36
|
end
|
37
37
|
|
38
|
-
def self.create_response_and_transaction(identifier, transaction_model, api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id,
|
38
|
+
def self.create_response_and_transaction(identifier, transaction_model, api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id, gw_response, amount_in_cents, currency, extra_params = {}, model = Response)
|
39
39
|
response, transaction, exception = nil
|
40
40
|
|
41
41
|
# Rails wraps all create/save calls in a transaction. To speed things up, create a single transaction for both rows.
|
42
42
|
# This has a small gotcha in the unhappy path though (see below).
|
43
43
|
transaction do
|
44
44
|
# Save the response to our logs
|
45
|
-
response = from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id,
|
45
|
+
response = from_response(api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id, gw_response, extra_params, model)
|
46
46
|
response.save!(shared_activerecord_options)
|
47
47
|
|
48
48
|
transaction = nil
|
49
49
|
txn_id = response.txn_id
|
50
|
-
if response.success and !kb_payment_id.blank?
|
50
|
+
if response.success and !kb_payment_id.blank?
|
51
51
|
# Record the transaction
|
52
52
|
# Note that we want to avoid throwing an exception here because we don't want to rollback the response row
|
53
53
|
begin
|
@@ -19,7 +19,7 @@ module Killbill
|
|
19
19
|
@@kb_apis = kb_apis
|
20
20
|
@@test = @@config[gateway_name][:test]
|
21
21
|
|
22
|
-
@@gateway = Gateway.wrap(gateway_builder, @@config[gateway_name.to_sym])
|
22
|
+
@@gateway = Gateway.wrap(gateway_builder, logger, @@config[gateway_name.to_sym])
|
23
23
|
|
24
24
|
@@logger = logger
|
25
25
|
@@logger.log_level = Logger::DEBUG if (@@config[:logger] || {})[:debug]
|
@@ -42,6 +42,12 @@ module Killbill
|
|
42
42
|
@@logger.warn "Unable to establish a database connection: #{e}"
|
43
43
|
end
|
44
44
|
|
45
|
+
# Configure the ActiveMerchant HTTP backend
|
46
|
+
connection_type = (@@config[:active_merchant] || {})[:connection_type]
|
47
|
+
if connection_type == :typhoeus
|
48
|
+
require 'killbill/ext/active_merchant/typhoeus_connection'
|
49
|
+
end
|
50
|
+
|
45
51
|
@@initialized = true
|
46
52
|
end
|
47
53
|
|
@@ -4,7 +4,9 @@ module Killbill
|
|
4
4
|
require 'active_merchant'
|
5
5
|
|
6
6
|
class Gateway
|
7
|
-
def self.wrap(gateway_builder, config)
|
7
|
+
def self.wrap(gateway_builder, logger, config)
|
8
|
+
::ActiveMerchant::Billing::Gateway.logger = logger
|
9
|
+
|
8
10
|
if config[:test]
|
9
11
|
::ActiveMerchant::Billing::Base.mode = :test
|
10
12
|
end
|
@@ -23,10 +25,17 @@ module Killbill
|
|
23
25
|
|
24
26
|
# Unfortunate name...
|
25
27
|
def capture(money, authorization, options = {})
|
26
|
-
|
28
|
+
method_missing(:capture, money, authorization, options)
|
27
29
|
end
|
28
30
|
|
29
31
|
def method_missing(m, *args, &block)
|
32
|
+
# The options hash should be the last argument, iterate through all to be safe
|
33
|
+
args.reverse.each do |arg|
|
34
|
+
if arg.respond_to?(:has_key?) && arg.has_key?(:skip_gw)
|
35
|
+
return ::ActiveMerchant::Billing::Response.new(true, 'Skipped Gateway call')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
30
39
|
@gateway.send(m, *args, &block)
|
31
40
|
end
|
32
41
|
end
|
@@ -2,6 +2,7 @@ module Killbill
|
|
2
2
|
module Plugin
|
3
3
|
module ActiveMerchant
|
4
4
|
require 'active_record'
|
5
|
+
require 'monetize'
|
5
6
|
require 'money'
|
6
7
|
|
7
8
|
class PaymentPlugin < ::Killbill::Plugin::Payment
|
@@ -161,12 +162,19 @@ module Killbill
|
|
161
162
|
payment_source = get_payment_source(nil, all_properties, options, context)
|
162
163
|
|
163
164
|
# Go to the gateway
|
164
|
-
gw_response = gateway.store
|
165
|
+
gw_response = gateway.store(payment_source, options)
|
165
166
|
response, transaction = save_response_and_transaction gw_response, :add_payment_method, kb_account_id, context.tenant_id
|
166
167
|
|
167
168
|
if response.success
|
168
|
-
#
|
169
|
-
|
169
|
+
# If we have skipped the call to the gateway, we still need to store the payment method
|
170
|
+
if options[:skip_gw]
|
171
|
+
cc_or_token = payment_source
|
172
|
+
else
|
173
|
+
# response.authorization may be a String combination separated by ; - don't split it! Some plugins expect it as-is (they split it themselves)
|
174
|
+
cc_or_token = response.authorization
|
175
|
+
end
|
176
|
+
|
177
|
+
payment_method = @payment_method_model.from_response(kb_account_id, kb_payment_method_id, context.tenant_id, cc_or_token, gw_response, options, {}, @payment_method_model)
|
170
178
|
payment_method.save!
|
171
179
|
payment_method
|
172
180
|
else
|
@@ -346,7 +354,7 @@ module Killbill
|
|
346
354
|
|
347
355
|
def to_cents(amount, currency)
|
348
356
|
# Use Money to compute the amount in cents, as it depends on the currency (1 cent of BTC is 1 Satoshi, not 0.01 BTC)
|
349
|
-
Monetize.from_numeric(amount, currency).cents.to_i
|
357
|
+
::Monetize.from_numeric(amount, currency).cents.to_i
|
350
358
|
end
|
351
359
|
|
352
360
|
def get_payment_source(kb_payment_method_id, properties, options, context)
|
@@ -398,10 +406,10 @@ module Killbill
|
|
398
406
|
account.currency
|
399
407
|
end
|
400
408
|
|
401
|
-
def save_response_and_transaction(
|
402
|
-
@logger.warn "Unsuccessful #{api_call}: #{
|
409
|
+
def save_response_and_transaction(gw_response, api_call, kb_account_id, kb_tenant_id, kb_payment_id=nil, kb_payment_transaction_id=nil, transaction_type=nil, amount_in_cents=0, currency=nil)
|
410
|
+
@logger.warn "Unsuccessful #{api_call}: #{gw_response.message}" unless gw_response.success?
|
403
411
|
|
404
|
-
response, transaction = @response_model.create_response_and_transaction(@identifier, @transaction_model, api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id,
|
412
|
+
response, transaction = @response_model.create_response_and_transaction(@identifier, @transaction_model, api_call, kb_account_id, kb_payment_id, kb_payment_transaction_id, transaction_type, kb_tenant_id, gw_response, amount_in_cents, currency, {}, @response_model)
|
405
413
|
|
406
414
|
@logger.debug "Recorded transaction: #{transaction.inspect}" unless transaction.nil?
|
407
415
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spec/killbill/helpers/payment_method_spec'
|
3
|
+
require 'spec/killbill/helpers/response_spec'
|
4
|
+
require 'spec/killbill/helpers/transaction_spec'
|
5
|
+
|
6
|
+
describe Killbill::Plugin::ActiveMerchant::PaymentPlugin do
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
Dir.mktmpdir do |dir|
|
10
|
+
file = File.new(File.join(dir, 'test.yml'), "w+")
|
11
|
+
file.write(<<-eos)
|
12
|
+
:test:
|
13
|
+
:test: true
|
14
|
+
# As defined by spec_helper.rb
|
15
|
+
:database:
|
16
|
+
:adapter: 'sqlite3'
|
17
|
+
:database: 'test.db'
|
18
|
+
eos
|
19
|
+
file.close
|
20
|
+
|
21
|
+
@plugin = ::Killbill::Plugin::ActiveMerchant::PaymentPlugin.new(Proc.new { |config| nil },
|
22
|
+
:test,
|
23
|
+
::Killbill::Test::TestPaymentMethod,
|
24
|
+
::Killbill::Test::TestTransaction,
|
25
|
+
::Killbill::Test::TestResponse)
|
26
|
+
@plugin.logger = Logger.new(STDOUT)
|
27
|
+
@plugin.logger.level = Logger::INFO
|
28
|
+
@plugin.conf_dir = File.dirname(file)
|
29
|
+
|
30
|
+
# Start the plugin here - since the config file will be deleted
|
31
|
+
@plugin.start_plugin
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
@kb_account_id = SecureRandom.uuid
|
37
|
+
@kb_payment_id = SecureRandom.uuid
|
38
|
+
@kb_payment_method_id = SecureRandom.uuid
|
39
|
+
|
40
|
+
@amount_in_cents = rand(100000)
|
41
|
+
@currency = 'USD'
|
42
|
+
@call_context = Killbill::Plugin::Model::CallContext.new
|
43
|
+
@call_context.tenant_id = SecureRandom.uuid
|
44
|
+
|
45
|
+
property = ::Killbill::Plugin::Model::PluginProperty.new
|
46
|
+
property.key = 'skip_gw'
|
47
|
+
property.value = 'true'
|
48
|
+
@properties = [property]
|
49
|
+
|
50
|
+
token = ::Killbill::Plugin::Model::PluginProperty.new
|
51
|
+
token.key = 'token'
|
52
|
+
token.value = SecureRandom.uuid
|
53
|
+
@payment_method_props = ::Killbill::Plugin::Model::PaymentMethodPlugin.new
|
54
|
+
@payment_method_props.properties = [token]
|
55
|
+
end
|
56
|
+
|
57
|
+
after(:all) do
|
58
|
+
@plugin.stop_plugin
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should implement payment plugin API calls' do
|
62
|
+
@plugin.get_payment_methods(@kb_account_id, true, @properties, @call_context).size.should == 0
|
63
|
+
|
64
|
+
@plugin.add_payment_method(@kb_account_id, @kb_payment_method_id, @payment_method_props, true, @properties, @call_context)
|
65
|
+
@plugin.get_payment_methods(@kb_account_id, true, @properties, @call_context).size.should == 1
|
66
|
+
::Killbill::Test::TestPaymentMethod.where(:kb_payment_method_id => @kb_payment_method_id).first.token.should == @payment_method_props.properties[0].value
|
67
|
+
|
68
|
+
authorization_id = SecureRandom.uuid
|
69
|
+
authorization = @plugin.authorize_payment(@kb_account_id, @kb_payment_id, authorization_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context)
|
70
|
+
verify_transaction_info_plugin(authorization, authorization_id, :AUTHORIZE, 1)
|
71
|
+
|
72
|
+
capture_id = SecureRandom.uuid
|
73
|
+
capture = @plugin.capture_payment(@kb_account_id, @kb_payment_id, capture_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context)
|
74
|
+
verify_transaction_info_plugin(capture, capture_id, :CAPTURE, 2)
|
75
|
+
|
76
|
+
purchase_id = SecureRandom.uuid
|
77
|
+
purchase = @plugin.purchase_payment(@kb_account_id, @kb_payment_id, purchase_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context)
|
78
|
+
verify_transaction_info_plugin(purchase, purchase_id, :PURCHASE, 3)
|
79
|
+
|
80
|
+
void_id = SecureRandom.uuid
|
81
|
+
void = @plugin.void_payment(@kb_account_id, @kb_payment_id, void_id, @kb_payment_method_id, @properties, @call_context)
|
82
|
+
verify_transaction_info_plugin(void, void_id, :VOID, 4)
|
83
|
+
|
84
|
+
credit_id = SecureRandom.uuid
|
85
|
+
credit = @plugin.credit_payment(@kb_account_id, @kb_payment_id, credit_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context)
|
86
|
+
verify_transaction_info_plugin(credit, credit_id, :CREDIT, 5)
|
87
|
+
|
88
|
+
refund_id = SecureRandom.uuid
|
89
|
+
refund = @plugin.refund_payment(@kb_account_id, @kb_payment_id, refund_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context)
|
90
|
+
verify_transaction_info_plugin(refund, refund_id, :REFUND, 6)
|
91
|
+
|
92
|
+
@plugin.delete_payment_method(@kb_account_id, @kb_payment_method_id, @properties, @call_context)
|
93
|
+
@plugin.get_payment_methods(@kb_account_id, true, @properties, @call_context).size.should == 0
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def verify_transaction_info_plugin(t_info_plugin, kb_transaction_id, type, transaction_nb)
|
99
|
+
t_info_plugin.kb_payment_id.should == @kb_payment_id
|
100
|
+
t_info_plugin.kb_transaction_payment_id.should == kb_transaction_id
|
101
|
+
t_info_plugin.transaction_type.should == type
|
102
|
+
if type == :VOID
|
103
|
+
t_info_plugin.amount.should be_nil
|
104
|
+
t_info_plugin.currency.should be_nil
|
105
|
+
else
|
106
|
+
t_info_plugin.amount.should == @amount_in_cents
|
107
|
+
t_info_plugin.currency.should == @currency
|
108
|
+
end
|
109
|
+
t_info_plugin.status.should == :PROCESSED
|
110
|
+
|
111
|
+
transactions = @plugin.get_payment_info(@kb_account_id, @kb_payment_id, [], @call_context)
|
112
|
+
transactions.size.should == transaction_nb
|
113
|
+
transactions[transaction_nb - 1].to_json.should == t_info_plugin.to_json
|
114
|
+
end
|
115
|
+
end
|
@@ -33,8 +33,8 @@ ActiveRecord::Schema.define(:version => 20140410153635) do
|
|
33
33
|
t.string "kb_payment_transaction_id", :null => false
|
34
34
|
t.string "transaction_type", :null => false
|
35
35
|
t.string "txn_id"
|
36
|
-
t.integer "amount_in_cents"
|
37
|
-
t.string "currency"
|
36
|
+
t.integer "amount_in_cents"
|
37
|
+
t.string "currency"
|
38
38
|
t.datetime "created_at", :null => false
|
39
39
|
t.datetime "updated_at", :null => false
|
40
40
|
t.string "kb_account_id", :null => false
|
@@ -12,7 +12,6 @@ describe Killbill::Plugin::Payment do
|
|
12
12
|
@currency = 'USD'
|
13
13
|
@call_context = Killbill::Plugin::Model::CallContext.new
|
14
14
|
|
15
|
-
@payment_method = Hash.new(:credit_card => SecureRandom.uuid)
|
16
15
|
@kb_payment_method_id = SecureRandom.uuid
|
17
16
|
|
18
17
|
@search_key = SecureRandom.uuid
|
@@ -36,10 +35,10 @@ describe Killbill::Plugin::Payment do
|
|
36
35
|
lambda { @plugin.refund_payment(@kb_account_id, @kb_payment_id, @kb_payment_transaction_id, @kb_payment_method_id, @amount_in_cents, @currency, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
37
36
|
lambda { @plugin.get_payment_info(@kb_account_id, @kb_payment_id, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
38
37
|
lambda { @plugin.search_payments(@search_key, @offset, @limit, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
39
|
-
lambda { @plugin.add_payment_method(@kb_account_id, @
|
38
|
+
lambda { @plugin.add_payment_method(@kb_account_id, @kb_payment_method_id, @payment_method_props, true, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
40
39
|
lambda { @plugin.delete_payment_method(@kb_account_id, @kb_payment_method_id, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
41
|
-
lambda { @plugin.get_payment_method_detail(@kb_account_id, @
|
42
|
-
lambda { @plugin.set_default_payment_method(@kb_account_id, @
|
40
|
+
lambda { @plugin.get_payment_method_detail(@kb_account_id, @kb_payment_method_id, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
41
|
+
lambda { @plugin.set_default_payment_method(@kb_account_id, @kb_payment_method_id, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
43
42
|
lambda { @plugin.get_payment_methods(@kb_account_id, true, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
44
43
|
lambda { @plugin.search_payment_methods(@search_key, @offset, @limit, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
45
44
|
lambda { @plugin.reset_payment_methods(@kb_account_id, @payment_methods, @properties, @call_context) }.should raise_error Killbill::Plugin::Payment::OperationUnsupportedByGatewayError
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveMerchant::Connection do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@logger = Logger.new(STDOUT)
|
7
|
+
@logger.level = Logger::DEBUG
|
8
|
+
|
9
|
+
@wiredump_device = Tempfile.new('foo')
|
10
|
+
end
|
11
|
+
|
12
|
+
after :all do
|
13
|
+
@wiredump_device.close
|
14
|
+
@wiredump_device.unlink
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should delegate to Typhoeus' do
|
18
|
+
response = ssl_get('https://github.com/killbill/killbill/blob/master/pom.xml')
|
19
|
+
response.code.should == 200
|
20
|
+
response.return_code.should == :ok
|
21
|
+
response.body.size.should > 0
|
22
|
+
|
23
|
+
response = ssl_get('https://github.com/killbill/killbill/blob/master/pomme.xml')
|
24
|
+
response.code.should == 404
|
25
|
+
response.return_code.should == :ok
|
26
|
+
response.body.size.should > 0
|
27
|
+
|
28
|
+
response = ssl_get('/something')
|
29
|
+
response.return_code.should == :url_malformat
|
30
|
+
response.body.size.should == 0
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def ssl_get(endpoint, headers={})
|
36
|
+
ssl_request(:get, endpoint, nil, headers)
|
37
|
+
end
|
38
|
+
|
39
|
+
def ssl_request(method, endpoint, data, headers = {})
|
40
|
+
connection = ::ActiveMerchant::Connection.new(endpoint)
|
41
|
+
connection.open_timeout = 60
|
42
|
+
connection.read_timeout = 60
|
43
|
+
connection.retry_safe = true
|
44
|
+
connection.verify_peer = true
|
45
|
+
connection.logger = @logger
|
46
|
+
connection.tag = self.class.name
|
47
|
+
connection.wiredump_device = @wiredump_device
|
48
|
+
connection.pem = nil
|
49
|
+
connection.pem_password = nil
|
50
|
+
|
51
|
+
connection.request(method, data, headers)
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ require 'java'
|
|
2
2
|
|
3
3
|
require 'bundler'
|
4
4
|
require 'logger'
|
5
|
+
require 'tempfile'
|
5
6
|
|
6
7
|
require 'killbill'
|
7
8
|
require 'killbill/killbill_logger'
|
@@ -13,6 +14,8 @@ require 'killbill/notification_test'
|
|
13
14
|
require 'killbill/helpers/active_merchant'
|
14
15
|
require 'killbill/helpers/active_merchant/active_record/models/helpers'
|
15
16
|
|
17
|
+
require 'killbill/ext/active_merchant/typhoeus_connection'
|
18
|
+
|
16
19
|
%w(
|
17
20
|
MockAccountUserApi
|
18
21
|
).each do |api|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: killbill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kill Bill core team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
version: 1.3.4
|
25
25
|
prerelease: false
|
26
26
|
type: :runtime
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: typhoeus
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.6.9
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.6.9
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: tzinfo
|
29
43
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,20 @@ dependencies:
|
|
52
66
|
version: 4.1.0
|
53
67
|
prerelease: false
|
54
68
|
type: :development
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord-jdbcmysql-adapter
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.7
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 1.3.7
|
81
|
+
prerelease: false
|
82
|
+
type: :development
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: activerecord-jdbcsqlite3-adapter
|
57
85
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -80,6 +108,34 @@ dependencies:
|
|
80
108
|
version: 1.42.0
|
81
109
|
prerelease: false
|
82
110
|
type: :development
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: monetize
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.3.0
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ~>
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 0.3.0
|
123
|
+
prerelease: false
|
124
|
+
type: :development
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: money
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 6.1.1
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ~>
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 6.1.1
|
137
|
+
prerelease: false
|
138
|
+
type: :development
|
83
139
|
- !ruby/object:Gem::Dependency
|
84
140
|
name: jbundler
|
85
141
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -199,6 +255,7 @@ files:
|
|
199
255
|
- lib/killbill.rb
|
200
256
|
- lib/killbill/creator.rb
|
201
257
|
- lib/killbill/currency.rb
|
258
|
+
- lib/killbill/ext/active_merchant/typhoeus_connection.rb
|
202
259
|
- lib/killbill/gen/api/account.rb
|
203
260
|
- lib/killbill/gen/api/account_api_exception.rb
|
204
261
|
- lib/killbill/gen/api/account_audit_logs.rb
|
@@ -348,6 +405,7 @@ files:
|
|
348
405
|
- spec/killbill/config_test.ru
|
349
406
|
- spec/killbill/gen_conversions_spec.rb
|
350
407
|
- spec/killbill/helpers/payment_method_spec.rb
|
408
|
+
- spec/killbill/helpers/payment_plugin_spec.rb
|
351
409
|
- spec/killbill/helpers/response_spec.rb
|
352
410
|
- spec/killbill/helpers/test_schema.rb
|
353
411
|
- spec/killbill/helpers/transaction_spec.rb
|
@@ -362,6 +420,7 @@ files:
|
|
362
420
|
- spec/killbill/payment_plugin_spec.rb
|
363
421
|
- spec/killbill/payment_test.rb
|
364
422
|
- spec/killbill/rack_handler_spec.rb
|
423
|
+
- spec/killbill/remote/active_merchant_typhoeus_connection_spec.rb
|
365
424
|
- spec/spec_helper.rb
|
366
425
|
homepage: http://kill-bill.org
|
367
426
|
licenses:
|
@@ -396,6 +455,7 @@ test_files:
|
|
396
455
|
- spec/killbill/config_test.ru
|
397
456
|
- spec/killbill/gen_conversions_spec.rb
|
398
457
|
- spec/killbill/helpers/payment_method_spec.rb
|
458
|
+
- spec/killbill/helpers/payment_plugin_spec.rb
|
399
459
|
- spec/killbill/helpers/response_spec.rb
|
400
460
|
- spec/killbill/helpers/test_schema.rb
|
401
461
|
- spec/killbill/helpers/transaction_spec.rb
|
@@ -410,4 +470,5 @@ test_files:
|
|
410
470
|
- spec/killbill/payment_plugin_spec.rb
|
411
471
|
- spec/killbill/payment_test.rb
|
412
472
|
- spec/killbill/rack_handler_spec.rb
|
473
|
+
- spec/killbill/remote/active_merchant_typhoeus_connection_spec.rb
|
413
474
|
- spec/spec_helper.rb
|