killbill-stripe 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/Gemfile +1 -1
- data/Jarfile +7 -5
- data/LICENSE +201 -0
- data/NEWS +1 -1
- data/README.md +26 -7
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/config.ru +1 -1
- data/db/ddl.sql +28 -5
- data/db/schema.rb +41 -17
- data/killbill-stripe.gemspec +14 -7
- data/lib/stripe.rb +10 -16
- data/lib/stripe/api.rb +143 -203
- data/lib/stripe/{config/application.rb → application.rb} +35 -20
- data/lib/stripe/models/payment_method.rb +58 -0
- data/lib/stripe/models/response.rb +80 -0
- data/lib/stripe/models/transaction.rb +11 -0
- data/lib/stripe/private_api.rb +28 -46
- data/pom.xml +3 -3
- data/release.sh +8 -8
- data/spec/spec_helper.rb +3 -16
- data/spec/stripe/base_plugin_spec.rb +26 -20
- data/spec/stripe/remote/integration_spec.rb +120 -167
- data/stripe.yml +21 -0
- metadata +104 -26
- data/lib/stripe/config/configuration.rb +0 -38
- data/lib/stripe/config/properties.rb +0 -23
- data/lib/stripe/models/stripe_payment_method.rb +0 -182
- data/lib/stripe/models/stripe_response.rb +0 -242
- data/lib/stripe/models/stripe_transaction.rb +0 -44
- data/lib/stripe/stripe/gateway.rb +0 -24
- data/lib/stripe/stripe_utils.rb +0 -27
- data/spec/stripe/stripe_payment_method_spec.rb +0 -97
- data/spec/stripe/stripe_response_spec.rb +0 -84
@@ -1,44 +0,0 @@
|
|
1
|
-
module Killbill::Stripe
|
2
|
-
class StripeTransaction < ActiveRecord::Base
|
3
|
-
belongs_to :stripe_response
|
4
|
-
attr_accessible :amount_in_cents, :currency, :api_call, :kb_payment_id, :stripe_txn_id
|
5
|
-
|
6
|
-
def self.from_kb_payment_id(kb_payment_id)
|
7
|
-
transaction_from_kb_payment_id :charge, kb_payment_id, :single
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.refunds_from_kb_payment_id(kb_payment_id)
|
11
|
-
transaction_from_kb_payment_id :refund, kb_payment_id, :multiple
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.find_candidate_transaction_for_refund(kb_payment_id, amount_in_cents)
|
15
|
-
# Find one successful charge which amount is at least the amount we are trying to refund
|
16
|
-
stripe_transactions = StripeTransaction.where("stripe_transactions.amount_in_cents >= ?", amount_in_cents)
|
17
|
-
.find_all_by_api_call_and_kb_payment_id(:charge, kb_payment_id)
|
18
|
-
raise "Unable to find Stripe transaction id for payment #{kb_payment_id}" if stripe_transactions.size == 0
|
19
|
-
|
20
|
-
# We have candidates, but we now need to make sure we didn't refund more than for the specified amount
|
21
|
-
amount_refunded_in_cents = Killbill::Stripe::StripeTransaction.where("api_call = ? and kb_payment_id = ?", :refund, kb_payment_id)
|
22
|
-
.sum("amount_in_cents")
|
23
|
-
|
24
|
-
amount_left_to_refund_in_cents = -amount_refunded_in_cents
|
25
|
-
stripe_transactions.map { |transaction| amount_left_to_refund_in_cents += transaction.amount_in_cents }
|
26
|
-
raise "Amount #{amount_in_cents} too large to refund for payment #{kb_payment_id}" if amount_left_to_refund_in_cents < amount_in_cents
|
27
|
-
|
28
|
-
stripe_transactions.first
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def self.transaction_from_kb_payment_id(api_call, kb_payment_id, how_many)
|
34
|
-
stripe_transactions = find_all_by_api_call_and_kb_payment_id(api_call, kb_payment_id)
|
35
|
-
raise "Unable to find Stripe transaction id for payment #{kb_payment_id}" if stripe_transactions.empty?
|
36
|
-
if how_many == :single
|
37
|
-
raise "Killbill payment mapping to multiple Stripe transactions for payment #{kb_payment_id}" if stripe_transactions.size > 1
|
38
|
-
stripe_transactions[0]
|
39
|
-
else
|
40
|
-
stripe_transactions
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Killbill::Stripe
|
2
|
-
class Gateway
|
3
|
-
def self.from_config(config)
|
4
|
-
if config[:test]
|
5
|
-
ActiveMerchant::Billing::Base.mode = :test
|
6
|
-
end
|
7
|
-
|
8
|
-
if config[:log_file]
|
9
|
-
ActiveMerchant::Billing::StripeGateway.wiredump_device = File.open(config[:log_file], 'w')
|
10
|
-
ActiveMerchant::Billing::StripeGateway.wiredump_device.sync = true
|
11
|
-
end
|
12
|
-
|
13
|
-
Gateway.new(config[:api_secret_key])
|
14
|
-
end
|
15
|
-
|
16
|
-
def initialize(api_secret_key)
|
17
|
-
@gateway = ActiveMerchant::Billing::StripeGateway.new(:login => api_secret_key)
|
18
|
-
end
|
19
|
-
|
20
|
-
def method_missing(m, *args, &block)
|
21
|
-
@gateway.send(m, *args, &block)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/stripe/stripe_utils.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module Killbill::Stripe
|
2
|
-
# Closest from a streaming API as we can get with ActiveRecord
|
3
|
-
class StreamyResultSet
|
4
|
-
include Enumerable
|
5
|
-
|
6
|
-
def initialize(limit, batch_size = 100, &delegate)
|
7
|
-
@limit = limit
|
8
|
-
@batch = [batch_size, limit].min
|
9
|
-
@delegate = delegate
|
10
|
-
end
|
11
|
-
|
12
|
-
def each(&block)
|
13
|
-
(0..(@limit - @batch)).step(@batch) do |i|
|
14
|
-
result = @delegate.call(i, @batch)
|
15
|
-
block.call(result)
|
16
|
-
# Optimization: bail out if no more results
|
17
|
-
break if result.nil? || result.empty?
|
18
|
-
end if @batch > 0
|
19
|
-
# Make sure to return DB connections to the Pool
|
20
|
-
ActiveRecord::Base.connection.close
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_a
|
24
|
-
super.to_a.flatten
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Killbill::Stripe::StripePaymentMethod do
|
4
|
-
before :all do
|
5
|
-
Killbill::Stripe::StripePaymentMethod.delete_all
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'should generate the right SQL query' do
|
9
|
-
# Check count query (search query numeric)
|
10
|
-
expected_query = "SELECT COUNT(DISTINCT \"stripe_payment_methods\".\"id\") FROM \"stripe_payment_methods\" WHERE (((((((((((((((\"stripe_payment_methods\".\"kb_account_id\" = '1234' OR \"stripe_payment_methods\".\"kb_payment_method_id\" = '1234') OR \"stripe_payment_methods\".\"stripe_customer_id\" = '1234') OR \"stripe_payment_methods\".\"stripe_card_id_or_token\" = '1234') OR \"stripe_payment_methods\".\"cc_type\" = '1234') OR \"stripe_payment_methods\".\"state\" = '1234') OR \"stripe_payment_methods\".\"zip\" = '1234') OR \"stripe_payment_methods\".\"cc_first_name\" LIKE '%1234%') OR \"stripe_payment_methods\".\"cc_last_name\" LIKE '%1234%') OR \"stripe_payment_methods\".\"address1\" LIKE '%1234%') OR \"stripe_payment_methods\".\"address2\" LIKE '%1234%') OR \"stripe_payment_methods\".\"city\" LIKE '%1234%') OR \"stripe_payment_methods\".\"country\" LIKE '%1234%') OR \"stripe_payment_methods\".\"cc_exp_month\" = 1234) OR \"stripe_payment_methods\".\"cc_exp_year\" = 1234) OR \"stripe_payment_methods\".\"cc_last_4\" = 1234) AND \"stripe_payment_methods\".\"kb_payment_method_id\" IS NOT NULL ORDER BY \"stripe_payment_methods\".\"id\""
|
11
|
-
# Note that Kill Bill will pass a String, even for numeric types
|
12
|
-
Killbill::Stripe::StripePaymentMethod.search_query('1234').to_sql.should == expected_query
|
13
|
-
|
14
|
-
# Check query with results (search query numeric)
|
15
|
-
expected_query = "SELECT DISTINCT \"stripe_payment_methods\".* FROM \"stripe_payment_methods\" WHERE (((((((((((((((\"stripe_payment_methods\".\"kb_account_id\" = '1234' OR \"stripe_payment_methods\".\"kb_payment_method_id\" = '1234') OR \"stripe_payment_methods\".\"stripe_customer_id\" = '1234') OR \"stripe_payment_methods\".\"stripe_card_id_or_token\" = '1234') OR \"stripe_payment_methods\".\"cc_type\" = '1234') OR \"stripe_payment_methods\".\"state\" = '1234') OR \"stripe_payment_methods\".\"zip\" = '1234') OR \"stripe_payment_methods\".\"cc_first_name\" LIKE '%1234%') OR \"stripe_payment_methods\".\"cc_last_name\" LIKE '%1234%') OR \"stripe_payment_methods\".\"address1\" LIKE '%1234%') OR \"stripe_payment_methods\".\"address2\" LIKE '%1234%') OR \"stripe_payment_methods\".\"city\" LIKE '%1234%') OR \"stripe_payment_methods\".\"country\" LIKE '%1234%') OR \"stripe_payment_methods\".\"cc_exp_month\" = 1234) OR \"stripe_payment_methods\".\"cc_exp_year\" = 1234) OR \"stripe_payment_methods\".\"cc_last_4\" = 1234) AND \"stripe_payment_methods\".\"kb_payment_method_id\" IS NOT NULL ORDER BY \"stripe_payment_methods\".\"id\" LIMIT 10 OFFSET 0"
|
16
|
-
# Note that Kill Bill will pass a String, even for numeric types
|
17
|
-
Killbill::Stripe::StripePaymentMethod.search_query('1234', 0, 10).to_sql.should == expected_query
|
18
|
-
|
19
|
-
# Check count query (search query string)
|
20
|
-
expected_query = "SELECT COUNT(DISTINCT \"stripe_payment_methods\".\"id\") FROM \"stripe_payment_methods\" WHERE ((((((((((((\"stripe_payment_methods\".\"kb_account_id\" = 'XXX' OR \"stripe_payment_methods\".\"kb_payment_method_id\" = 'XXX') OR \"stripe_payment_methods\".\"stripe_customer_id\" = 'XXX') OR \"stripe_payment_methods\".\"stripe_card_id_or_token\" = 'XXX') OR \"stripe_payment_methods\".\"cc_type\" = 'XXX') OR \"stripe_payment_methods\".\"state\" = 'XXX') OR \"stripe_payment_methods\".\"zip\" = 'XXX') OR \"stripe_payment_methods\".\"cc_first_name\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"cc_last_name\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"address1\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"address2\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"city\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"country\" LIKE '%XXX%') AND \"stripe_payment_methods\".\"kb_payment_method_id\" IS NOT NULL ORDER BY \"stripe_payment_methods\".\"id\""
|
21
|
-
Killbill::Stripe::StripePaymentMethod.search_query('XXX').to_sql.should == expected_query
|
22
|
-
|
23
|
-
# Check query with results (search query string)
|
24
|
-
expected_query = "SELECT DISTINCT \"stripe_payment_methods\".* FROM \"stripe_payment_methods\" WHERE ((((((((((((\"stripe_payment_methods\".\"kb_account_id\" = 'XXX' OR \"stripe_payment_methods\".\"kb_payment_method_id\" = 'XXX') OR \"stripe_payment_methods\".\"stripe_customer_id\" = 'XXX') OR \"stripe_payment_methods\".\"stripe_card_id_or_token\" = 'XXX') OR \"stripe_payment_methods\".\"cc_type\" = 'XXX') OR \"stripe_payment_methods\".\"state\" = 'XXX') OR \"stripe_payment_methods\".\"zip\" = 'XXX') OR \"stripe_payment_methods\".\"cc_first_name\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"cc_last_name\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"address1\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"address2\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"city\" LIKE '%XXX%') OR \"stripe_payment_methods\".\"country\" LIKE '%XXX%') AND \"stripe_payment_methods\".\"kb_payment_method_id\" IS NOT NULL ORDER BY \"stripe_payment_methods\".\"id\" LIMIT 10 OFFSET 0"
|
25
|
-
Killbill::Stripe::StripePaymentMethod.search_query('XXX', 0, 10).to_sql.should == expected_query
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should search all fields' do
|
29
|
-
do_search('foo').size.should == 0
|
30
|
-
|
31
|
-
pm = Killbill::Stripe::StripePaymentMethod.create :kb_account_id => '11-22-33-44',
|
32
|
-
:kb_payment_method_id => '55-66-77-88',
|
33
|
-
:stripe_customer_id => '123xka',
|
34
|
-
:stripe_card_id_or_token => 38102343,
|
35
|
-
:cc_first_name => 'ccFirstName',
|
36
|
-
:cc_last_name => 'ccLastName',
|
37
|
-
:cc_type => 'ccType',
|
38
|
-
:cc_exp_month => 10,
|
39
|
-
:cc_exp_year => 11,
|
40
|
-
:cc_last_4 => 1234,
|
41
|
-
:address1 => 'address1',
|
42
|
-
:address2 => 'address2',
|
43
|
-
:city => 'city',
|
44
|
-
:state => 'state',
|
45
|
-
:zip => 'zip',
|
46
|
-
:country => 'country'
|
47
|
-
|
48
|
-
do_search('foo').size.should == 0
|
49
|
-
do_search(pm.stripe_card_id_or_token).size.should == 1
|
50
|
-
do_search('ccType').size.should == 1
|
51
|
-
# Exact match only for cc_last_4
|
52
|
-
do_search('123').size.should == 0
|
53
|
-
do_search('1234').size.should == 1
|
54
|
-
# Test partial match
|
55
|
-
do_search('address').size.should == 1
|
56
|
-
do_search('Name').size.should == 1
|
57
|
-
|
58
|
-
pm2 = Killbill::Stripe::StripePaymentMethod.create :kb_account_id => '22-33-44-55',
|
59
|
-
:kb_payment_method_id => '66-77-88-99',
|
60
|
-
:stripe_customer_id => '123xka',
|
61
|
-
:stripe_card_id_or_token => 49384029302,
|
62
|
-
:cc_first_name => 'ccFirstName',
|
63
|
-
:cc_last_name => 'ccLastName',
|
64
|
-
:cc_type => 'ccType',
|
65
|
-
:cc_exp_month => 10,
|
66
|
-
:cc_exp_year => 11,
|
67
|
-
:cc_last_4 => 1234,
|
68
|
-
:address1 => 'address1',
|
69
|
-
:address2 => 'address2',
|
70
|
-
:city => 'city',
|
71
|
-
:state => 'state',
|
72
|
-
:zip => 'zip',
|
73
|
-
:country => 'country'
|
74
|
-
|
75
|
-
do_search('foo').size.should == 0
|
76
|
-
do_search(pm.stripe_card_id_or_token).size.should == 1
|
77
|
-
do_search(pm2.stripe_card_id_or_token).size.should == 1
|
78
|
-
do_search('ccType').size.should == 2
|
79
|
-
# Exact match only for cc_last_4
|
80
|
-
do_search('123').size.should == 0
|
81
|
-
do_search('1234').size.should == 2
|
82
|
-
# Test partial match
|
83
|
-
do_search('cc').size.should == 2
|
84
|
-
do_search('address').size.should == 2
|
85
|
-
do_search('Name').size.should == 2
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def do_search(search_key)
|
91
|
-
pagination = Killbill::Stripe::StripePaymentMethod.search(search_key)
|
92
|
-
pagination.current_offset.should == 0
|
93
|
-
results = pagination.iterator.to_a
|
94
|
-
pagination.total_nb_records.should == results.size
|
95
|
-
results
|
96
|
-
end
|
97
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Killbill::Stripe::StripeResponse do
|
4
|
-
before :all do
|
5
|
-
Killbill::Stripe::StripeResponse.delete_all
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'should generate the right SQL query' do
|
9
|
-
# Check count query (search query numeric)
|
10
|
-
expected_query = "SELECT COUNT(DISTINCT \"stripe_responses\".\"id\") FROM \"stripe_responses\" WHERE ((\"stripe_responses\".\"authorization\" = '1234' OR \"stripe_responses\".\"params_id\" = '1234') OR \"stripe_responses\".\"params_card_id\" = '1234') AND \"stripe_responses\".\"api_call\" = 'charge' AND \"stripe_responses\".\"success\" = 't' ORDER BY \"stripe_responses\".\"id\""
|
11
|
-
# Note that Kill Bill will pass a String, even for numeric types
|
12
|
-
Killbill::Stripe::StripeResponse.search_query('charge', '1234').to_sql.should == expected_query
|
13
|
-
|
14
|
-
# Check query with results (search query numeric)
|
15
|
-
expected_query = "SELECT DISTINCT \"stripe_responses\".* FROM \"stripe_responses\" WHERE ((\"stripe_responses\".\"authorization\" = '1234' OR \"stripe_responses\".\"params_id\" = '1234') OR \"stripe_responses\".\"params_card_id\" = '1234') AND \"stripe_responses\".\"api_call\" = 'charge' AND \"stripe_responses\".\"success\" = 't' ORDER BY \"stripe_responses\".\"id\" LIMIT 10 OFFSET 0"
|
16
|
-
# Note that Kill Bill will pass a String, even for numeric types
|
17
|
-
Killbill::Stripe::StripeResponse.search_query('charge', '1234', 0, 10).to_sql.should == expected_query
|
18
|
-
|
19
|
-
# Check count query (search query string)
|
20
|
-
expected_query = "SELECT COUNT(DISTINCT \"stripe_responses\".\"id\") FROM \"stripe_responses\" WHERE ((\"stripe_responses\".\"authorization\" = 'XXX' OR \"stripe_responses\".\"params_id\" = 'XXX') OR \"stripe_responses\".\"params_card_id\" = 'XXX') AND \"stripe_responses\".\"api_call\" = 'charge' AND \"stripe_responses\".\"success\" = 't' ORDER BY \"stripe_responses\".\"id\""
|
21
|
-
Killbill::Stripe::StripeResponse.search_query('charge', 'XXX').to_sql.should == expected_query
|
22
|
-
|
23
|
-
# Check query with results (search query string)
|
24
|
-
expected_query = "SELECT DISTINCT \"stripe_responses\".* FROM \"stripe_responses\" WHERE ((\"stripe_responses\".\"authorization\" = 'XXX' OR \"stripe_responses\".\"params_id\" = 'XXX') OR \"stripe_responses\".\"params_card_id\" = 'XXX') AND \"stripe_responses\".\"api_call\" = 'charge' AND \"stripe_responses\".\"success\" = 't' ORDER BY \"stripe_responses\".\"id\" LIMIT 10 OFFSET 0"
|
25
|
-
Killbill::Stripe::StripeResponse.search_query('charge', 'XXX', 0, 10).to_sql.should == expected_query
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should search all fields' do
|
29
|
-
do_search('foo').size.should == 0
|
30
|
-
|
31
|
-
pm = Killbill::Stripe::StripeResponse.create :api_call => 'charge',
|
32
|
-
:kb_payment_id => '11-22-33-44',
|
33
|
-
:authorization => 'aa-bb-cc-dd',
|
34
|
-
:params_id => '55-66-77-88',
|
35
|
-
:params_card_id => 38102343,
|
36
|
-
:success => true
|
37
|
-
|
38
|
-
# Wrong api_call
|
39
|
-
ignored1 = Killbill::Stripe::StripeResponse.create :api_call => 'add_payment_method',
|
40
|
-
:kb_payment_id => pm.kb_payment_id,
|
41
|
-
:authorization => pm.authorization,
|
42
|
-
:params_id => pm.params_id,
|
43
|
-
:params_card_id => pm.params_card_id,
|
44
|
-
:success => true
|
45
|
-
|
46
|
-
# Not successful
|
47
|
-
ignored2 = Killbill::Stripe::StripeResponse.create :api_call => 'charge',
|
48
|
-
:kb_payment_id => pm.kb_payment_id,
|
49
|
-
:authorization => pm.authorization,
|
50
|
-
:params_id => pm.params_id,
|
51
|
-
:params_card_id => pm.params_card_id,
|
52
|
-
:success => false
|
53
|
-
|
54
|
-
do_search('foo').size.should == 0
|
55
|
-
do_search(pm.authorization).size.should == 1
|
56
|
-
do_search(pm.params_id).size.should == 1
|
57
|
-
do_search(pm.params_card_id).size.should == 1
|
58
|
-
|
59
|
-
pm2 = Killbill::Stripe::StripeResponse.create :api_call => 'charge',
|
60
|
-
:kb_payment_id => '11-22-33-44',
|
61
|
-
:authorization => 'AA-BB-CC-DD',
|
62
|
-
:params_id => '11-22-33-44',
|
63
|
-
:params_card_id => pm.params_card_id,
|
64
|
-
:success => true
|
65
|
-
|
66
|
-
do_search('foo').size.should == 0
|
67
|
-
do_search(pm.authorization).size.should == 1
|
68
|
-
do_search(pm.params_id).size.should == 1
|
69
|
-
do_search(pm.params_card_id).size.should == 2
|
70
|
-
do_search(pm2.authorization).size.should == 1
|
71
|
-
do_search(pm2.params_id).size.should == 1
|
72
|
-
do_search(pm2.params_card_id).size.should == 2
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def do_search(search_key)
|
78
|
-
pagination = Killbill::Stripe::StripeResponse.search(search_key)
|
79
|
-
pagination.current_offset.should == 0
|
80
|
-
results = pagination.iterator.to_a
|
81
|
-
pagination.total_nb_records.should == results.size
|
82
|
-
results
|
83
|
-
end
|
84
|
-
end
|