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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbdc020a826585e1d723991b963ea2cc0b9866a6
4
- data.tar.gz: 2140de112d1665611c8535bde2084bfa731b8f85
3
+ metadata.gz: 2b3fd774290b63212046cc65ae4d9e597feecdcf
4
+ data.tar.gz: 3f76e5e8fa7b0c3541d010588be12b36546d1a37
5
5
  SHA512:
6
- metadata.gz: 4a58e78693d70c2504d8ff46e9263325b301927424899875e7fb84dc353c751230732543cba821de087b52134111ca941d15e351b573f6c775ec143c2608cf9a
7
- data.tar.gz: 688c6b82d49c17c34551d6daca4a9d20d7dda4d1ca6257f70ab90860570dd924cf2d40a781eb70be3dd275cf013ed8caf23b077c19d43e92b42c8503a3c5deea
6
+ metadata.gz: 58f9df996d008f919c4de81efef0024f6f3579691985e0643e75a0c6636bb712e9da1db2029c74b8151a5d1f2152b61d323ff97d16ad4dde6cada95a51583c44
7
+ data.tar.gz: 63a9d8bce5a5fcbec1690433ea13e47262691747c4d14f0733b4a6e6b4efd11eaa7f3d10cf62c517a24e4d8c6faaffed823162a4378afc3b7388149dfa21f71f
@@ -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
- super(kb_payment_method_id, properties, options, context)
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
@@ -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 !stripe_customer_id.blank? && response.respond_to?(:responses)
10
- card_response = response.responses.first.params
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
- card_response = response.params['sources']['data'][0]
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
- card_response = {}
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 => card_response['id'],
29
- :cc_first_name => card_response['name'],
44
+ :token => payment_response['id'],
45
+ :cc_first_name => payment_response['name'],
30
46
  :cc_last_name => nil,
31
- :cc_type => card_response['brand'],
32
- :cc_exp_month => card_response['exp_month'],
33
- :cc_exp_year => card_response['exp_year'],
34
- :cc_last_4 => card_response['last4'],
35
- :address1 => card_response['address_line1'],
36
- :address2 => card_response['address_line2'],
37
- :city => card_response['address_city'],
38
- :state => card_response['address_state'],
39
- :zip => card_response['address_zip'],
40
- :country => card_response['address_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.1.1
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: 2017-05-03 00:00:00.000000000 Z
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: '8.0'
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: '8.0'
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: