killbill-stripe 4.1.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/stripe/api.rb +25 -2
- data/lib/stripe/application.rb +10 -0
- data/lib/stripe/ext/active_merchant/active_merchant.rb +135 -0
- data/lib/stripe/models/payment_method.rb +33 -17
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b3fd774290b63212046cc65ae4d9e597feecdcf
|
4
|
+
data.tar.gz: 3f76e5e8fa7b0c3541d010588be12b36546d1a37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58f9df996d008f919c4de81efef0024f6f3579691985e0643e75a0c6636bb712e9da1db2029c74b8151a5d1f2152b61d323ff97d16ad4dde6cada95a51583c44
|
7
|
+
data.tar.gz: 63a9d8bce5a5fcbec1690433ea13e47262691747c4d14f0733b4a6e6b4efd11eaa7f3d10cf62c517a24e4d8c6faaffed823162a4378afc3b7388149dfa21f71f
|
data/lib/stripe/api.rb
CHANGED
@@ -2,7 +2,6 @@ include Killbill::Plugin::ActiveMerchant
|
|
2
2
|
module Killbill #:nodoc:
|
3
3
|
module Stripe #:nodoc:
|
4
4
|
class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
|
5
|
-
|
6
5
|
def initialize
|
7
6
|
gateway_builder = Proc.new do |config|
|
8
7
|
::ActiveMerchant::Billing::StripeGateway.new :login => config[:api_secret_key]
|
@@ -207,8 +206,18 @@ module Killbill #:nodoc:
|
|
207
206
|
gw_notification
|
208
207
|
end
|
209
208
|
|
209
|
+
def verify_bank_account(stripe_customer_id, stripe_bank_account_id, amounts, kb_tenant_id)
|
210
|
+
gateway = lookup_gateway(:default, kb_tenant_id)
|
211
|
+
url = "customers/#{CGI.escape(stripe_customer_id)}/sources/#{CGI.escape(stripe_bank_account_id)}/verify?#{amounts_to_uri(amounts)}"
|
212
|
+
gateway.api_request(:post, url)
|
213
|
+
end
|
214
|
+
|
210
215
|
private
|
211
216
|
|
217
|
+
def amounts_to_uri(amounts)
|
218
|
+
amounts.map {|v| "amounts[]=#{v.to_s}" }.join("&")
|
219
|
+
end
|
220
|
+
|
212
221
|
def before_gateways(kb_transaction, last_transaction, payment_source, amount_in_cents, currency, options, context)
|
213
222
|
super(kb_transaction, last_transaction, payment_source, amount_in_cents, currency, options, context)
|
214
223
|
options[:idempotency_key] ||= kb_transaction.external_key
|
@@ -216,7 +225,16 @@ module Killbill #:nodoc:
|
|
216
225
|
|
217
226
|
def get_payment_source(kb_payment_method_id, properties, options, context)
|
218
227
|
return nil if options[:customer_id]
|
219
|
-
|
228
|
+
if is_bank_account?(properties)
|
229
|
+
ActiveMerchant::Billing::StripeGateway::BankAccount.new({
|
230
|
+
:bank_name => find_value_from_properties(properties, :bank_name),
|
231
|
+
:routing_number => find_value_from_properties(properties, :routing_number),
|
232
|
+
:account_number => find_value_from_properties(properties, :account_number),
|
233
|
+
:type => find_value_from_properties(properties, :type) || "personal",
|
234
|
+
})
|
235
|
+
else
|
236
|
+
super(kb_payment_method_id, properties, options, context)
|
237
|
+
end
|
220
238
|
end
|
221
239
|
|
222
240
|
def populate_defaults(pm, amount, properties, context, options)
|
@@ -246,6 +264,11 @@ module Killbill #:nodoc:
|
|
246
264
|
|
247
265
|
config(context.tenant_id)[:stripe][:fees_amount] || (config(context.tenant_id)[:stripe][:fees_percent].to_f * amount * 100)
|
248
266
|
end
|
267
|
+
|
268
|
+
def is_bank_account?(properties)
|
269
|
+
find_value_from_properties(properties, :routing_number) &&
|
270
|
+
find_value_from_properties(properties, :account_number)
|
271
|
+
end
|
249
272
|
end
|
250
273
|
end
|
251
274
|
end
|
data/lib/stripe/application.rb
CHANGED
@@ -72,6 +72,16 @@ post '/plugins/killbill-stripe', :provides => 'json' do
|
|
72
72
|
response.to_json
|
73
73
|
end
|
74
74
|
|
75
|
+
post '/plugins/killbill-stripe/verify', :provides => 'json' do
|
76
|
+
return params.to_json if development? or test?
|
77
|
+
|
78
|
+
stripe_response = plugin(session).verify_bank_account(params)
|
79
|
+
|
80
|
+
response = params.dup
|
81
|
+
response['stripe_response'] = stripe_response
|
82
|
+
response.to_json
|
83
|
+
end
|
84
|
+
|
75
85
|
# Create managed account
|
76
86
|
post '/plugins/killbill-stripe/accounts', :provides => 'json' do
|
77
87
|
kb_account_id = params.delete('kb_account_id')
|
@@ -4,6 +4,10 @@ module ActiveMerchant
|
|
4
4
|
KB_PLUGIN_VERSION = Gem.loaded_specs['killbill-stripe'].version.version rescue nil
|
5
5
|
|
6
6
|
class StripeGateway
|
7
|
+
BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
|
8
|
+
"personal" => "individual",
|
9
|
+
"business" => "company",
|
10
|
+
}
|
7
11
|
|
8
12
|
def get_balance(options = {})
|
9
13
|
commit(:get, 'balance', nil, options)
|
@@ -37,6 +41,137 @@ module ActiveMerchant
|
|
37
41
|
|
38
42
|
headers
|
39
43
|
end
|
44
|
+
|
45
|
+
# To create a charge on a card or a token, call
|
46
|
+
#
|
47
|
+
# purchase(money, card_hash_or_token, { ... })
|
48
|
+
#
|
49
|
+
# To create a charge on a customer, call
|
50
|
+
#
|
51
|
+
# purchase(money, nil, { :customer => id, ... })
|
52
|
+
def purchase(money, payment, options = {})
|
53
|
+
responses = MultiResponse.run do |r|
|
54
|
+
if payment.is_a?(ApplePayPaymentToken)
|
55
|
+
r.process { tokenize_apple_pay_token(payment) }
|
56
|
+
payment = StripePaymentToken.new(r.params["token"]) if r.success?
|
57
|
+
end
|
58
|
+
r.process do
|
59
|
+
post = create_post_for_auth_or_purchase(money, payment, options)
|
60
|
+
commit(:post, 'charges', post, options)
|
61
|
+
end
|
62
|
+
end.responses.last
|
63
|
+
end
|
64
|
+
|
65
|
+
def store(payment, options = {})
|
66
|
+
params = {}
|
67
|
+
post = {}
|
68
|
+
|
69
|
+
if payment.is_a?(ApplePayPaymentToken)
|
70
|
+
token_exchange_response = tokenize_apple_pay_token(payment)
|
71
|
+
params = { :card => token_exchange_response.params["token"]["id"] } if token_exchange_response.success?
|
72
|
+
elsif payment.is_a?(BankAccount)
|
73
|
+
post.merge!(bank_account_params(payment, options))
|
74
|
+
else
|
75
|
+
add_creditcard(params, payment, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
unless payment.is_a?(BankAccount)
|
79
|
+
post[:validate] = options[:validate] unless options[:validate].nil?
|
80
|
+
post[:description] = options[:description] if options[:description]
|
81
|
+
post[:email] = options[:email] if options[:email]
|
82
|
+
end
|
83
|
+
|
84
|
+
if post[:bank_account]
|
85
|
+
customer_url = "customers"
|
86
|
+
if options[:customer]
|
87
|
+
customer_url += "/#{CGI.escape(options[:customer])}/sources"
|
88
|
+
end
|
89
|
+
responses = MultiResponse.run do |r|
|
90
|
+
# get token and associate it with the customer
|
91
|
+
r.process { commit(:post, "tokens?#{post_data(post)}", nil, { bank_account: true }) }
|
92
|
+
|
93
|
+
if r.success?
|
94
|
+
r.process { commit(:post, customer_url, { source: r.params["id"] } ) }
|
95
|
+
end
|
96
|
+
end.responses
|
97
|
+
if options[:customer]
|
98
|
+
return responses.first
|
99
|
+
else
|
100
|
+
return responses.last
|
101
|
+
end
|
102
|
+
elsif options[:account]
|
103
|
+
add_external_account(post, params, payment)
|
104
|
+
commit(:post, "accounts/#{CGI.escape(options[:account])}/external_accounts", post, options)
|
105
|
+
elsif options[:customer]
|
106
|
+
MultiResponse.run(:first) do |r|
|
107
|
+
# The /cards endpoint does not update other customer parameters.
|
108
|
+
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", params, options) }
|
109
|
+
|
110
|
+
if options[:set_default] and r.success? and !r.params['id'].blank?
|
111
|
+
post[:default_card] = r.params['id']
|
112
|
+
end
|
113
|
+
|
114
|
+
if post.count > 0
|
115
|
+
r.process { update_customer(options[:customer], post) }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
else
|
119
|
+
commit(:post, 'customers', post.merge(params), options)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def commit(method, url, parameters = nil, options = {})
|
124
|
+
if options[:bank_account]
|
125
|
+
response = api_request(:post, url)
|
126
|
+
success = response["error"].nil?
|
127
|
+
|
128
|
+
Response.new(success, nil, response)
|
129
|
+
else
|
130
|
+
add_expand_parameters(parameters, options) if parameters
|
131
|
+
response = api_request(method, url, parameters, options)
|
132
|
+
|
133
|
+
success = !response.key?("error")
|
134
|
+
|
135
|
+
card = card_from_response(response)
|
136
|
+
avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
|
137
|
+
cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
|
138
|
+
Response.new(success,
|
139
|
+
success ? "Transaction approved" : response["error"]["message"],
|
140
|
+
response,
|
141
|
+
:test => response.has_key?("livemode") ? !response["livemode"] : false,
|
142
|
+
:authorization => authorization_from(success, url, method, response),
|
143
|
+
:avs_result => { :code => avs_code },
|
144
|
+
:cvv_result => cvc_code,
|
145
|
+
:emv_authorization => emv_authorization_from_response(response),
|
146
|
+
:error_code => success ? nil : error_code_from(response)
|
147
|
+
)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def bank_account_params(bank_account, options = {})
|
152
|
+
account_holder_type = BANK_ACCOUNT_HOLDER_TYPE_MAPPING[bank_account.type]
|
153
|
+
|
154
|
+
post = {
|
155
|
+
bank_account: {
|
156
|
+
account_number: bank_account.account_number,
|
157
|
+
country: 'US',
|
158
|
+
currency: 'usd',
|
159
|
+
routing_number: bank_account.routing_number,
|
160
|
+
name: bank_account.bank_name,
|
161
|
+
account_holder_type: account_holder_type,
|
162
|
+
}
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
class BankAccount
|
167
|
+
attr_accessor :bank_name, :account_number, :routing_number, :type
|
168
|
+
|
169
|
+
def initialize(args)
|
170
|
+
args.each do |k,v|
|
171
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
40
175
|
end
|
41
176
|
end
|
42
177
|
end
|
@@ -4,16 +4,32 @@ module Killbill #:nodoc:
|
|
4
4
|
|
5
5
|
self.table_name = 'stripe_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 = {}, model = ::Killbill::Stripe::StripePaymentMethod)
|
7
|
+
def self.from_response(kb_account_id, kb_payment_method_id, kb_tenant_id, cc_or_token, response, options, extra_params = {:source_type => "cc"}, model = ::Killbill::Stripe::StripePaymentMethod)
|
8
8
|
stripe_customer_id = options[:customer] || self.stripe_customer_id_from_kb_account_id(kb_account_id, kb_tenant_id)
|
9
|
-
if
|
10
|
-
|
9
|
+
if response.params["bank_account"]
|
10
|
+
extra_params = {} #overwrite extra params because they will be passed with assumption of CC
|
11
|
+
payment_response = {
|
12
|
+
"token" => response.params["bank_account"]["id"],
|
13
|
+
"address_country" => response.params["bank_account"]["country"],
|
14
|
+
}
|
15
|
+
customer_response = { "id" => stripe_customer_id }
|
16
|
+
extra_params[:bank_name] = response.params["bank_account"]["bank_name"]
|
17
|
+
extra_params[:bank_routing_number] = response.params["bank_account"]["routing_number"]
|
18
|
+
extra_params[:source_type] = "bank_account"
|
19
|
+
cc_or_token ||= response.params["bank_account"]["id"]
|
20
|
+
elsif !stripe_customer_id.blank? && response.respond_to?(:responses)
|
21
|
+
payment_response = response.responses.first.params
|
11
22
|
customer_response = response.responses.last.params
|
12
23
|
elsif response.params['sources']
|
13
|
-
|
24
|
+
payment_response = response.params['sources']['data'][0]
|
14
25
|
customer_response = response.params
|
26
|
+
if response.params['sources']['data'][0]["object"] == "bank_account"
|
27
|
+
extra_params[:bank_name] = response.params["sources"]["data"][0]["bank_name"]
|
28
|
+
extra_params[:bank_routing_number] = response.params["sources"]["data"][0]["routing_number"]
|
29
|
+
extra_params[:source_type] = "bank_account"
|
30
|
+
end
|
15
31
|
else
|
16
|
-
|
32
|
+
payment_response = {}
|
17
33
|
customer_response = { 'id' => stripe_customer_id }
|
18
34
|
end
|
19
35
|
|
@@ -25,19 +41,19 @@ module Killbill #:nodoc:
|
|
25
41
|
options,
|
26
42
|
{
|
27
43
|
:stripe_customer_id => customer_response['id'],
|
28
|
-
:token =>
|
29
|
-
:cc_first_name =>
|
44
|
+
:token => payment_response['id'],
|
45
|
+
:cc_first_name => payment_response['name'],
|
30
46
|
:cc_last_name => nil,
|
31
|
-
:cc_type =>
|
32
|
-
:cc_exp_month =>
|
33
|
-
:cc_exp_year =>
|
34
|
-
:cc_last_4 =>
|
35
|
-
:address1 =>
|
36
|
-
:address2 =>
|
37
|
-
:city =>
|
38
|
-
:state =>
|
39
|
-
:zip =>
|
40
|
-
:country =>
|
47
|
+
:cc_type => payment_response['brand'],
|
48
|
+
:cc_exp_month => payment_response['exp_month'],
|
49
|
+
:cc_exp_year => payment_response['exp_year'],
|
50
|
+
:cc_last_4 => payment_response['last4'],
|
51
|
+
:address1 => payment_response['address_line1'],
|
52
|
+
:address2 => payment_response['address_line2'],
|
53
|
+
:city => payment_response['address_city'],
|
54
|
+
:state => payment_response['address_state'],
|
55
|
+
:zip => payment_response['address_zip'],
|
56
|
+
:country => payment_response['address_country']
|
41
57
|
}.merge!(extra_params.compact), # Don't override with nil values
|
42
58
|
model)
|
43
59
|
end
|
metadata
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: killbill-stripe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
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:
|
11
|
+
date: 2018-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version:
|
18
|
+
version: 9.3.0
|
19
19
|
name: killbill
|
20
20
|
prerelease: false
|
21
21
|
type: :runtime
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 9.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
@@ -218,6 +218,9 @@ dependencies:
|
|
218
218
|
- - ">="
|
219
219
|
- !ruby/object:Gem::Version
|
220
220
|
version: 10.0.0
|
221
|
+
- - "<"
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: 11.0.0
|
221
224
|
name: rake
|
222
225
|
prerelease: false
|
223
226
|
type: :development
|
@@ -226,6 +229,9 @@ dependencies:
|
|
226
229
|
- - ">="
|
227
230
|
- !ruby/object:Gem::Version
|
228
231
|
version: 10.0.0
|
232
|
+
- - "<"
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: 11.0.0
|
229
235
|
- !ruby/object:Gem::Dependency
|
230
236
|
requirement: !ruby/object:Gem::Requirement
|
231
237
|
requirements:
|