stripe 1.18.0 → 1.30.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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +11 -1
- data/History.txt +98 -0
- data/README.rdoc +19 -10
- data/VERSION +1 -1
- data/lib/stripe/account.rb +46 -4
- data/lib/stripe/api_operations/create.rb +3 -10
- data/lib/stripe/api_operations/delete.rb +4 -4
- data/lib/stripe/api_operations/list.rb +17 -9
- data/lib/stripe/api_operations/request.rb +41 -0
- data/lib/stripe/api_operations/update.rb +41 -40
- data/lib/stripe/api_resource.rb +7 -4
- data/lib/stripe/application_fee.rb +3 -4
- data/lib/stripe/application_fee_refund.rb +1 -1
- data/lib/stripe/balance_transaction.rb +1 -1
- data/lib/stripe/bank_account.rb +19 -0
- data/lib/stripe/bitcoin_receiver.rb +12 -2
- data/lib/stripe/bitcoin_transaction.rb +5 -0
- data/lib/stripe/card.rb +6 -4
- data/lib/stripe/charge.rb +14 -22
- data/lib/stripe/coupon.rb +2 -2
- data/lib/stripe/customer.rb +24 -26
- data/lib/stripe/dispute.rb +16 -0
- data/lib/stripe/errors/card_error.rb +3 -2
- data/lib/stripe/errors/invalid_request_error.rb +3 -2
- data/lib/stripe/errors/rate_limit_error.rb +4 -0
- data/lib/stripe/errors/stripe_error.rb +8 -2
- data/lib/stripe/event.rb +1 -1
- data/lib/stripe/file_upload.rb +12 -22
- data/lib/stripe/invoice.rb +8 -8
- data/lib/stripe/invoice_item.rb +2 -2
- data/lib/stripe/list_object.rb +77 -13
- data/lib/stripe/order.rb +19 -0
- data/lib/stripe/plan.rb +2 -2
- data/lib/stripe/product.rb +16 -0
- data/lib/stripe/recipient.rb +2 -2
- data/lib/stripe/refund.rb +2 -9
- data/lib/stripe/reversal.rb +14 -0
- data/lib/stripe/singleton_api_resource.rb +2 -2
- data/lib/stripe/sku.rb +8 -0
- data/lib/stripe/stripe_object.rb +232 -46
- data/lib/stripe/subscription.rb +3 -3
- data/lib/stripe/token.rb +1 -1
- data/lib/stripe/transfer.rb +3 -3
- data/lib/stripe/util.rb +64 -21
- data/lib/stripe/version.rb +1 -1
- data/lib/stripe.rb +102 -67
- data/stripe.gemspec +0 -2
- data/test/stripe/account_test.rb +135 -6
- data/test/stripe/api_resource_test.rb +326 -42
- data/test/stripe/application_fee_refund_test.rb +6 -6
- data/test/stripe/application_fee_test.rb +3 -3
- data/test/stripe/balance_test.rb +11 -0
- data/test/stripe/bitcoin_receiver_test.rb +30 -7
- data/test/stripe/bitcoin_transaction_test.rb +29 -0
- data/test/stripe/charge_refund_test.rb +55 -0
- data/test/stripe/charge_test.rb +32 -13
- data/test/stripe/coupon_test.rb +3 -3
- data/test/stripe/customer_card_test.rb +20 -14
- data/test/stripe/customer_test.rb +15 -15
- data/test/stripe/dispute_test.rb +45 -0
- data/test/stripe/file_upload_test.rb +17 -6
- data/test/stripe/invoice_test.rb +18 -4
- data/test/stripe/list_object_test.rb +126 -2
- data/test/stripe/metadata_test.rb +28 -13
- data/test/stripe/order_test.rb +52 -0
- data/test/stripe/product_test.rb +41 -0
- data/test/stripe/recipient_card_test.rb +9 -9
- data/test/stripe/refund_test.rb +23 -15
- data/test/stripe/reversal_test.rb +47 -0
- data/test/stripe/sku_test.rb +24 -0
- data/test/stripe/stripe_object_test.rb +67 -6
- data/test/stripe/subscription_test.rb +13 -13
- data/test/stripe/transfer_test.rb +4 -4
- data/test/stripe/util_test.rb +45 -29
- data/test/stripe_test.rb +16 -0
- data/test/test_data.rb +273 -66
- metadata +47 -76
- data/lib/stripe/certificate_blacklist.rb +0 -55
- data/test/stripe/certificate_blacklist_test.rb +0 -18
data/lib/stripe/stripe_object.rb
CHANGED
@@ -2,25 +2,16 @@ module Stripe
|
|
2
2
|
class StripeObject
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
|
6
|
-
@@permanent_attributes = Set.new([:api_key, :id])
|
5
|
+
@@permanent_attributes = Set.new([:id])
|
7
6
|
|
8
7
|
# The default :id method is deprecated and isn't useful to us
|
9
8
|
if method_defined?(:id)
|
10
9
|
undef :id
|
11
10
|
end
|
12
11
|
|
13
|
-
def initialize(id=nil,
|
14
|
-
|
15
|
-
|
16
|
-
@retrieve_options = id.dup
|
17
|
-
@retrieve_options.delete(:id)
|
18
|
-
id = id[:id]
|
19
|
-
else
|
20
|
-
@retrieve_options = {}
|
21
|
-
end
|
22
|
-
|
23
|
-
@api_key = api_key
|
12
|
+
def initialize(id=nil, opts={})
|
13
|
+
id, @retrieve_params = Util.normalize_id(id)
|
14
|
+
@opts = Util.normalize_opts(opts)
|
24
15
|
@values = {}
|
25
16
|
# This really belongs in APIResource, but not putting it there allows us
|
26
17
|
# to have a unified inspect method
|
@@ -29,8 +20,25 @@ module Stripe
|
|
29
20
|
@values[:id] = id if id
|
30
21
|
end
|
31
22
|
|
32
|
-
def self.construct_from(values,
|
33
|
-
|
23
|
+
def self.construct_from(values, opts={})
|
24
|
+
values = Stripe::Util.symbolize_names(values)
|
25
|
+
|
26
|
+
# work around protected #initialize_from for now
|
27
|
+
self.new(values[:id]).send(:initialize_from, values, opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Determines the equality of two Stripe objects. Stripe objects are
|
31
|
+
# considered to be equal if they have the same set of values and each one
|
32
|
+
# of those values is the same.
|
33
|
+
def ==(other)
|
34
|
+
@values == other.instance_variable_get(:@values)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Indicates whether or not the resource has been deleted on the server.
|
38
|
+
# Note that some, but not all, resources can indicate whether they have
|
39
|
+
# been deleted.
|
40
|
+
def deleted?
|
41
|
+
@values.fetch(:deleted, false)
|
34
42
|
end
|
35
43
|
|
36
44
|
def to_s(*args)
|
@@ -42,32 +50,36 @@ module Stripe
|
|
42
50
|
"#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
|
43
51
|
end
|
44
52
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
# Re-initializes the object based on a hash of values (usually one that's
|
54
|
+
# come back from an API call). Adds or removes value accessors as necessary
|
55
|
+
# and updates the state of internal data.
|
56
|
+
#
|
57
|
+
# Please don't use this method. If you're trying to do mass assignment, try
|
58
|
+
# #initialize_from instead.
|
59
|
+
def refresh_from(values, opts, partial=false)
|
60
|
+
initialize_from(values, opts, partial)
|
61
|
+
end
|
62
|
+
extend Gem::Deprecate
|
63
|
+
deprecate :refresh_from, "#update_attributes", 2016, 01
|
54
64
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
65
|
+
# Mass assigns attributes on the model.
|
66
|
+
#
|
67
|
+
# This is a version of +update_attributes+ that takes some extra options
|
68
|
+
# for internal use.
|
69
|
+
#
|
70
|
+
# ==== Attributes
|
71
|
+
#
|
72
|
+
# * +values+ - Hash of values to use to update the current attributes of
|
73
|
+
# the object.
|
74
|
+
#
|
75
|
+
# ==== Options
|
76
|
+
#
|
77
|
+
# * +:opts+ Options for StripeObject like an API key.
|
78
|
+
def update_attributes(values, opts = {})
|
64
79
|
values.each do |k, v|
|
65
|
-
@values[k] = Util.convert_to_stripe_object(v,
|
66
|
-
@
|
67
|
-
@unsaved_values.delete(k)
|
80
|
+
@values[k] = Util.convert_to_stripe_object(v, opts)
|
81
|
+
@unsaved_values.add(k)
|
68
82
|
end
|
69
|
-
|
70
|
-
return self
|
71
83
|
end
|
72
84
|
|
73
85
|
def [](k)
|
@@ -95,8 +107,17 @@ module Stripe
|
|
95
107
|
end
|
96
108
|
|
97
109
|
def to_hash
|
110
|
+
maybe_to_hash = lambda do |value|
|
111
|
+
value.respond_to?(:to_hash) ? value.to_hash : value
|
112
|
+
end
|
113
|
+
|
98
114
|
@values.inject({}) do |acc, (key, value)|
|
99
|
-
acc[key] =
|
115
|
+
acc[key] = case value
|
116
|
+
when Array
|
117
|
+
value.map(&maybe_to_hash)
|
118
|
+
else
|
119
|
+
maybe_to_hash.call(value)
|
120
|
+
end
|
100
121
|
acc
|
101
122
|
end
|
102
123
|
end
|
@@ -106,12 +127,12 @@ module Stripe
|
|
106
127
|
end
|
107
128
|
|
108
129
|
def _dump(level)
|
109
|
-
Marshal.dump([@values, @
|
130
|
+
Marshal.dump([@values, @opts])
|
110
131
|
end
|
111
132
|
|
112
133
|
def self._load(args)
|
113
|
-
values,
|
114
|
-
construct_from(values,
|
134
|
+
values, opts = Marshal.load(args)
|
135
|
+
construct_from(values, opts)
|
115
136
|
end
|
116
137
|
|
117
138
|
if RUBY_VERSION < '1.9.2'
|
@@ -120,15 +141,96 @@ module Stripe
|
|
120
141
|
end
|
121
142
|
end
|
122
143
|
|
144
|
+
def serialize_nested_object(key)
|
145
|
+
new_value = @values[key]
|
146
|
+
if new_value.is_a?(APIResource)
|
147
|
+
return {}
|
148
|
+
end
|
149
|
+
|
150
|
+
if @unsaved_values.include?(key)
|
151
|
+
# the object has been reassigned
|
152
|
+
# e.g. as object.key = {foo => bar}
|
153
|
+
update = new_value
|
154
|
+
new_keys = update.keys.map(&:to_sym)
|
155
|
+
|
156
|
+
# remove keys at the server, but not known locally
|
157
|
+
if @original_values[key]
|
158
|
+
keys_to_unset = @original_values[key].keys - new_keys
|
159
|
+
keys_to_unset.each {|key| update[key] = ''}
|
160
|
+
end
|
161
|
+
|
162
|
+
update
|
163
|
+
else
|
164
|
+
# can be serialized normally
|
165
|
+
self.class.serialize_params(new_value)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.serialize_params(obj, original_value=nil)
|
170
|
+
case obj
|
171
|
+
when nil
|
172
|
+
''
|
173
|
+
when StripeObject
|
174
|
+
unsaved_keys = obj.instance_variable_get(:@unsaved_values)
|
175
|
+
obj_values = obj.instance_variable_get(:@values)
|
176
|
+
update_hash = {}
|
177
|
+
|
178
|
+
unsaved_keys.each do |k|
|
179
|
+
update_hash[k] = serialize_params(obj_values[k])
|
180
|
+
end
|
181
|
+
|
182
|
+
obj_values.each do |k, v|
|
183
|
+
if v.is_a?(StripeObject) || v.is_a?(Hash)
|
184
|
+
update_hash[k] = obj.serialize_nested_object(k)
|
185
|
+
elsif v.is_a?(Array)
|
186
|
+
original_value = obj.instance_variable_get(:@original_values)[k]
|
187
|
+
if original_value && original_value.length > v.length
|
188
|
+
# url params provide no mechanism for deleting an item in an array,
|
189
|
+
# just overwriting the whole array or adding new items. So let's not
|
190
|
+
# allow deleting without a full overwrite until we have a solution.
|
191
|
+
raise ArgumentError.new(
|
192
|
+
"You cannot delete an item from an array, you must instead set a new array"
|
193
|
+
)
|
194
|
+
end
|
195
|
+
update_hash[k] = serialize_params(v, original_value)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
update_hash
|
200
|
+
when Array
|
201
|
+
update_hash = {}
|
202
|
+
obj.each_with_index do |value, index|
|
203
|
+
update = serialize_params(value)
|
204
|
+
if update != {} && (!original_value || update != original_value[index])
|
205
|
+
update_hash[index] = update
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
if update_hash == {}
|
210
|
+
nil
|
211
|
+
else
|
212
|
+
update_hash
|
213
|
+
end
|
214
|
+
else
|
215
|
+
obj
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
123
219
|
protected
|
124
220
|
|
125
221
|
def metaclass
|
126
222
|
class << self; self; end
|
127
223
|
end
|
128
224
|
|
225
|
+
def protected_fields
|
226
|
+
[]
|
227
|
+
end
|
228
|
+
|
129
229
|
def remove_accessors(keys)
|
230
|
+
f = protected_fields
|
130
231
|
metaclass.instance_eval do
|
131
232
|
keys.each do |k|
|
233
|
+
next if f.include?(k)
|
132
234
|
next if @@permanent_attributes.include?(k)
|
133
235
|
k_eq = :"#{k}="
|
134
236
|
remove_method(k) if method_defined?(k)
|
@@ -137,22 +239,29 @@ module Stripe
|
|
137
239
|
end
|
138
240
|
end
|
139
241
|
|
140
|
-
def add_accessors(keys)
|
242
|
+
def add_accessors(keys, values)
|
243
|
+
f = protected_fields
|
141
244
|
metaclass.instance_eval do
|
142
245
|
keys.each do |k|
|
246
|
+
next if f.include?(k)
|
143
247
|
next if @@permanent_attributes.include?(k)
|
144
248
|
k_eq = :"#{k}="
|
145
249
|
define_method(k) { @values[k] }
|
146
250
|
define_method(k_eq) do |v|
|
147
251
|
if v == ""
|
148
252
|
raise ArgumentError.new(
|
149
|
-
"You cannot set #{k} to an empty string."
|
150
|
-
"We interpret empty strings as nil in requests."
|
253
|
+
"You cannot set #{k} to an empty string." \
|
254
|
+
"We interpret empty strings as nil in requests." \
|
151
255
|
"You may set #{self}.#{k} = nil to delete the property.")
|
152
256
|
end
|
153
257
|
@values[k] = v
|
154
258
|
@unsaved_values.add(k)
|
155
259
|
end
|
260
|
+
|
261
|
+
if [FalseClass, TrueClass].include?(values[k].class)
|
262
|
+
k_bool = :"#{k}?"
|
263
|
+
define_method(k_bool) { @values[k] }
|
264
|
+
end
|
156
265
|
end
|
157
266
|
end
|
158
267
|
end
|
@@ -161,7 +270,10 @@ module Stripe
|
|
161
270
|
# TODO: only allow setting in updateable classes.
|
162
271
|
if name.to_s.end_with?('=')
|
163
272
|
attr = name.to_s[0...-1].to_sym
|
164
|
-
|
273
|
+
|
274
|
+
# the second argument is only required when adding boolean accessors
|
275
|
+
add_accessors([attr], {})
|
276
|
+
|
165
277
|
begin
|
166
278
|
mth = method(name)
|
167
279
|
rescue NameError
|
@@ -186,5 +298,79 @@ module Stripe
|
|
186
298
|
def respond_to_missing?(symbol, include_private = false)
|
187
299
|
@values && @values.has_key?(symbol) || super
|
188
300
|
end
|
301
|
+
|
302
|
+
# Re-initializes the object based on a hash of values (usually one that's
|
303
|
+
# come back from an API call). Adds or removes value accessors as necessary
|
304
|
+
# and updates the state of internal data.
|
305
|
+
#
|
306
|
+
# Protected on purpose! Please do not expose.
|
307
|
+
#
|
308
|
+
# ==== Options
|
309
|
+
#
|
310
|
+
# * +:values:+ Hash used to update accessors and values.
|
311
|
+
# * +:opts:+ Options for StripeObject like an API key.
|
312
|
+
# * +:partial:+ Indicates that the re-initialization should not attempt to
|
313
|
+
# remove accessors.
|
314
|
+
def initialize_from(values, opts, partial=false)
|
315
|
+
@opts = Util.normalize_opts(opts)
|
316
|
+
@original_values = Marshal.load(Marshal.dump(values)) # deep copy
|
317
|
+
|
318
|
+
removed = partial ? Set.new : Set.new(@values.keys - values.keys)
|
319
|
+
added = Set.new(values.keys - @values.keys)
|
320
|
+
|
321
|
+
# Wipe old state before setting new. This is useful for e.g. updating a
|
322
|
+
# customer, where there is no persistent card parameter. Mark those values
|
323
|
+
# which don't persist as transient
|
324
|
+
|
325
|
+
instance_eval do
|
326
|
+
remove_accessors(removed)
|
327
|
+
add_accessors(added, values)
|
328
|
+
end
|
329
|
+
|
330
|
+
removed.each do |k|
|
331
|
+
@values.delete(k)
|
332
|
+
@transient_values.add(k)
|
333
|
+
@unsaved_values.delete(k)
|
334
|
+
end
|
335
|
+
|
336
|
+
update_attributes(values, :opts => opts)
|
337
|
+
values.each do |k, _|
|
338
|
+
@transient_values.delete(k)
|
339
|
+
@unsaved_values.delete(k)
|
340
|
+
end
|
341
|
+
|
342
|
+
self
|
343
|
+
end
|
344
|
+
|
345
|
+
# Mass assigns attributes on the model.
|
346
|
+
#
|
347
|
+
# This is a version of +update_attributes+ that takes some extra options
|
348
|
+
# for internal use.
|
349
|
+
#
|
350
|
+
# ==== Options
|
351
|
+
#
|
352
|
+
# * +:opts:+ Options for StripeObject like an API key.
|
353
|
+
# * +:raise_error:+ Set to false to suppress ArgumentErrors on keys that
|
354
|
+
# don't exist.
|
355
|
+
def update_attributes_with_options(values, options={})
|
356
|
+
# `opts` are StripeObject options
|
357
|
+
opts = options.fetch(:opts, {})
|
358
|
+
raise_error = options.fetch(:raise_error, true)
|
359
|
+
|
360
|
+
values.each do |k, v|
|
361
|
+
if !@@permanent_attributes.include?(k) && !self.respond_to?(:"#{k}=")
|
362
|
+
if raise_error
|
363
|
+
raise ArgumentError,
|
364
|
+
"#{k} is not an attribute that can be assigned on this object"
|
365
|
+
else
|
366
|
+
next
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
@values[k] = Util.convert_to_stripe_object(v, opts)
|
371
|
+
@unsaved_values.add(k)
|
372
|
+
end
|
373
|
+
self
|
374
|
+
end
|
189
375
|
end
|
190
376
|
end
|
data/lib/stripe/subscription.rb
CHANGED
@@ -7,13 +7,13 @@ module Stripe
|
|
7
7
|
"#{Customer.url}/#{CGI.escape(customer)}/subscriptions/#{CGI.escape(id)}"
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.retrieve(id,
|
10
|
+
def self.retrieve(id, opts=nil)
|
11
11
|
raise NotImplementedError.new("Subscriptions cannot be retrieved without a customer ID. Retrieve a subscription using customer.subscriptions.retrieve('subscription_id')")
|
12
12
|
end
|
13
13
|
|
14
14
|
def delete_discount
|
15
|
-
|
16
|
-
|
15
|
+
response, opts = request(:delete, discount_url)
|
16
|
+
initialize_from({ :discount => nil }, opts, true)
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
data/lib/stripe/token.rb
CHANGED
data/lib/stripe/transfer.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Stripe
|
2
2
|
class Transfer < APIResource
|
3
|
-
|
4
|
-
|
3
|
+
extend Stripe::APIOperations::List
|
4
|
+
extend Stripe::APIOperations::Create
|
5
5
|
include Stripe::APIOperations::Update
|
6
6
|
|
7
7
|
def cancel
|
8
8
|
response, api_key = Stripe.request(:post, cancel_url, @api_key)
|
9
|
-
|
9
|
+
initialize_from(response, api_key)
|
10
10
|
end
|
11
11
|
|
12
12
|
def cancel_url
|
data/lib/stripe/util.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
1
3
|
module Stripe
|
2
4
|
module Util
|
3
5
|
def self.objects_to_ids(h)
|
@@ -21,9 +23,11 @@ module Stripe
|
|
21
23
|
'list' => ListObject,
|
22
24
|
|
23
25
|
# business objects
|
26
|
+
'account' => Account,
|
24
27
|
'application_fee' => ApplicationFee,
|
25
28
|
'balance' => Balance,
|
26
29
|
'balance_transaction' => BalanceTransaction,
|
30
|
+
'bank_account' => BankAccount,
|
27
31
|
'card' => Card,
|
28
32
|
'charge' => Charge,
|
29
33
|
'coupon' => Coupon,
|
@@ -37,19 +41,25 @@ module Stripe
|
|
37
41
|
'refund' => Refund,
|
38
42
|
'subscription' => Subscription,
|
39
43
|
'file_upload' => FileUpload,
|
44
|
+
'token' => Token,
|
40
45
|
'transfer' => Transfer,
|
46
|
+
'transfer_reversal' => Reversal,
|
41
47
|
'bitcoin_receiver' => BitcoinReceiver,
|
42
|
-
'bitcoin_transaction' => BitcoinTransaction
|
48
|
+
'bitcoin_transaction' => BitcoinTransaction,
|
49
|
+
'dispute' => Dispute,
|
50
|
+
'product' => Product,
|
51
|
+
'sku' => SKU,
|
52
|
+
'order' => Order,
|
43
53
|
}
|
44
54
|
end
|
45
55
|
|
46
|
-
def self.convert_to_stripe_object(resp,
|
56
|
+
def self.convert_to_stripe_object(resp, opts)
|
47
57
|
case resp
|
48
58
|
when Array
|
49
|
-
resp.map { |i| convert_to_stripe_object(i,
|
59
|
+
resp.map { |i| convert_to_stripe_object(i, opts) }
|
50
60
|
when Hash
|
51
61
|
# Try converting to a known object class. If none available, fall back to generic StripeObject
|
52
|
-
object_classes.fetch(resp[:object], StripeObject).construct_from(resp,
|
62
|
+
object_classes.fetch(resp[:object], StripeObject).construct_from(resp, opts)
|
53
63
|
else
|
54
64
|
resp
|
55
65
|
end
|
@@ -84,14 +94,30 @@ module Stripe
|
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
97
|
+
# Encodes a hash of parameters in a way that's suitable for use as query
|
98
|
+
# parameters in a URI or as form parameters in a request body. This mainly
|
99
|
+
# involves escaping special characters from parameter keys and values (e.g.
|
100
|
+
# `&`).
|
101
|
+
def self.encode_parameters(params)
|
102
|
+
Util.flatten_params(params).
|
103
|
+
map { |k,v| "#{url_encode(k)}=#{url_encode(v)}" }.join('&')
|
104
|
+
end
|
105
|
+
|
106
|
+
# Encodes a string in a way that makes it suitable for use in a set of
|
107
|
+
# query parameters in a URI or in a set of form parameters in a request
|
108
|
+
# body.
|
87
109
|
def self.url_encode(key)
|
88
|
-
|
110
|
+
CGI.escape(key.to_s).
|
111
|
+
# Don't use strict form encoding by changing the square bracket control
|
112
|
+
# characters back to their literals. This is fine by the server, and
|
113
|
+
# makes these parameter strings easier to read.
|
114
|
+
gsub('%5B', '[').gsub('%5D', ']')
|
89
115
|
end
|
90
116
|
|
91
117
|
def self.flatten_params(params, parent_key=nil)
|
92
118
|
result = []
|
93
119
|
params.each do |key, value|
|
94
|
-
calculated_key = parent_key ? "#{parent_key}[#{
|
120
|
+
calculated_key = parent_key ? "#{parent_key}[#{key}]" : "#{key}"
|
95
121
|
if value.is_a?(Hash)
|
96
122
|
result += flatten_params(value, calculated_key)
|
97
123
|
elsif value.is_a?(Array)
|
@@ -100,14 +126,19 @@ module Stripe
|
|
100
126
|
result << [calculated_key, value]
|
101
127
|
end
|
102
128
|
end
|
103
|
-
|
129
|
+
|
130
|
+
# The #sort_by call here is mostly so that we can get some stability in
|
131
|
+
# our 1.8.7 test suite where Hash key order is not preserved.
|
132
|
+
#
|
133
|
+
# https://www.igvita.com/2009/02/04/ruby-19-internals-ordered-hash/
|
134
|
+
result.sort_by { |(k, _)| k }
|
104
135
|
end
|
105
136
|
|
106
137
|
def self.flatten_params_array(value, calculated_key)
|
107
138
|
result = []
|
108
139
|
value.each do |elem|
|
109
140
|
if elem.is_a?(Hash)
|
110
|
-
result += flatten_params(elem, calculated_key)
|
141
|
+
result += flatten_params(elem, "#{calculated_key}[]")
|
111
142
|
elsif elem.is_a?(Array)
|
112
143
|
result += flatten_params_array(elem, calculated_key)
|
113
144
|
else
|
@@ -117,26 +148,38 @@ module Stripe
|
|
117
148
|
result
|
118
149
|
end
|
119
150
|
|
151
|
+
def self.normalize_id(id)
|
152
|
+
if id.kind_of?(Hash) # overloaded id
|
153
|
+
params_hash = id.dup
|
154
|
+
id = params_hash.delete(:id)
|
155
|
+
else
|
156
|
+
params_hash = {}
|
157
|
+
end
|
158
|
+
[id, params_hash]
|
159
|
+
end
|
160
|
+
|
120
161
|
# The secondary opts argument can either be a string or hash
|
121
162
|
# Turn this value into an api_key and a set of headers
|
122
|
-
def self.
|
163
|
+
def self.normalize_opts(opts)
|
123
164
|
case opts
|
124
|
-
when NilClass
|
125
|
-
return nil, {}
|
126
165
|
when String
|
127
|
-
|
166
|
+
{:api_key => opts}
|
128
167
|
when Hash
|
129
|
-
|
130
|
-
|
131
|
-
headers[:idempotency_key] = opts[:idempotency_key]
|
132
|
-
end
|
133
|
-
if opts[:stripe_account]
|
134
|
-
headers[:stripe_account] = opts[:stripe_account]
|
135
|
-
end
|
136
|
-
return opts[:api_key], headers
|
168
|
+
check_api_key!(opts.fetch(:api_key)) if opts.has_key?(:api_key)
|
169
|
+
opts.clone
|
137
170
|
else
|
138
|
-
raise TypeError.new(
|
171
|
+
raise TypeError.new('normalize_opts expects a string or a hash')
|
139
172
|
end
|
140
173
|
end
|
174
|
+
|
175
|
+
def self.check_string_argument!(key)
|
176
|
+
raise TypeError.new("argument must be a string") unless key.is_a?(String)
|
177
|
+
key
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.check_api_key!(key)
|
181
|
+
raise TypeError.new("api_key must be a string") unless key.is_a?(String)
|
182
|
+
key
|
183
|
+
end
|
141
184
|
end
|
142
185
|
end
|
data/lib/stripe/version.rb
CHANGED