stripe 1.31.0 → 1.58.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/.github/ISSUE_TEMPLATE.md +5 -0
- data/.travis.yml +2 -12
- data/Gemfile +29 -4
- data/History.txt +168 -0
- data/README.md +134 -0
- data/Rakefile +10 -0
- data/VERSION +1 -1
- data/bin/stripe-console +12 -5
- data/lib/data/ca-certificates.crt +3868 -5114
- data/lib/stripe/account.rb +41 -21
- data/lib/stripe/alipay_account.rb +20 -0
- data/lib/stripe/api_operations/create.rb +1 -1
- data/lib/stripe/api_operations/delete.rb +1 -1
- data/lib/stripe/api_operations/list.rb +1 -2
- data/lib/stripe/api_operations/save.rb +87 -0
- data/lib/stripe/api_resource.rb +37 -4
- data/lib/stripe/apple_pay_domain.rb +12 -0
- data/lib/stripe/application_fee.rb +8 -8
- data/lib/stripe/application_fee_refund.rb +7 -3
- data/lib/stripe/balance_transaction.rb +1 -1
- data/lib/stripe/bank_account.rb +9 -5
- data/lib/stripe/bitcoin_receiver.rb +6 -6
- data/lib/stripe/bitcoin_transaction.rb +1 -1
- data/lib/stripe/card.rb +9 -5
- data/lib/stripe/charge.rb +30 -12
- data/lib/stripe/country_spec.rb +9 -0
- data/lib/stripe/coupon.rb +1 -1
- data/lib/stripe/customer.rb +6 -4
- data/lib/stripe/dispute.rb +2 -2
- data/lib/stripe/errors.rb +82 -0
- data/lib/stripe/file_upload.rb +1 -1
- data/lib/stripe/invoice.rb +3 -3
- data/lib/stripe/invoice_item.rb +1 -1
- data/lib/stripe/list_object.rb +7 -6
- data/lib/stripe/order.rb +10 -2
- data/lib/stripe/order_return.rb +9 -0
- data/lib/stripe/plan.rb +1 -1
- data/lib/stripe/product.rb +2 -10
- data/lib/stripe/recipient.rb +1 -1
- data/lib/stripe/refund.rb +1 -1
- data/lib/stripe/reversal.rb +7 -3
- data/lib/stripe/singleton_api_resource.rb +3 -3
- data/lib/stripe/sku.rb +2 -2
- data/lib/stripe/source.rb +11 -0
- data/lib/stripe/stripe_object.rb +167 -91
- data/lib/stripe/subscription.rb +15 -9
- data/lib/stripe/subscription_item.rb +12 -0
- data/lib/stripe/three_d_secure.rb +9 -0
- data/lib/stripe/transfer.rb +3 -4
- data/lib/stripe/util.rb +100 -28
- data/lib/stripe/version.rb +1 -1
- data/lib/stripe.rb +283 -140
- data/stripe.gemspec +5 -18
- data/test/stripe/account_test.rb +55 -9
- data/test/stripe/alipay_account_test.rb +11 -0
- data/test/stripe/api_operations_test.rb +31 -0
- data/test/stripe/api_resource_test.rb +204 -10
- data/test/stripe/apple_pay_domain_test.rb +34 -0
- data/test/stripe/application_fee_test.rb +8 -5
- data/test/stripe/bitcoin_receiver_test.rb +2 -2
- data/test/stripe/charge_refund_test.rb +12 -0
- data/test/stripe/charge_test.rb +32 -4
- data/test/stripe/country_spec_test.rb +43 -0
- data/test/stripe/coupon_test.rb +9 -1
- data/test/stripe/customer_card_test.rb +2 -2
- data/test/stripe/customer_test.rb +24 -1
- data/test/stripe/dispute_test.rb +8 -0
- data/test/stripe/errors_test.rb +18 -0
- data/test/stripe/invoice_item_test.rb +19 -0
- data/test/stripe/invoice_test.rb +27 -1
- data/test/stripe/list_object_test.rb +36 -15
- data/test/stripe/order_return_test.rb +25 -0
- data/test/stripe/order_test.rb +21 -1
- data/test/stripe/plan_test.rb +31 -0
- data/test/stripe/product_test.rb +17 -7
- data/test/stripe/recipient_card_test.rb +2 -2
- data/test/stripe/recipient_test.rb +21 -0
- data/test/stripe/refund_test.rb +10 -1
- data/test/stripe/sku_test.rb +15 -6
- data/test/stripe/source_test.rb +83 -0
- data/test/stripe/stripe_object_test.rb +180 -11
- data/test/stripe/subscription_item_test.rb +76 -0
- data/test/stripe/subscription_test.rb +161 -37
- data/test/stripe/three_d_secure_test.rb +22 -0
- data/test/stripe/transfer_test.rb +8 -0
- data/test/stripe/util_test.rb +48 -16
- data/test/stripe_test.rb +58 -0
- data/test/test_data.rb +337 -27
- data/test/test_helper.rb +7 -3
- metadata +47 -133
- data/README.rdoc +0 -68
- data/gemfiles/default-with-activesupport.gemfile +0 -10
- data/gemfiles/json.gemfile +0 -12
- data/gemfiles/yajl.gemfile +0 -12
- data/lib/stripe/api_operations/update.rb +0 -58
- data/lib/stripe/errors/api_connection_error.rb +0 -4
- data/lib/stripe/errors/api_error.rb +0 -4
- data/lib/stripe/errors/authentication_error.rb +0 -4
- data/lib/stripe/errors/card_error.rb +0 -12
- data/lib/stripe/errors/invalid_request_error.rb +0 -11
- data/lib/stripe/errors/rate_limit_error.rb +0 -4
- data/lib/stripe/errors/stripe_error.rb +0 -26
data/test/stripe/account_test.rb
CHANGED
@@ -52,7 +52,23 @@ module Stripe
|
|
52
52
|
assert_equal 'secret-key', account.keys.secret
|
53
53
|
end
|
54
54
|
|
55
|
-
should "be
|
55
|
+
should "be rejectable" do
|
56
|
+
account_data = {:id => 'acct_foo'}
|
57
|
+
@mock.expects(:get).
|
58
|
+
once.
|
59
|
+
with('https://api.stripe.com/v1/accounts/acct_foo', nil, nil).
|
60
|
+
returns(make_response(account_data))
|
61
|
+
|
62
|
+
@mock.expects(:post).
|
63
|
+
once.
|
64
|
+
with("https://api.stripe.com/v1/accounts/acct_foo/reject", nil, 'reason=fraud').
|
65
|
+
returns(make_response(account_data))
|
66
|
+
|
67
|
+
account = Stripe::Account.retrieve('acct_foo')
|
68
|
+
account.reject(:reason => 'fraud')
|
69
|
+
end
|
70
|
+
|
71
|
+
should "be saveable" do
|
56
72
|
resp = {
|
57
73
|
:id => 'acct_foo',
|
58
74
|
:legal_entity => {
|
@@ -77,6 +93,20 @@ module Stripe
|
|
77
93
|
a.save
|
78
94
|
end
|
79
95
|
|
96
|
+
should "be updatable" do
|
97
|
+
resp = {
|
98
|
+
:id => 'acct_foo',
|
99
|
+
:business_name => 'ACME Corp',
|
100
|
+
}
|
101
|
+
@mock.expects(:post).
|
102
|
+
once.
|
103
|
+
with('https://api.stripe.com/v1/accounts/acct_foo', nil, 'business_name=ACME+Corp').
|
104
|
+
returns(make_response(resp))
|
105
|
+
|
106
|
+
a = Stripe::Account.update('acct_foo', :business_name => "ACME Corp")
|
107
|
+
assert_equal('ACME Corp', a.business_name)
|
108
|
+
end
|
109
|
+
|
80
110
|
should 'disallow direct overrides of legal_entity' do
|
81
111
|
account = Stripe::Account.construct_from(make_account({
|
82
112
|
:keys => {
|
@@ -121,7 +151,7 @@ module Stripe
|
|
121
151
|
:id => 'acct_1234',
|
122
152
|
:external_accounts => {
|
123
153
|
:object => "list",
|
124
|
-
:
|
154
|
+
:resource_url => "/v1/accounts/acct_1234/external_accounts",
|
125
155
|
:data => [],
|
126
156
|
}
|
127
157
|
}
|
@@ -140,7 +170,7 @@ module Stripe
|
|
140
170
|
:id => 'acct_1234',
|
141
171
|
:external_accounts => {
|
142
172
|
:object => "list",
|
143
|
-
:
|
173
|
+
:resource_url => "/v1/accounts/acct_1234/external_accounts",
|
144
174
|
:data => [{
|
145
175
|
:id => "ba_1234",
|
146
176
|
:object => "bank_account",
|
@@ -155,8 +185,8 @@ module Stripe
|
|
155
185
|
should "#serialize_params an a new additional_owners" do
|
156
186
|
obj = Stripe::Util.convert_to_stripe_object({
|
157
187
|
:object => "account",
|
158
|
-
:legal_entity => {
|
159
|
-
},
|
188
|
+
:legal_entity => Stripe::StripeObject.construct_from({
|
189
|
+
}),
|
160
190
|
}, {})
|
161
191
|
obj.legal_entity.additional_owners = [
|
162
192
|
{ :first_name => "Joe" },
|
@@ -171,7 +201,7 @@ module Stripe
|
|
171
201
|
}
|
172
202
|
}
|
173
203
|
}
|
174
|
-
assert_equal(expected, obj.
|
204
|
+
assert_equal(expected, obj.serialize_params)
|
175
205
|
end
|
176
206
|
|
177
207
|
should "#serialize_params on an partially changed additional_owners" do
|
@@ -197,7 +227,7 @@ module Stripe
|
|
197
227
|
}
|
198
228
|
}
|
199
229
|
}
|
200
|
-
assert_equal(expected, obj.
|
230
|
+
assert_equal(expected, obj.serialize_params)
|
201
231
|
end
|
202
232
|
|
203
233
|
should "#serialize_params on an unchanged additional_owners" do
|
@@ -220,7 +250,7 @@ module Stripe
|
|
220
250
|
:additional_owners => {}
|
221
251
|
}
|
222
252
|
}
|
223
|
-
assert_equal(expected, obj.
|
253
|
+
assert_equal(expected, obj.serialize_params)
|
224
254
|
end
|
225
255
|
|
226
256
|
# Note that the empty string that we send for this one has a special
|
@@ -246,7 +276,23 @@ module Stripe
|
|
246
276
|
:additional_owners => ""
|
247
277
|
}
|
248
278
|
}
|
249
|
-
assert_equal(expected, obj.
|
279
|
+
assert_equal(expected, obj.serialize_params)
|
280
|
+
end
|
281
|
+
|
282
|
+
context "#bank_account=" do
|
283
|
+
should "warn that #bank_account= is deprecated" do
|
284
|
+
old_stderr = $stderr
|
285
|
+
$stderr = StringIO.new
|
286
|
+
begin
|
287
|
+
a = Stripe::Account.new("test_account")
|
288
|
+
a.bank_account = "tok_123"
|
289
|
+
message = "NOTE: Stripe::Account#bank_account= is " +
|
290
|
+
"deprecated; use #external_account= instead"
|
291
|
+
assert_match Regexp.new(message), $stderr.string
|
292
|
+
ensure
|
293
|
+
$stderr = old_stderr
|
294
|
+
end
|
295
|
+
end
|
250
296
|
end
|
251
297
|
end
|
252
298
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Stripe
|
4
|
+
class AlipayAccountTest < Test::Unit::TestCase
|
5
|
+
should "raise if accessing Stripe::Alipay.account directly" do
|
6
|
+
assert_raises NotImplementedError do
|
7
|
+
Stripe::AlipayAccount.retrieve "card_12345"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path('../../test_helper', __FILE__)
|
3
|
+
|
4
|
+
module Stripe
|
5
|
+
class ApiOperationsTest < Test::Unit::TestCase
|
6
|
+
class UpdateableResource < APIResource
|
7
|
+
include Stripe::APIOperations::Save
|
8
|
+
|
9
|
+
def self.protected_fields
|
10
|
+
[:protected]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context ".update" do
|
15
|
+
should "post the correct parameters to the resource URL" do
|
16
|
+
@mock.expects(:post).once.
|
17
|
+
with("#{Stripe.api_base}/v1/updateableresources/id", nil, 'foo=bar').
|
18
|
+
returns(make_response({foo: 'bar'}))
|
19
|
+
resource = UpdateableResource::update("id", { foo: "bar" })
|
20
|
+
assert_equal('bar', resource.foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "error on protected fields" do
|
24
|
+
e = assert_raises do
|
25
|
+
UpdateableResource::update("id", { protected: "bar" })
|
26
|
+
end
|
27
|
+
assert_equal "Cannot update protected field: protected", e.message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -3,6 +3,26 @@ require File.expand_path('../../test_helper', __FILE__)
|
|
3
3
|
|
4
4
|
module Stripe
|
5
5
|
class ApiResourceTest < Test::Unit::TestCase
|
6
|
+
class NestedTestAPIResource < Stripe::APIResource
|
7
|
+
save_nested_resource :external_account
|
8
|
+
end
|
9
|
+
|
10
|
+
context ".save_nested_resource" do
|
11
|
+
should "can have a scalar set" do
|
12
|
+
r = NestedTestAPIResource.new("test_resource")
|
13
|
+
r.external_account = "tok_123"
|
14
|
+
assert_equal "tok_123", r.external_account
|
15
|
+
end
|
16
|
+
|
17
|
+
should "set a flag if given an object source" do
|
18
|
+
r = NestedTestAPIResource.new("test_resource")
|
19
|
+
r.external_account = {
|
20
|
+
:object => 'card'
|
21
|
+
}
|
22
|
+
assert_equal true, r.external_account.save_with_parent
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
6
26
|
should "creating a new APIResource should not fetch over the network" do
|
7
27
|
@mock.expects(:get).never
|
8
28
|
Stripe::Customer.new("someid")
|
@@ -174,7 +194,7 @@ module Stripe
|
|
174
194
|
context "with no global API key set" do
|
175
195
|
should "use the per-object credential when creating" do
|
176
196
|
Stripe.expects(:execute_request).with do |opts|
|
177
|
-
opts[:headers][
|
197
|
+
opts[:headers]['Authorization'] == 'Bearer sk_test_local'
|
178
198
|
end.returns(make_response(make_charge))
|
179
199
|
|
180
200
|
Stripe::Charge.create({:card => {:number => '4242424242424242'}},
|
@@ -193,7 +213,7 @@ module Stripe
|
|
193
213
|
|
194
214
|
should "use the per-object credential when creating" do
|
195
215
|
Stripe.expects(:execute_request).with do |opts|
|
196
|
-
opts[:headers][
|
216
|
+
opts[:headers]['Authorization'] == 'Bearer local'
|
197
217
|
end.returns(make_response(make_charge))
|
198
218
|
|
199
219
|
Stripe::Charge.create({:card => {:number => '4242424242424242'}},
|
@@ -203,15 +223,15 @@ module Stripe
|
|
203
223
|
should "use the per-object credential when retrieving and making other calls" do
|
204
224
|
Stripe.expects(:execute_request).with do |opts|
|
205
225
|
opts[:url] == "#{Stripe.api_base}/v1/charges/ch_test_charge" &&
|
206
|
-
opts[:headers][
|
226
|
+
opts[:headers]['Authorization'] == 'Bearer local'
|
207
227
|
end.returns(make_response(make_charge))
|
208
228
|
Stripe.expects(:execute_request).with do |opts|
|
209
|
-
opts[:url] == "#{Stripe.api_base}/v1/charges/ch_test_charge/
|
210
|
-
opts[:headers][
|
211
|
-
end.returns(make_response(
|
229
|
+
opts[:url] == "#{Stripe.api_base}/v1/charges/ch_test_charge/refunds" &&
|
230
|
+
opts[:headers]['Authorization'] == 'Bearer local'
|
231
|
+
end.returns(make_response(make_refund))
|
212
232
|
|
213
233
|
ch = Stripe::Charge.retrieve('ch_test_charge', 'local')
|
214
|
-
ch.
|
234
|
+
ch.refunds.create
|
215
235
|
end
|
216
236
|
end
|
217
237
|
end
|
@@ -280,6 +300,18 @@ module Stripe
|
|
280
300
|
end
|
281
301
|
end
|
282
302
|
|
303
|
+
should "a 403 should give a PermissionError with http status, body, and JSON body" do
|
304
|
+
response = make_response(make_missing_id_error, 403)
|
305
|
+
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 403))
|
306
|
+
begin
|
307
|
+
Stripe::Customer.retrieve("foo")
|
308
|
+
rescue Stripe::PermissionError => e
|
309
|
+
assert_equal(403, e.http_status)
|
310
|
+
assert_equal(true, !!e.http_body)
|
311
|
+
assert_equal(true, e.json_body.kind_of?(Hash))
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
283
315
|
should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do
|
284
316
|
response = make_response(make_missing_id_error, 404)
|
285
317
|
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
|
@@ -387,6 +419,31 @@ module Stripe
|
|
387
419
|
assert_equal false, c.livemode
|
388
420
|
end
|
389
421
|
|
422
|
+
should "updating should send along the idempotency-key header" do
|
423
|
+
Stripe.expects(:execute_request).with do |opts|
|
424
|
+
opts[:headers][:idempotency_key] == 'bar'
|
425
|
+
end.returns(make_response(make_customer))
|
426
|
+
c = Stripe::Customer.new
|
427
|
+
c.save({}, { :idempotency_key => 'bar' })
|
428
|
+
assert_equal false, c.livemode
|
429
|
+
end
|
430
|
+
|
431
|
+
should "updating should fail if api_key is overwritten with nil" do
|
432
|
+
c = Stripe::Customer.new
|
433
|
+
assert_raises TypeError do
|
434
|
+
c.save({}, { :api_key => nil })
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
should "updating should use the supplied api_key" do
|
439
|
+
Stripe.expects(:execute_request).with do |opts|
|
440
|
+
opts[:headers]['Authorization'] == 'Bearer sk_test_local'
|
441
|
+
end.returns(make_response(make_customer))
|
442
|
+
c = Stripe::Customer.new
|
443
|
+
c.save({}, { :api_key => 'sk_test_local' })
|
444
|
+
assert_equal false, c.livemode
|
445
|
+
end
|
446
|
+
|
390
447
|
should "deleting should send no props and result in an object that has no props other deleted" do
|
391
448
|
@mock.expects(:get).never
|
392
449
|
@mock.expects(:post).never
|
@@ -420,7 +477,7 @@ module Stripe
|
|
420
477
|
opts[:url] == "#{Stripe.api_base}/v1/customers/c_test_customer" &&
|
421
478
|
opts[:headers][:stripe_account] == 'acct_abc'
|
422
479
|
end.once.returns(make_response(make_customer))
|
423
|
-
|
480
|
+
Stripe::Customer.retrieve("c_test_customer", {:stripe_account => 'acct_abc'})
|
424
481
|
end
|
425
482
|
|
426
483
|
should "passing in a stripe_account header should pass it through on save" do
|
@@ -652,10 +709,147 @@ module Stripe
|
|
652
709
|
:display_name => nil,
|
653
710
|
})
|
654
711
|
|
655
|
-
@mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts", nil, 'display_name=stripe').
|
712
|
+
@mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts", nil, 'display_name=stripe&metadata[key]=value').
|
656
713
|
returns(make_response({"id" => "charge_id"}))
|
657
714
|
|
658
|
-
account.save(:display_name => 'stripe')
|
715
|
+
account.save(:display_name => 'stripe', :metadata => {:key => 'value' })
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
context "with retries" do
|
720
|
+
setup do
|
721
|
+
Stripe.stubs(:max_network_retries).returns(2)
|
722
|
+
end
|
723
|
+
|
724
|
+
should 'retry failed network requests if specified and raise if error persists' do
|
725
|
+
Stripe.expects(:sleep_time).at_least_once.returns(0)
|
726
|
+
@mock.expects(:post).times(3).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
727
|
+
raises(Errno::ECONNREFUSED.new)
|
728
|
+
|
729
|
+
err = assert_raises Stripe::APIConnectionError do
|
730
|
+
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
731
|
+
end
|
732
|
+
assert_match(/Request was retried 2 times/, err.message)
|
733
|
+
end
|
734
|
+
|
735
|
+
should 'retry failed network requests if specified and return successful response' do
|
736
|
+
Stripe.expects(:sleep_time).at_least_once.returns(0)
|
737
|
+
response = make_response({"id" => "myid"})
|
738
|
+
@mock.expects(:post).times(2).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
739
|
+
raises(Errno::ECONNREFUSED.new).
|
740
|
+
then.
|
741
|
+
returns(response)
|
742
|
+
|
743
|
+
result = Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
744
|
+
assert_equal "myid", result.id
|
745
|
+
end
|
746
|
+
|
747
|
+
should 'not add an idempotency key to GET requests' do
|
748
|
+
SecureRandom.expects(:uuid).times(0)
|
749
|
+
Stripe.expects(:execute_request).with do |opts|
|
750
|
+
opts[:headers][:idempotency_key].nil?
|
751
|
+
end.returns(make_response({"id" => "myid"}))
|
752
|
+
|
753
|
+
Stripe::Charge.list
|
754
|
+
end
|
755
|
+
|
756
|
+
should 'ensure there is always an idempotency_key on POST requests' do
|
757
|
+
SecureRandom.expects(:uuid).at_least_once.returns("random_key")
|
758
|
+
Stripe.expects(:execute_request).with do |opts|
|
759
|
+
opts[:headers]['Idempotency-Key'] == "random_key"
|
760
|
+
end.returns(make_response({"id" => "myid"}))
|
761
|
+
|
762
|
+
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
763
|
+
end
|
764
|
+
|
765
|
+
should 'ensure there is always an idempotency_key on DELETE requests' do
|
766
|
+
SecureRandom.expects(:uuid).at_least_once.returns("random_key")
|
767
|
+
Stripe.expects(:execute_request).with do |opts|
|
768
|
+
opts[:headers]['Idempotency-Key'] == "random_key"
|
769
|
+
end.returns(make_response({"id" => "myid"}))
|
770
|
+
|
771
|
+
c = Stripe::Customer.construct_from(make_customer)
|
772
|
+
c.delete
|
773
|
+
end
|
774
|
+
|
775
|
+
should 'not override a provided idempotency_key' do
|
776
|
+
# Note that this expectation looks like `:idempotency_key` instead of
|
777
|
+
# the header `Idempotency-Key` because it's user provided as seen
|
778
|
+
# below. The ones injected by the library itself look like headers
|
779
|
+
# (`Idempotency-Key`), but rest-client does allow this symbol
|
780
|
+
# formatting and will properly override the system generated one as
|
781
|
+
# expected.
|
782
|
+
Stripe.expects(:execute_request).with do |opts|
|
783
|
+
opts[:headers][:idempotency_key] == "provided_key"
|
784
|
+
end.returns(make_response({"id" => "myid"}))
|
785
|
+
|
786
|
+
Stripe::Charge.create({:amount => 50, :currency => 'usd', :card => { :number => nil }}, {:idempotency_key => 'provided_key'})
|
787
|
+
end
|
788
|
+
|
789
|
+
end
|
790
|
+
|
791
|
+
context ".should_retry?" do
|
792
|
+
setup do
|
793
|
+
Stripe.stubs(:max_network_retries).returns(2)
|
794
|
+
end
|
795
|
+
|
796
|
+
should 'retry on a low-level network error' do
|
797
|
+
assert Stripe.should_retry?(Errno::ECONNREFUSED.new, 0)
|
798
|
+
end
|
799
|
+
|
800
|
+
should 'retry on timeout' do
|
801
|
+
assert Stripe.should_retry?(RestClient::RequestTimeout.new, 0)
|
802
|
+
end
|
803
|
+
|
804
|
+
should 'retry on a conflict' do
|
805
|
+
assert Stripe.should_retry?(RestClient::Conflict.new, 0)
|
806
|
+
end
|
807
|
+
|
808
|
+
should 'not retry at maximum count' do
|
809
|
+
refute Stripe.should_retry?(RuntimeError.new, Stripe.max_network_retries)
|
810
|
+
end
|
811
|
+
|
812
|
+
should 'not retry on a certificate validation error' do
|
813
|
+
refute Stripe.should_retry?(RestClient::SSLCertificateNotVerified.new('message'), 0)
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
context ".sleep_time" do
|
818
|
+
should "should grow exponentially" do
|
819
|
+
Stripe.stubs(:rand).returns(1)
|
820
|
+
Stripe.stubs(:max_network_retry_delay).returns(999)
|
821
|
+
assert_equal(Stripe.initial_network_retry_delay, Stripe.sleep_time(1))
|
822
|
+
assert_equal(Stripe.initial_network_retry_delay * 2, Stripe.sleep_time(2))
|
823
|
+
assert_equal(Stripe.initial_network_retry_delay * 4, Stripe.sleep_time(3))
|
824
|
+
assert_equal(Stripe.initial_network_retry_delay * 8, Stripe.sleep_time(4))
|
825
|
+
end
|
826
|
+
|
827
|
+
should "enforce the max_network_retry_delay" do
|
828
|
+
Stripe.stubs(:rand).returns(1)
|
829
|
+
Stripe.stubs(:initial_network_retry_delay).returns(1)
|
830
|
+
Stripe.stubs(:max_network_retry_delay).returns(2)
|
831
|
+
assert_equal(1, Stripe.sleep_time(1))
|
832
|
+
assert_equal(2, Stripe.sleep_time(2))
|
833
|
+
assert_equal(2, Stripe.sleep_time(3))
|
834
|
+
assert_equal(2, Stripe.sleep_time(4))
|
835
|
+
end
|
836
|
+
|
837
|
+
should "add some randomness" do
|
838
|
+
random_value = 0.8
|
839
|
+
Stripe.stubs(:rand).returns(random_value)
|
840
|
+
Stripe.stubs(:initial_network_retry_delay).returns(1)
|
841
|
+
Stripe.stubs(:max_network_retry_delay).returns(8)
|
842
|
+
|
843
|
+
base_value = Stripe.initial_network_retry_delay * (0.5 * (1 + random_value))
|
844
|
+
|
845
|
+
# the initial value cannot be smaller than the base,
|
846
|
+
# so the randomness is ignored
|
847
|
+
assert_equal(Stripe.initial_network_retry_delay, Stripe.sleep_time(1))
|
848
|
+
|
849
|
+
# after the first one, the randomness is applied
|
850
|
+
assert_equal(base_value * 2, Stripe.sleep_time(2))
|
851
|
+
assert_equal(base_value * 4, Stripe.sleep_time(3))
|
852
|
+
assert_equal(base_value * 8, Stripe.sleep_time(4))
|
659
853
|
end
|
660
854
|
end
|
661
855
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Stripe
|
4
|
+
class ApplePayDomainTest < Test::Unit::TestCase
|
5
|
+
should "create should return a new Apple Pay domain" do
|
6
|
+
@mock.expects(:post).once
|
7
|
+
.with('https://api.stripe.com/v1/apple_pay/domains', nil, '')
|
8
|
+
.returns(make_response(make_apple_pay_domain))
|
9
|
+
d = Stripe::ApplePayDomain.create
|
10
|
+
assert_equal "apwc_test_domain", d.id
|
11
|
+
end
|
12
|
+
|
13
|
+
should "domains should be deletable" do
|
14
|
+
@mock.expects(:get).once
|
15
|
+
.with('https://api.stripe.com/v1/apple_pay/domains/apwc_test_domain', nil, nil)
|
16
|
+
.returns(make_response(make_apple_pay_domain))
|
17
|
+
@mock.expects(:delete).once.returns(make_response(make_apple_pay_domain(:deleted => true)))
|
18
|
+
domain = Stripe::ApplePayDomain.retrieve('apwc_test_domain')
|
19
|
+
domain.delete
|
20
|
+
assert domain.deleted
|
21
|
+
end
|
22
|
+
|
23
|
+
should "domains should be listable" do
|
24
|
+
@mock.expects(:get).once.with('https://api.stripe.com/v1/apple_pay/domains', nil, nil)
|
25
|
+
.returns(make_response(make_apple_pay_domain_array))
|
26
|
+
domains = Stripe::ApplePayDomain.list
|
27
|
+
assert domains.data.kind_of?(Array)
|
28
|
+
assert_equal 3, domains.data.length
|
29
|
+
domains.each do |domain|
|
30
|
+
assert domain.kind_of?(Stripe::ApplePayDomain)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -12,11 +12,14 @@ module Stripe
|
|
12
12
|
end
|
13
13
|
|
14
14
|
should "application fees should be refundable" do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
fee = Stripe::ApplicationFee.construct_from(make_application_fee)
|
16
|
+
|
17
|
+
@mock.expects(:post).once.
|
18
|
+
with("#{Stripe.api_base}/v1/application_fees/#{fee.id}/refunds", nil, '').
|
19
|
+
returns(make_response(make_application_fee_refund))
|
20
|
+
|
21
|
+
refund = fee.refunds.create
|
22
|
+
assert refund.is_a?(Stripe::ApplicationFeeRefund)
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
@@ -47,14 +47,14 @@ module Stripe
|
|
47
47
|
should "delete a bitcoin receiver with no customer through top-level API" do
|
48
48
|
@mock.expects(:delete).with("#{Stripe.api_base}/v1/bitcoin/receivers/btcrcv_test_receiver", nil, nil).once.returns(make_response({:deleted => true, :id => "btcrcv_test_receiver"}))
|
49
49
|
receiver = Stripe::BitcoinReceiver.construct_from(make_bitcoin_receiver)
|
50
|
-
|
50
|
+
receiver.delete
|
51
51
|
assert(receiver.deleted)
|
52
52
|
end
|
53
53
|
|
54
54
|
should "delete a bitcoin receiver with a customer through customer's subresource API" do
|
55
55
|
@mock.expects(:delete).with("#{Stripe.api_base}/v1/customers/customer_foo/sources/btcrcv_test_receiver", nil, nil).once.returns(make_response({:deleted => true, :id => "btcrcv_test_receiver"}))
|
56
56
|
receiver = Stripe::BitcoinReceiver.construct_from(make_bitcoin_receiver(:customer => 'customer_foo'))
|
57
|
-
|
57
|
+
receiver.delete
|
58
58
|
assert(receiver.deleted)
|
59
59
|
end
|
60
60
|
end
|
@@ -51,5 +51,17 @@ module Stripe
|
|
51
51
|
refund = charge.refunds.create(:amount => 20)
|
52
52
|
assert_equal 'test_new_refund', refund.id
|
53
53
|
end
|
54
|
+
|
55
|
+
should "should refund a charge with given amount" do
|
56
|
+
@mock.expects(:get).
|
57
|
+
with("#{Stripe.api_base}/v1/charges/test_charge", nil, nil).
|
58
|
+
twice.returns(make_response(make_charge(:id => 'test_charge')))
|
59
|
+
@mock.expects(:post).
|
60
|
+
with("#{Stripe.api_base}/v1/charges/test_charge/refunds", nil, 'amount=20').
|
61
|
+
once.returns(make_response(make_refund(:amount => 20)))
|
62
|
+
|
63
|
+
charge = Stripe::Charge.retrieve('test_charge')
|
64
|
+
charge.refund(:amount => 20)
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
data/test/stripe/charge_test.rb
CHANGED
@@ -12,10 +12,24 @@ module Stripe
|
|
12
12
|
end
|
13
13
|
|
14
14
|
should "charges should be refundable" do
|
15
|
+
c = Stripe::Charge.construct_from(make_charge)
|
15
16
|
@mock.expects(:get).never
|
16
|
-
@mock.expects(:post).once.returns(make_response(
|
17
|
-
|
18
|
-
|
17
|
+
@mock.expects(:post).once.returns(make_response(make_refund(:charge => c)))
|
18
|
+
r = c.refunds.create
|
19
|
+
assert r.is_a?(Stripe::Refund)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "charges should be refundable for old API versions" do
|
23
|
+
# "refunds" was a plain array in old API versions but is not a Stripe
|
24
|
+
# list (see the implementation of `make_charge` for a current example)
|
25
|
+
data = make_charge.merge!(:refunds => [])
|
26
|
+
c = Stripe::Charge.construct_from(data)
|
27
|
+
@mock.expects(:get).never
|
28
|
+
@mock.expects(:post).once.
|
29
|
+
with("#{Stripe.api_base}/v1/charges/#{c.id}/refund", nil, '').
|
30
|
+
returns(make_response(data.merge(:refunded => true)))
|
31
|
+
c = c.refund
|
32
|
+
assert c.is_a?(Stripe::Charge)
|
19
33
|
assert c.refunded
|
20
34
|
end
|
21
35
|
|
@@ -28,6 +42,14 @@ module Stripe
|
|
28
42
|
end
|
29
43
|
|
30
44
|
should "charges should be updateable" do
|
45
|
+
@mock.expects(:post).once.
|
46
|
+
with('https://api.stripe.com/v1/charges/test_charge', nil, 'metadata[foo]=bar').
|
47
|
+
returns(make_response(make_charge(metadata: {'foo' => 'bar'})))
|
48
|
+
c = Stripe::Charge.update("test_charge", metadata: {foo: 'bar'})
|
49
|
+
assert_equal('bar', c.metadata['foo'])
|
50
|
+
end
|
51
|
+
|
52
|
+
should "charges should be saveable" do
|
31
53
|
@mock.expects(:get).once.returns(make_response(make_charge))
|
32
54
|
@mock.expects(:post).once.returns(make_response(make_charge))
|
33
55
|
c = Stripe::Charge.new("test_charge")
|
@@ -58,6 +80,12 @@ module Stripe
|
|
58
80
|
assert c.card.kind_of?(Stripe::StripeObject) && c.card.object == 'card'
|
59
81
|
end
|
60
82
|
|
83
|
+
should "charges should have Outcome objects associated with their outcome property" do
|
84
|
+
@mock.expects(:get).once.returns(make_response(make_charge))
|
85
|
+
c = Stripe::Charge.retrieve("test_charge")
|
86
|
+
assert c.outcome.kind_of?(Stripe::StripeObject) && c.outcome.type == 'authorized'
|
87
|
+
end
|
88
|
+
|
61
89
|
should "execute should return a new, fully executed charge when passed correct `card` parameters" do
|
62
90
|
@mock.expects(:post).with do |url, api_key, params|
|
63
91
|
url == "#{Stripe.api_base}/v1/charges" && api_key.nil? && CGI.parse(params) == {
|
@@ -110,7 +138,7 @@ module Stripe
|
|
110
138
|
:amount => 100,
|
111
139
|
:source => 'btcrcv_test_receiver',
|
112
140
|
:currency => "usd",
|
113
|
-
:level3 => [{:red => 'firstred'}, {:
|
141
|
+
:level3 => [{:red => 'firstred'}, {:red => 'another', :one => 'fish'}]
|
114
142
|
})
|
115
143
|
assert c.paid
|
116
144
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Stripe
|
4
|
+
class CountrySpecTest < Test::Unit::TestCase
|
5
|
+
should "be listable" do
|
6
|
+
@mock.expects(:get).once.
|
7
|
+
returns(make_response(country_spec_array))
|
8
|
+
c = Stripe::CountrySpec.list
|
9
|
+
|
10
|
+
assert_equal('/v1/country_specs', c.resource_url)
|
11
|
+
assert_equal('list', c.object)
|
12
|
+
assert(c.data.kind_of?(Array))
|
13
|
+
assert_equal('US', c.data[0].id)
|
14
|
+
assert(c.data[0].kind_of?(Stripe::CountrySpec))
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be retrievable" do
|
18
|
+
resp = make_country_spec
|
19
|
+
@mock.expects(:get).once.
|
20
|
+
with('https://api.stripe.com/v1/country_specs/US', nil, nil).
|
21
|
+
returns(make_response(resp))
|
22
|
+
s = Stripe::CountrySpec.retrieve('US')
|
23
|
+
|
24
|
+
assert_equal('/v1/country_specs/US', s.resource_url)
|
25
|
+
assert_equal('country_spec', s.object)
|
26
|
+
assert(s.kind_of?(Stripe::CountrySpec))
|
27
|
+
|
28
|
+
s.supported_bank_account_currencies.map{ |k,v| assert v.kind_of?(Array) }
|
29
|
+
assert_equal(['US'], s.supported_bank_account_currencies['usd'])
|
30
|
+
assert(s.supported_payment_currencies.include?('usd'))
|
31
|
+
assert s.supported_payment_currencies.kind_of?(Array)
|
32
|
+
assert s.supported_payment_methods.kind_of?(Array)
|
33
|
+
|
34
|
+
['individual', 'company'].map{ |type|
|
35
|
+
item = s.verification_fields[type]
|
36
|
+
assert item.minimum.include?('external_account')
|
37
|
+
assert item.additional.include?('legal_entity.verification.document')
|
38
|
+
assert item.additional.kind_of?(Array)
|
39
|
+
assert item.minimum.kind_of?(Array)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/test/stripe/coupon_test.rb
CHANGED
@@ -8,7 +8,7 @@ module Stripe
|
|
8
8
|
assert_equal "co_test_coupon", c.id
|
9
9
|
end
|
10
10
|
|
11
|
-
should "coupons should be
|
11
|
+
should "coupons should be saveable" do
|
12
12
|
@mock.expects(:get).once.returns(make_response(make_coupon))
|
13
13
|
@mock.expects(:post).once.returns(make_response(make_coupon))
|
14
14
|
c = Stripe::Coupon.new("test_coupon")
|
@@ -16,5 +16,13 @@ module Stripe
|
|
16
16
|
c.metadata['foo'] = 'bar'
|
17
17
|
c.save
|
18
18
|
end
|
19
|
+
|
20
|
+
should "coupons should be updateable" do
|
21
|
+
@mock.expects(:post).once.
|
22
|
+
with("https://api.stripe.com/v1/coupons/test_coupon", nil, "metadata[foo]=bar").
|
23
|
+
returns(make_response(make_coupon(metadata: {foo: 'bar'})))
|
24
|
+
c = Stripe::Coupon.update("test_coupon", metadata: {foo: 'bar'})
|
25
|
+
assert_equal('bar', c.metadata['foo'])
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|