stripe 1.18.0 → 1.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +11 -1
  4. data/History.txt +98 -0
  5. data/README.rdoc +19 -10
  6. data/VERSION +1 -1
  7. data/lib/stripe/account.rb +46 -4
  8. data/lib/stripe/api_operations/create.rb +3 -10
  9. data/lib/stripe/api_operations/delete.rb +4 -4
  10. data/lib/stripe/api_operations/list.rb +17 -9
  11. data/lib/stripe/api_operations/request.rb +41 -0
  12. data/lib/stripe/api_operations/update.rb +41 -40
  13. data/lib/stripe/api_resource.rb +7 -4
  14. data/lib/stripe/application_fee.rb +3 -4
  15. data/lib/stripe/application_fee_refund.rb +1 -1
  16. data/lib/stripe/balance_transaction.rb +1 -1
  17. data/lib/stripe/bank_account.rb +19 -0
  18. data/lib/stripe/bitcoin_receiver.rb +12 -2
  19. data/lib/stripe/bitcoin_transaction.rb +5 -0
  20. data/lib/stripe/card.rb +6 -4
  21. data/lib/stripe/charge.rb +14 -22
  22. data/lib/stripe/coupon.rb +2 -2
  23. data/lib/stripe/customer.rb +24 -26
  24. data/lib/stripe/dispute.rb +16 -0
  25. data/lib/stripe/errors/card_error.rb +3 -2
  26. data/lib/stripe/errors/invalid_request_error.rb +3 -2
  27. data/lib/stripe/errors/rate_limit_error.rb +4 -0
  28. data/lib/stripe/errors/stripe_error.rb +8 -2
  29. data/lib/stripe/event.rb +1 -1
  30. data/lib/stripe/file_upload.rb +12 -22
  31. data/lib/stripe/invoice.rb +8 -8
  32. data/lib/stripe/invoice_item.rb +2 -2
  33. data/lib/stripe/list_object.rb +77 -13
  34. data/lib/stripe/order.rb +19 -0
  35. data/lib/stripe/plan.rb +2 -2
  36. data/lib/stripe/product.rb +16 -0
  37. data/lib/stripe/recipient.rb +2 -2
  38. data/lib/stripe/refund.rb +2 -9
  39. data/lib/stripe/reversal.rb +14 -0
  40. data/lib/stripe/singleton_api_resource.rb +2 -2
  41. data/lib/stripe/sku.rb +8 -0
  42. data/lib/stripe/stripe_object.rb +232 -46
  43. data/lib/stripe/subscription.rb +3 -3
  44. data/lib/stripe/token.rb +1 -1
  45. data/lib/stripe/transfer.rb +3 -3
  46. data/lib/stripe/util.rb +64 -21
  47. data/lib/stripe/version.rb +1 -1
  48. data/lib/stripe.rb +102 -67
  49. data/stripe.gemspec +0 -2
  50. data/test/stripe/account_test.rb +135 -6
  51. data/test/stripe/api_resource_test.rb +326 -42
  52. data/test/stripe/application_fee_refund_test.rb +6 -6
  53. data/test/stripe/application_fee_test.rb +3 -3
  54. data/test/stripe/balance_test.rb +11 -0
  55. data/test/stripe/bitcoin_receiver_test.rb +30 -7
  56. data/test/stripe/bitcoin_transaction_test.rb +29 -0
  57. data/test/stripe/charge_refund_test.rb +55 -0
  58. data/test/stripe/charge_test.rb +32 -13
  59. data/test/stripe/coupon_test.rb +3 -3
  60. data/test/stripe/customer_card_test.rb +20 -14
  61. data/test/stripe/customer_test.rb +15 -15
  62. data/test/stripe/dispute_test.rb +45 -0
  63. data/test/stripe/file_upload_test.rb +17 -6
  64. data/test/stripe/invoice_test.rb +18 -4
  65. data/test/stripe/list_object_test.rb +126 -2
  66. data/test/stripe/metadata_test.rb +28 -13
  67. data/test/stripe/order_test.rb +52 -0
  68. data/test/stripe/product_test.rb +41 -0
  69. data/test/stripe/recipient_card_test.rb +9 -9
  70. data/test/stripe/refund_test.rb +23 -15
  71. data/test/stripe/reversal_test.rb +47 -0
  72. data/test/stripe/sku_test.rb +24 -0
  73. data/test/stripe/stripe_object_test.rb +67 -6
  74. data/test/stripe/subscription_test.rb +13 -13
  75. data/test/stripe/transfer_test.rb +4 -4
  76. data/test/stripe/util_test.rb +45 -29
  77. data/test/stripe_test.rb +16 -0
  78. data/test/test_data.rb +273 -66
  79. metadata +47 -76
  80. data/lib/stripe/certificate_blacklist.rb +0 -55
  81. data/test/stripe/certificate_blacklist_test.rb +0 -18
@@ -2,25 +2,16 @@ module Stripe
2
2
  class StripeObject
3
3
  include Enumerable
4
4
 
5
- attr_accessor :api_key
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, api_key=nil)
14
- # parameter overloading!
15
- if id.kind_of?(Hash)
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, api_key=nil)
33
- self.new(values[:id], api_key).refresh_from(values, api_key)
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
- def refresh_from(values, api_key, partial=false)
46
- @api_key = api_key
47
-
48
- @previous_metadata = values[:metadata]
49
- removed = partial ? Set.new : Set.new(@values.keys - values.keys)
50
- added = Set.new(values.keys - @values.keys)
51
- # Wipe old state before setting new. This is useful for e.g. updating a
52
- # customer, where there is no persistent card parameter. Mark those values
53
- # which don't persist as transient
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
- instance_eval do
56
- remove_accessors(removed)
57
- add_accessors(added)
58
- end
59
- removed.each do |k|
60
- @values.delete(k)
61
- @transient_values.add(k)
62
- @unsaved_values.delete(k)
63
- end
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, api_key)
66
- @transient_values.delete(k)
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] = value.respond_to?(:to_hash) ? value.to_hash : value
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, @api_key])
130
+ Marshal.dump([@values, @opts])
110
131
  end
111
132
 
112
133
  def self._load(args)
113
- values, api_key = Marshal.load(args)
114
- construct_from(values, api_key)
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
- add_accessors([attr])
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
@@ -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, api_key=nil)
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
- Stripe.request(:delete, discount_url, @api_key)
16
- refresh_from({ :discount => nil }, api_key, true)
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
@@ -1,5 +1,5 @@
1
1
  module Stripe
2
2
  class Token < APIResource
3
- include Stripe::APIOperations::Create
3
+ extend Stripe::APIOperations::Create
4
4
  end
5
5
  end
@@ -1,12 +1,12 @@
1
1
  module Stripe
2
2
  class Transfer < APIResource
3
- include Stripe::APIOperations::List
4
- include Stripe::APIOperations::Create
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
- refresh_from(response, api_key)
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, api_key)
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, api_key) }
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, api_key)
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
- URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
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}[#{url_encode(key)}]" : url_encode(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
- result
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.parse_opts(opts)
163
+ def self.normalize_opts(opts)
123
164
  case opts
124
- when NilClass
125
- return nil, {}
126
165
  when String
127
- return opts, {}
166
+ {:api_key => opts}
128
167
  when Hash
129
- headers = {}
130
- if opts[:idempotency_key]
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("parse_opts expects a string or a hash")
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
@@ -1,3 +1,3 @@
1
1
  module Stripe
2
- VERSION = '1.18.0'
2
+ VERSION = '1.30.0'
3
3
  end