stripe 3.0.3 → 3.1.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/.travis.yml +23 -0
- data/Gemfile +1 -2
- data/History.txt +4 -0
- data/README.md +28 -3
- data/Rakefile +0 -12
- data/VERSION +1 -1
- data/lib/stripe.rb +24 -0
- data/lib/stripe/stripe_client.rb +166 -19
- data/lib/stripe/util.rb +127 -8
- data/lib/stripe/version.rb +1 -1
- data/test/api_stub_helpers.rb +0 -125
- data/test/stripe/account_test.rb +11 -13
- data/test/stripe/alipay_account_test.rb +2 -4
- data/test/stripe/api_resource_test.rb +112 -76
- data/test/stripe/apple_pay_domain_test.rb +4 -6
- data/test/stripe/application_fee_refund_test.rb +2 -5
- data/test/stripe/application_fee_test.rb +0 -2
- data/test/stripe/bank_account_test.rb +8 -13
- data/test/stripe/bitcoin_receiver_test.rb +13 -16
- data/test/stripe/bitcoin_transaction_test.rb +2 -4
- data/test/stripe/charge_test.rb +9 -11
- data/test/stripe/country_spec_test.rb +2 -4
- data/test/stripe/coupon_test.rb +6 -8
- data/test/stripe/customer_card_test.rb +13 -9
- data/test/stripe/customer_test.rb +16 -18
- data/test/stripe/dispute_test.rb +8 -10
- data/test/stripe/file_upload_test.rb +3 -3
- data/test/stripe/invoice_item_test.rb +9 -11
- data/test/stripe/invoice_line_item_test.rb +0 -1
- data/test/stripe/invoice_test.rb +39 -21
- data/test/stripe/list_object_test.rb +1 -1
- data/test/stripe/login_link_test.rb +6 -7
- data/test/stripe/order_return_test.rb +2 -4
- data/test/stripe/order_test.rb +10 -12
- data/test/stripe/payout_test.rb +7 -9
- data/test/stripe/plan_test.rb +8 -10
- data/test/stripe/product_test.rb +8 -10
- data/test/stripe/recipient_card_test.rb +13 -9
- data/test/stripe/recipient_test.rb +8 -10
- data/test/stripe/refund_test.rb +7 -9
- data/test/stripe/reversal_test.rb +5 -7
- data/test/stripe/sku_test.rb +9 -11
- data/test/stripe/source_test.rb +16 -15
- data/test/stripe/stripe_client_test.rb +190 -26
- data/test/stripe/subscription_item_test.rb +12 -14
- data/test/stripe/subscription_test.rb +10 -12
- data/test/stripe/three_d_secure_test.rb +3 -5
- data/test/stripe/transfer_test.rb +7 -9
- data/test/stripe/util_test.rb +164 -0
- data/test/test_helper.rb +33 -18
- metadata +2 -8
- data/openapi/fixtures.json +0 -1896
- data/openapi/fixtures.yaml +0 -1505
- data/openapi/spec2.json +0 -24601
- data/openapi/spec2.yaml +0 -18801
- data/test/api_fixtures.rb +0 -29
data/lib/stripe/util.rb
CHANGED
@@ -89,6 +89,20 @@ module Stripe
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
def self.log_info(message, data = {})
|
93
|
+
if Stripe.log_level == Stripe::LEVEL_DEBUG ||Stripe.log_level == Stripe::LEVEL_INFO
|
94
|
+
log_internal(message, data, color: :cyan,
|
95
|
+
level: Stripe::LEVEL_INFO, out: $stdout)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.log_debug(message, data = {})
|
100
|
+
if Stripe.log_level == Stripe::LEVEL_DEBUG
|
101
|
+
log_internal(message, data, color: :blue,
|
102
|
+
level: Stripe::LEVEL_DEBUG, out: $stdout)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
92
106
|
def self.file_readable(file)
|
93
107
|
# This is nominally equivalent to File.readable?, but that can
|
94
108
|
# report incorrect results on some more oddball filesystems
|
@@ -220,8 +234,59 @@ module Stripe
|
|
220
234
|
key
|
221
235
|
end
|
222
236
|
|
237
|
+
# Normalizes header keys so that they're all lower case and each
|
238
|
+
# hyphen-delimited section starts with a single capitalized letter. For
|
239
|
+
# example, `request-id` becomes `Request-Id`. This is useful for extracting
|
240
|
+
# certain key values when the user could have set them with a variety of
|
241
|
+
# diffent naming schemes.
|
242
|
+
def self.normalize_headers(headers)
|
243
|
+
headers.inject({}) do |new_headers, (k, v)|
|
244
|
+
if k.is_a?(Symbol)
|
245
|
+
k = titlecase_parts(k.to_s.gsub("_", "-"))
|
246
|
+
elsif k.is_a?(String)
|
247
|
+
k = titlecase_parts(k)
|
248
|
+
end
|
249
|
+
|
250
|
+
new_headers[k] = v
|
251
|
+
new_headers
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Generates a Dashboard link to inspect a request ID based off of a request
|
256
|
+
# ID value and an API key, which is used to attempt to extract whether the
|
257
|
+
# environment is livemode or testmode.
|
258
|
+
def self.request_id_dashboard_url(request_id, api_key)
|
259
|
+
env = !api_key.nil? && api_key.start_with?("sk_live") ? "live" : "test"
|
260
|
+
"https://dashboard.stripe.com/#{env}/logs/#{request_id}"
|
261
|
+
end
|
262
|
+
|
263
|
+
# Constant time string comparison to prevent timing attacks
|
264
|
+
# Code borrowed from ActiveSupport
|
265
|
+
def self.secure_compare(a, b)
|
266
|
+
return false unless a.bytesize == b.bytesize
|
267
|
+
|
268
|
+
l = a.unpack "C#{a.bytesize}"
|
269
|
+
|
270
|
+
res = 0
|
271
|
+
b.each_byte { |byte| res |= byte ^ l.shift }
|
272
|
+
res == 0
|
273
|
+
end
|
274
|
+
|
223
275
|
private
|
224
276
|
|
277
|
+
COLOR_CODES = {
|
278
|
+
:black => 0, :light_black => 60,
|
279
|
+
:red => 1, :light_red => 61,
|
280
|
+
:green => 2, :light_green => 62,
|
281
|
+
:yellow => 3, :light_yellow => 63,
|
282
|
+
:blue => 4, :light_blue => 64,
|
283
|
+
:magenta => 5, :light_magenta => 65,
|
284
|
+
:cyan => 6, :light_cyan => 66,
|
285
|
+
:white => 7, :light_white => 67,
|
286
|
+
:default => 9
|
287
|
+
}
|
288
|
+
private_constant :COLOR_CODES
|
289
|
+
|
225
290
|
# We use a pretty janky version of form encoding (Rack's) that supports
|
226
291
|
# more complex data structures like maps and arrays through the use of
|
227
292
|
# specialized syntax. To encode an array of maps like:
|
@@ -258,17 +323,71 @@ module Stripe
|
|
258
323
|
end
|
259
324
|
end
|
260
325
|
end
|
326
|
+
private_class_method :check_array_of_maps_start_keys!
|
261
327
|
|
262
|
-
#
|
263
|
-
#
|
264
|
-
def self.
|
265
|
-
return
|
328
|
+
# Uses an ANSI escape code to colorize text if it's going to be sent to a
|
329
|
+
# TTY.
|
330
|
+
def self.colorize(val, color, isatty)
|
331
|
+
return val unless isatty
|
266
332
|
|
267
|
-
|
333
|
+
mode = 0 # default
|
334
|
+
foreground = 30 + COLOR_CODES.fetch(color)
|
335
|
+
background = 40 + COLOR_CODES.fetch(:default)
|
268
336
|
|
269
|
-
|
270
|
-
|
271
|
-
|
337
|
+
"\033[#{mode};#{foreground};#{background}m#{val}\033[0m"
|
338
|
+
end
|
339
|
+
private_class_method :colorize
|
340
|
+
|
341
|
+
# TODO: Make these named required arguments when we drop support for Ruby
|
342
|
+
# 2.0.
|
343
|
+
def self.log_internal(message, data = {}, color: nil, level: nil, out: nil)
|
344
|
+
data_str = data.select { |k,v| !v.nil? }.
|
345
|
+
map { |(k,v)|
|
346
|
+
"%s=%s" % [
|
347
|
+
colorize(k, color, out.isatty),
|
348
|
+
wrap_logfmt_value(v)
|
349
|
+
]
|
350
|
+
}.join(" ")
|
351
|
+
|
352
|
+
if out.isatty
|
353
|
+
out.puts "%s %s %s" %
|
354
|
+
[colorize(level[0, 4].upcase, color, out.isatty), message, data_str]
|
355
|
+
else
|
356
|
+
out.puts "message=%s level=%s %s" %
|
357
|
+
[wrap_logfmt_value(message), level, data_str]
|
358
|
+
end
|
359
|
+
end
|
360
|
+
private_class_method :log_internal
|
361
|
+
|
362
|
+
def self.titlecase_parts(s)
|
363
|
+
s.split("-").
|
364
|
+
select { |p| p != "" }.
|
365
|
+
map { |p| p[0].upcase + p[1..-1].downcase }.
|
366
|
+
join("-")
|
367
|
+
end
|
368
|
+
private_class_method :titlecase_parts
|
369
|
+
|
370
|
+
# Wraps a value in double quotes if it looks sufficiently complex so that
|
371
|
+
# it can be read by logfmt parsers.
|
372
|
+
def self.wrap_logfmt_value(val)
|
373
|
+
# If value is any kind of number, just allow it to be formatted directly
|
374
|
+
# to a string (this will handle integers or floats).
|
375
|
+
return val if val.is_a?(Numeric)
|
376
|
+
|
377
|
+
# Hopefully val is a string, but protect in case it's not.
|
378
|
+
val = val.to_s
|
379
|
+
|
380
|
+
if %r{[^\w\-/]} =~ val
|
381
|
+
# If the string contains any special characters, escape any double
|
382
|
+
# quotes it has, remove newlines, and wrap the whole thing in quotes.
|
383
|
+
%{"%s"} % val.gsub('"', '\"').gsub("\n", "")
|
384
|
+
else
|
385
|
+
# Otherwise use the basic value if it looks like a standard set of
|
386
|
+
# characters (and allow a few special characters like hyphens, and
|
387
|
+
# slashes)
|
388
|
+
val
|
389
|
+
end
|
272
390
|
end
|
391
|
+
private_class_method :wrap_logfmt_value
|
273
392
|
end
|
274
393
|
end
|
data/lib/stripe/version.rb
CHANGED
data/test/api_stub_helpers.rb
CHANGED
@@ -1,125 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
|
-
# Provides a set of helpers for a test suite that help to mock out the Stripe
|
4
|
-
# API.
|
5
|
-
module APIStubHelpers
|
6
|
-
protected
|
7
|
-
|
8
|
-
# Uses Webmock to stub out the Stripe API for testing purposes. The stub will
|
9
|
-
# by default respond on any routes that are defined in the bundled OpenAPI
|
10
|
-
# spec with generated response data.
|
11
|
-
#
|
12
|
-
# An `override_app` can be specified to get finer grain control over how a
|
13
|
-
# stubbed endpoint responds. It can be used to modify generated responses,
|
14
|
-
# mock expectations, or even to override the default stub completely.
|
15
|
-
def stub_api
|
16
|
-
stub_request(:any, /^#{Stripe.api_base}/).to_rack(new_api_stub)
|
17
|
-
end
|
18
|
-
|
19
|
-
def stub_connect
|
20
|
-
stub_request(:any, /^#{Stripe.connect_base}/).to_return(:body => "{}")
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
# APIStubMiddleware intercepts a response generated by Committee's stubbing
|
26
|
-
# middleware, and tries to replace it with a better version from a set of
|
27
|
-
# sample fixtures data generated from Stripe's core API service.
|
28
|
-
class APIStubMiddleware
|
29
|
-
API_FIXTURES = APIFixtures.new
|
30
|
-
|
31
|
-
def initialize(app)
|
32
|
-
@app = app
|
33
|
-
end
|
34
|
-
|
35
|
-
def call(env)
|
36
|
-
# We use a vendor specific prefix (`x-resourceId`) embedded in the schema
|
37
|
-
# of any resource in our spec to identify it (e.g. "charge"). This allows
|
38
|
-
# us to cross-reference that response with some data that we might find
|
39
|
-
# in our fixtures file so that we can respond with a higher fidelity
|
40
|
-
# response.
|
41
|
-
schema = env["committee.response_schema"]
|
42
|
-
resource_id = schema.data["x-resourceId"] || ""
|
43
|
-
|
44
|
-
if data = API_FIXTURES[resource_id.to_sym]
|
45
|
-
# standard top-level API resource
|
46
|
-
data = fixturize_lists_recursively(schema, data)
|
47
|
-
env["committee.response"] = data
|
48
|
-
elsif schema.properties["object"].enum == ["list"]
|
49
|
-
# top level list (like from a list endpoint)
|
50
|
-
data = fixturize_list(schema, env["committee.response"])
|
51
|
-
env["committee.response"] = data
|
52
|
-
else
|
53
|
-
raise "no fixture for: #{resource_id}"
|
54
|
-
end
|
55
|
-
@app.call(env)
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# If schema looks like a Stripe list object, then we look up the resource
|
61
|
-
# that the list is supposed to include and inject it into `data` as a
|
62
|
-
# fixture. Also calls into that other schema recursively so that sublists
|
63
|
-
# within it will also be assigned a fixture.
|
64
|
-
def fixturize_list(schema, data)
|
65
|
-
object_schema = schema.properties["object"]
|
66
|
-
if object_schema && object_schema.enum == ["list"]
|
67
|
-
subschema = schema.properties["data"].items
|
68
|
-
resource_id = subschema.data["x-resourceId"] || ""
|
69
|
-
if subdata = API_FIXTURES[resource_id.to_sym]
|
70
|
-
subdata = fixturize_lists_recursively(subschema, subdata)
|
71
|
-
|
72
|
-
data = data ? data.dup : {}
|
73
|
-
data[:data] = [subdata]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
data
|
77
|
-
end
|
78
|
-
|
79
|
-
# Examines each of the given schema's properties and calls #fixturize_list
|
80
|
-
# on them so that any sublists will be populated with sample fixture data.
|
81
|
-
def fixturize_lists_recursively(schema, data)
|
82
|
-
data = data.dup
|
83
|
-
schema.properties.each do |key, subschema|
|
84
|
-
data[key.to_sym] = fixturize_list(subschema, data[key.to_sym])
|
85
|
-
end
|
86
|
-
data
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# A descendant of the standard `Sinatra::Base` that we can use to enrich
|
91
|
-
# certain types of responses.
|
92
|
-
class APIStubApp < Sinatra::Base
|
93
|
-
not_found do
|
94
|
-
"endpoint not found in API stub: #{request.request_method} #{request.path_info}"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Finds the latest OpenAPI specification in ROOT/openapi/ and parses it for
|
99
|
-
# use with Committee.
|
100
|
-
def self.initialize_spec
|
101
|
-
spec_data = ::JSON.parse(File.read("#{PROJECT_ROOT}/openapi/spec2.json"))
|
102
|
-
|
103
|
-
driver = Committee::Drivers::OpenAPI2.new
|
104
|
-
driver.parse(spec_data)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Creates a new Rack app with Committee middleware it.
|
108
|
-
def new_api_stub
|
109
|
-
Rack::Builder.new {
|
110
|
-
use Committee::Middleware::RequestValidation, schema: @@spec,
|
111
|
-
params_response: true, strict: true
|
112
|
-
use Committee::Middleware::Stub, schema: @@spec,
|
113
|
-
call: true
|
114
|
-
use APIStubMiddleware
|
115
|
-
run APIStubApp.new
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
# Parse and initialize the OpenAPI spec only once for the entire test suite.
|
120
|
-
@@spec = initialize_spec
|
121
|
-
|
122
|
-
# The default override app. Doesn't respond on any route so generated
|
123
|
-
# responses will always take precedence.
|
124
|
-
@@default_override_app = Sinatra.new
|
125
|
-
end
|
data/test/stripe/account_test.rb
CHANGED
@@ -2,8 +2,6 @@ require File.expand_path('../../test_helper', __FILE__)
|
|
2
2
|
|
3
3
|
module Stripe
|
4
4
|
class AccountTest < Test::Unit::TestCase
|
5
|
-
FIXTURE = API_FIXTURES.fetch(:account)
|
6
|
-
|
7
5
|
should "be listable" do
|
8
6
|
accounts = Stripe::Account.list
|
9
7
|
assert_requested :get, "#{Stripe.api_base}/v1/accounts"
|
@@ -18,8 +16,8 @@ module Stripe
|
|
18
16
|
end
|
19
17
|
|
20
18
|
should "be retrievable using plural endpoint" do
|
21
|
-
account = Stripe::Account.retrieve(
|
22
|
-
assert_requested :get, "#{Stripe.api_base}/v1/accounts
|
19
|
+
account = Stripe::Account.retrieve("acct_123")
|
20
|
+
assert_requested :get, "#{Stripe.api_base}/v1/accounts/acct_123"
|
23
21
|
assert account.kind_of?(Stripe::Account)
|
24
22
|
end
|
25
23
|
|
@@ -42,22 +40,22 @@ module Stripe
|
|
42
40
|
end
|
43
41
|
|
44
42
|
should "be saveable" do
|
45
|
-
account = Stripe::Account.retrieve(
|
43
|
+
account = Stripe::Account.retrieve("acct_123")
|
46
44
|
account.metadata['key'] = 'value'
|
47
45
|
account.save
|
48
|
-
assert_requested :post, "#{Stripe.api_base}/v1/accounts/#{
|
46
|
+
assert_requested :post, "#{Stripe.api_base}/v1/accounts/#{account.id}"
|
49
47
|
end
|
50
48
|
|
51
49
|
should "be updateable" do
|
52
|
-
account = Stripe::Account.update(
|
53
|
-
assert_requested :post, "#{Stripe.api_base}/v1/accounts
|
50
|
+
account = Stripe::Account.update("acct_123", metadata: {foo: 'bar'})
|
51
|
+
assert_requested :post, "#{Stripe.api_base}/v1/accounts/acct_123"
|
54
52
|
assert account.kind_of?(Stripe::Account)
|
55
53
|
end
|
56
54
|
|
57
55
|
should "be deletable" do
|
58
|
-
account = Stripe::Account.retrieve(
|
56
|
+
account = Stripe::Account.retrieve("acct_123")
|
59
57
|
account = account.delete
|
60
|
-
assert_requested :delete, "#{Stripe.api_base}/v1/accounts/#{
|
58
|
+
assert_requested :delete, "#{Stripe.api_base}/v1/accounts/#{account.id}"
|
61
59
|
assert account.kind_of?(Stripe::Account)
|
62
60
|
end
|
63
61
|
|
@@ -66,7 +64,7 @@ module Stripe
|
|
66
64
|
old_stderr = $stderr
|
67
65
|
$stderr = StringIO.new
|
68
66
|
begin
|
69
|
-
account = Stripe::Account.retrieve(
|
67
|
+
account = Stripe::Account.retrieve("acct_123")
|
70
68
|
account.bank_account = "tok_123"
|
71
69
|
message = "NOTE: Stripe::Account#bank_account= is " +
|
72
70
|
"deprecated; use #external_account= instead"
|
@@ -79,7 +77,7 @@ module Stripe
|
|
79
77
|
|
80
78
|
context "#deauthorize" do
|
81
79
|
should "deauthorize an account" do
|
82
|
-
account = Stripe::Account.retrieve(
|
80
|
+
account = Stripe::Account.retrieve("acct_123")
|
83
81
|
|
84
82
|
# Unfortunately, the OpenAPI spec doesn't yet cover anything under the
|
85
83
|
# Connect endpoints, so for just stub this out with Webmock.
|
@@ -92,7 +90,7 @@ module Stripe
|
|
92
90
|
|
93
91
|
context "#legal_entity=" do
|
94
92
|
should 'disallow direct overrides' do
|
95
|
-
account = Stripe::Account.retrieve(
|
93
|
+
account = Stripe::Account.retrieve("acct_123")
|
96
94
|
|
97
95
|
assert_raise NoMethodError do
|
98
96
|
account.legal_entity = {:first_name => 'Blah'}
|
@@ -2,17 +2,15 @@ require File.expand_path('../../test_helper', __FILE__)
|
|
2
2
|
|
3
3
|
module Stripe
|
4
4
|
class AlipayAccountTest < Test::Unit::TestCase
|
5
|
-
FIXTURE = API_FIXTURES.fetch(:alipay_account)
|
6
|
-
|
7
5
|
should "raise on #retrieve" do
|
8
6
|
assert_raises NotImplementedError do
|
9
|
-
Stripe::AlipayAccount.retrieve
|
7
|
+
Stripe::AlipayAccount.retrieve("aliacc_123")
|
10
8
|
end
|
11
9
|
end
|
12
10
|
|
13
11
|
should "raise on #update" do
|
14
12
|
assert_raises NotImplementedError do
|
15
|
-
Stripe::AlipayAccount.update
|
13
|
+
Stripe::AlipayAccount.update("aliacc_123", {})
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
@@ -38,14 +38,14 @@ module Stripe
|
|
38
38
|
end
|
39
39
|
|
40
40
|
should "setting an attribute should not cause a network request" do
|
41
|
-
c = Stripe::Customer.new("
|
41
|
+
c = Stripe::Customer.new("cus_123");
|
42
42
|
c.card = {:id => "somecard", :object => "card"}
|
43
43
|
assert_not_requested :get, %r{#{Stripe.api_base}/.*}
|
44
44
|
assert_not_requested :post, %r{#{Stripe.api_base}/.*}
|
45
45
|
end
|
46
46
|
|
47
47
|
should "accessing id should not issue a fetch" do
|
48
|
-
c = Stripe::Customer.new("
|
48
|
+
c = Stripe::Customer.new("cus_123")
|
49
49
|
c.id
|
50
50
|
assert_not_requested :get, %r{#{Stripe.api_base}/.*}
|
51
51
|
end
|
@@ -53,7 +53,7 @@ module Stripe
|
|
53
53
|
should "not specifying api credentials should raise an exception" do
|
54
54
|
Stripe.api_key = nil
|
55
55
|
assert_raises Stripe::AuthenticationError do
|
56
|
-
Stripe::Customer.new("
|
56
|
+
Stripe::Customer.new("cus_123").refresh
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
@@ -69,36 +69,36 @@ module Stripe
|
|
69
69
|
should "specifying api credentials containing whitespace should raise an exception" do
|
70
70
|
Stripe.api_key = "key "
|
71
71
|
assert_raises Stripe::AuthenticationError do
|
72
|
-
Stripe::Customer.new("
|
72
|
+
Stripe::Customer.new("cus_123").refresh
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
should "send expand on fetch properly" do
|
77
|
-
stub_request(:get, "#{Stripe.api_base}/v1/charges/
|
77
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
|
78
78
|
with(query: { "expand" => ["customer"] }).
|
79
|
-
to_return(body: JSON.generate(
|
79
|
+
to_return(body: JSON.generate(charge_fixture))
|
80
80
|
|
81
|
-
Stripe::Charge.retrieve({:id => '
|
81
|
+
Stripe::Charge.retrieve({:id => 'ch_123', :expand => [:customer]})
|
82
82
|
end
|
83
83
|
|
84
84
|
should "preserve expand across refreshes" do
|
85
|
-
stub_request(:get, "#{Stripe.api_base}/v1/charges/
|
85
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
|
86
86
|
with(query: { "expand" => ["customer"] }).
|
87
|
-
to_return(body: JSON.generate(
|
87
|
+
to_return(body: JSON.generate(charge_fixture))
|
88
88
|
|
89
|
-
ch = Stripe::Charge.retrieve({:id => '
|
89
|
+
ch = Stripe::Charge.retrieve({:id => 'ch_123', :expand => :customer})
|
90
90
|
ch.refresh
|
91
91
|
end
|
92
92
|
|
93
93
|
should "send expand when fetching through ListObject" do
|
94
|
-
stub_request(:get, "#{Stripe.api_base}/v1/customers/
|
95
|
-
to_return(body: JSON.generate(
|
94
|
+
stub_request(:get, "#{Stripe.api_base}/v1/customers/cus_123").
|
95
|
+
to_return(body: JSON.generate(customer_fixture))
|
96
96
|
|
97
|
-
stub_request(:get, "#{Stripe.api_base}/v1/customers/
|
97
|
+
stub_request(:get, "#{Stripe.api_base}/v1/customers/cus_123/sources/cc_test_card").
|
98
98
|
with(query: { "expand" => ["customer"] }).
|
99
|
-
to_return(body: JSON.generate(
|
99
|
+
to_return(body: JSON.generate(customer_fixture))
|
100
100
|
|
101
|
-
customer = Stripe::Customer.retrieve('
|
101
|
+
customer = Stripe::Customer.retrieve('cus_123')
|
102
102
|
customer.sources.retrieve({:id => 'cc_test_card', :expand => :customer})
|
103
103
|
end
|
104
104
|
|
@@ -107,7 +107,7 @@ module Stripe
|
|
107
107
|
should "use the per-object credential when creating" do
|
108
108
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
109
109
|
with(headers: {"Authorization" => "Bearer sk_test_local"}).
|
110
|
-
to_return(body: JSON.generate(
|
110
|
+
to_return(body: JSON.generate(charge_fixture))
|
111
111
|
|
112
112
|
Stripe::Charge.create({:source => 'tok_visa'},
|
113
113
|
'sk_test_local')
|
@@ -125,22 +125,22 @@ module Stripe
|
|
125
125
|
|
126
126
|
should "use the per-object credential when creating" do
|
127
127
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
128
|
-
with(headers: {"Authorization" => "Bearer
|
129
|
-
to_return(body: JSON.generate(
|
128
|
+
with(headers: {"Authorization" => "Bearer sk_test_local"}).
|
129
|
+
to_return(body: JSON.generate(charge_fixture))
|
130
130
|
|
131
131
|
Stripe::Charge.create({:source => 'tok_visa'},
|
132
|
-
'
|
132
|
+
'sk_test_local')
|
133
133
|
end
|
134
134
|
|
135
135
|
should "use the per-object credential when retrieving and making other calls" do
|
136
|
-
stub_request(:get, "#{Stripe.api_base}/v1/charges/
|
137
|
-
with(headers: {"Authorization" => "Bearer
|
138
|
-
to_return(body: JSON.generate(
|
139
|
-
stub_request(:post, "#{Stripe.api_base}/v1/charges/
|
140
|
-
with(headers: {"Authorization" => "Bearer
|
141
|
-
to_return(body:
|
142
|
-
|
143
|
-
ch = Stripe::Charge.retrieve('
|
136
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
|
137
|
+
with(headers: {"Authorization" => "Bearer sk_test_local"}).
|
138
|
+
to_return(body: JSON.generate(charge_fixture))
|
139
|
+
stub_request(:post, "#{Stripe.api_base}/v1/charges/ch_123/refunds").
|
140
|
+
with(headers: {"Authorization" => "Bearer sk_test_local"}).
|
141
|
+
to_return(body: "{}")
|
142
|
+
|
143
|
+
ch = Stripe::Charge.retrieve('ch_123', 'sk_test_local')
|
144
144
|
ch.refunds.create
|
145
145
|
end
|
146
146
|
end
|
@@ -151,45 +151,45 @@ module Stripe
|
|
151
151
|
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
152
152
|
with(query: { customer: "test customer" }).
|
153
153
|
to_return(body: JSON.generate({
|
154
|
-
data: [
|
154
|
+
data: [charge_fixture]
|
155
155
|
}))
|
156
156
|
charges = Stripe::Charge.list(:customer => 'test customer').data
|
157
157
|
assert charges.kind_of? Array
|
158
158
|
end
|
159
159
|
|
160
160
|
should "construct URL properly with base query parameters" do
|
161
|
-
stub_request(:get, "#{Stripe.api_base}/v1/
|
162
|
-
with(query: { customer: "
|
161
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
162
|
+
with(query: { customer: "cus_123" }).
|
163
163
|
to_return(body: JSON.generate({
|
164
|
-
data: [
|
165
|
-
url: "/v1/
|
164
|
+
data: [charge_fixture],
|
165
|
+
url: "/v1/charges"
|
166
166
|
}))
|
167
|
-
|
167
|
+
charges = Stripe::Invoice.list(:customer => 'cus_123')
|
168
168
|
|
169
|
-
stub_request(:get, "#{Stripe.api_base}/v1/
|
170
|
-
with(query: { customer: "
|
169
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
170
|
+
with(query: { customer: "cus_123", created: "123" }).
|
171
171
|
to_return(body: JSON.generate({
|
172
|
-
data: [
|
173
|
-
url: "/v1/
|
172
|
+
data: [charge_fixture],
|
173
|
+
url: "/v1/charges"
|
174
174
|
}))
|
175
|
-
|
175
|
+
charges.list(:created => 123)
|
176
176
|
end
|
177
177
|
|
178
178
|
should "setting a nil value for a param should exclude that param from the request" do
|
179
179
|
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
180
180
|
with(query: { offset: 5, sad: false }).
|
181
|
-
to_return(body: JSON.generate({ :count => 1, :data => [
|
181
|
+
to_return(body: JSON.generate({ :count => 1, :data => [charge_fixture] }))
|
182
182
|
Stripe::Charge.list(:count => nil, :offset => 5, :sad => false)
|
183
183
|
|
184
184
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
185
185
|
with(body: { 'amount' => '50', 'currency' => 'usd' }).
|
186
|
-
to_return(body: JSON.generate({ :count => 1, :data => [
|
186
|
+
to_return(body: JSON.generate({ :count => 1, :data => [charge_fixture] }))
|
187
187
|
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
188
188
|
end
|
189
189
|
|
190
190
|
should "not trigger a warning if a known opt, such as idempotency_key, is in opts" do
|
191
191
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
192
|
-
to_return(body: JSON.generate(
|
192
|
+
to_return(body: JSON.generate(charge_fixture))
|
193
193
|
old_stderr = $stderr
|
194
194
|
$stderr = StringIO.new
|
195
195
|
begin
|
@@ -202,7 +202,7 @@ module Stripe
|
|
202
202
|
|
203
203
|
should "trigger a warning if a known opt, such as idempotency_key, is in params" do
|
204
204
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
205
|
-
to_return(body: JSON.generate(
|
205
|
+
to_return(body: JSON.generate(charge_fixture))
|
206
206
|
old_stderr = $stderr
|
207
207
|
$stderr = StringIO.new
|
208
208
|
begin
|
@@ -228,28 +228,28 @@ module Stripe
|
|
228
228
|
should "making a GET request with parameters should have a query string and no body" do
|
229
229
|
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
230
230
|
with(query: { limit: 1 }).
|
231
|
-
to_return(body: JSON.generate({ :data => [
|
231
|
+
to_return(body: JSON.generate({ :data => [charge_fixture] }))
|
232
232
|
Stripe::Charge.list({ :limit => 1 })
|
233
233
|
end
|
234
234
|
|
235
235
|
should "making a POST request with parameters should have a body and no query string" do
|
236
236
|
stub_request(:post, "#{Stripe.api_base}/v1/charges").
|
237
237
|
with(body: {'amount' => '100', 'currency' => 'usd', 'card' => 'sc_token'}).
|
238
|
-
to_return(body: JSON.generate(
|
238
|
+
to_return(body: JSON.generate(charge_fixture))
|
239
239
|
Stripe::Charge.create({ :amount => 100, :currency => 'usd', :card => 'sc_token' })
|
240
240
|
end
|
241
241
|
|
242
242
|
should "loading an object should issue a GET request" do
|
243
|
-
stub_request(:get, "#{Stripe.api_base}/v1/
|
244
|
-
to_return(body: JSON.generate(
|
245
|
-
c = Stripe::
|
243
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
|
244
|
+
to_return(body: JSON.generate(charge_fixture))
|
245
|
+
c = Stripe::Charge.new("ch_123")
|
246
246
|
c.refresh
|
247
247
|
end
|
248
248
|
|
249
249
|
should "using array accessors should be the same as the method interface" do
|
250
|
-
stub_request(:get, "#{Stripe.api_base}/v1/
|
251
|
-
to_return(body: JSON.generate(
|
252
|
-
c = Stripe::
|
250
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
|
251
|
+
to_return(body: JSON.generate(charge_fixture))
|
252
|
+
c = Stripe::Charge.new("cus_123")
|
253
253
|
c.refresh
|
254
254
|
assert_equal c.created, c[:created]
|
255
255
|
assert_equal c.created, c['created']
|
@@ -259,26 +259,26 @@ module Stripe
|
|
259
259
|
|
260
260
|
should "accessing a property other than id or parent on an unfetched object should fetch it" do
|
261
261
|
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
262
|
-
with(query: { customer: "
|
263
|
-
to_return(body: JSON.generate(
|
264
|
-
c = Stripe::Customer.new("
|
262
|
+
with(query: { customer: "cus_123" }).
|
263
|
+
to_return(body: JSON.generate(customer_fixture))
|
264
|
+
c = Stripe::Customer.new("cus_123")
|
265
265
|
c.charges
|
266
266
|
end
|
267
267
|
|
268
268
|
should "updating an object should issue a POST request with only the changed properties" do
|
269
|
-
stub_request(:post, "#{Stripe.api_base}/v1/customers/
|
269
|
+
stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123").
|
270
270
|
with(body: { 'description' => 'another_mn' }).
|
271
|
-
to_return(body: JSON.generate(
|
272
|
-
c = Stripe::Customer.construct_from(
|
271
|
+
to_return(body: JSON.generate(customer_fixture))
|
272
|
+
c = Stripe::Customer.construct_from(customer_fixture)
|
273
273
|
c.description = "another_mn"
|
274
274
|
c.save
|
275
275
|
end
|
276
276
|
|
277
277
|
should "updating should merge in returned properties" do
|
278
|
-
stub_request(:post, "#{Stripe.api_base}/v1/customers/
|
278
|
+
stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123").
|
279
279
|
with(body: { 'description' => 'another_mn' }).
|
280
|
-
to_return(body: JSON.generate(
|
281
|
-
c = Stripe::Customer.new("
|
280
|
+
to_return(body: JSON.generate(customer_fixture))
|
281
|
+
c = Stripe::Customer.new("cus_123")
|
282
282
|
c.description = "another_mn"
|
283
283
|
c.save
|
284
284
|
assert_equal false, c.livemode
|
@@ -294,23 +294,23 @@ module Stripe
|
|
294
294
|
should "updating should use the supplied api_key" do
|
295
295
|
stub_request(:post, "#{Stripe.api_base}/v1/customers").
|
296
296
|
with(headers: {"Authorization" => "Bearer sk_test_local"}).
|
297
|
-
to_return(body: JSON.generate(
|
297
|
+
to_return(body: JSON.generate(customer_fixture))
|
298
298
|
c = Stripe::Customer.new
|
299
299
|
c.save({}, { :api_key => 'sk_test_local' })
|
300
300
|
assert_equal false, c.livemode
|
301
301
|
end
|
302
302
|
|
303
303
|
should "deleting should send no props and result in an object that has no props other deleted" do
|
304
|
-
stub_request(:delete, "#{Stripe.api_base}/v1/customers/
|
305
|
-
to_return(body: JSON.generate({ "id" => "
|
306
|
-
c = Stripe::Customer.construct_from(
|
304
|
+
stub_request(:delete, "#{Stripe.api_base}/v1/customers/cus_123").
|
305
|
+
to_return(body: JSON.generate({ "id" => "cus_123", "deleted" => true }))
|
306
|
+
c = Stripe::Customer.construct_from(customer_fixture)
|
307
307
|
c.delete
|
308
308
|
end
|
309
309
|
|
310
310
|
should "loading all of an APIResource should return an array of recursively instantiated objects" do
|
311
311
|
stub_request(:get, "#{Stripe.api_base}/v1/charges").
|
312
312
|
to_return(body: JSON.generate({
|
313
|
-
data: [
|
313
|
+
data: [charge_fixture]
|
314
314
|
}))
|
315
315
|
charges = Stripe::Charge.list.data
|
316
316
|
assert charges.kind_of? Array
|
@@ -319,21 +319,21 @@ module Stripe
|
|
319
319
|
end
|
320
320
|
|
321
321
|
should "passing in a stripe_account header should pass it through on call" do
|
322
|
-
stub_request(:get, "#{Stripe.api_base}/v1/customers/
|
323
|
-
with(headers: {"Stripe-Account" => "
|
324
|
-
to_return(body: JSON.generate(
|
325
|
-
Stripe::Customer.retrieve("
|
322
|
+
stub_request(:get, "#{Stripe.api_base}/v1/customers/cus_123").
|
323
|
+
with(headers: {"Stripe-Account" => "acct_123"}).
|
324
|
+
to_return(body: JSON.generate(customer_fixture))
|
325
|
+
Stripe::Customer.retrieve("cus_123", {:stripe_account => 'acct_123'})
|
326
326
|
end
|
327
327
|
|
328
328
|
should "passing in a stripe_account header should pass it through on save" do
|
329
|
-
stub_request(:get, "#{Stripe.api_base}/v1/customers/
|
330
|
-
with(headers: {"Stripe-Account" => "
|
331
|
-
to_return(body: JSON.generate(
|
332
|
-
c = Stripe::Customer.retrieve("
|
333
|
-
|
334
|
-
stub_request(:post, "#{Stripe.api_base}/v1/customers/
|
335
|
-
with(headers: {"Stripe-Account" => "
|
336
|
-
to_return(body: JSON.generate(
|
329
|
+
stub_request(:get, "#{Stripe.api_base}/v1/customers/cus_123").
|
330
|
+
with(headers: {"Stripe-Account" => "acct_123"}).
|
331
|
+
to_return(body: JSON.generate(customer_fixture))
|
332
|
+
c = Stripe::Customer.retrieve("cus_123", {:stripe_account => 'acct_123'})
|
333
|
+
|
334
|
+
stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123").
|
335
|
+
with(headers: {"Stripe-Account" => "acct_123"}).
|
336
|
+
to_return(body: JSON.generate(customer_fixture))
|
337
337
|
c.description = 'FOO'
|
338
338
|
c.save
|
339
339
|
end
|
@@ -518,5 +518,41 @@ module Stripe
|
|
518
518
|
account.save(:display_name => 'stripe', :metadata => {:key => 'value' })
|
519
519
|
end
|
520
520
|
end
|
521
|
+
|
522
|
+
@@fixtures = {}
|
523
|
+
setup do
|
524
|
+
if @@fixtures.empty?
|
525
|
+
set_fixture(:charge) do
|
526
|
+
Charge.retrieve("ch_123")
|
527
|
+
end
|
528
|
+
set_fixture(:customer) do
|
529
|
+
Customer.retrieve("cus_123")
|
530
|
+
end
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
private
|
535
|
+
|
536
|
+
def charge_fixture
|
537
|
+
@@fixtures[:charge]
|
538
|
+
end
|
539
|
+
|
540
|
+
def customer_fixture
|
541
|
+
@@fixtures[:customer]
|
542
|
+
end
|
543
|
+
|
544
|
+
def get_fixture(key)
|
545
|
+
@@fixtures.fetch(key)
|
546
|
+
end
|
547
|
+
|
548
|
+
# Expects to retrieve a fixture from stripe-mock (an API call should be
|
549
|
+
# included in the block to yield to) and does very simple memoization.
|
550
|
+
def set_fixture(key)
|
551
|
+
return @@fixtures[key] if @@fixtures.key?(key)
|
552
|
+
|
553
|
+
obj = yield
|
554
|
+
@@fixtures[key] = obj.instance_variable_get(:@values).freeze
|
555
|
+
@@fixtures[key]
|
556
|
+
end
|
521
557
|
end
|
522
558
|
end
|