stripe 4.18.0 → 4.18.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -1
  3. data/.rubocop_todo.yml +3 -15
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile +3 -1
  6. data/VERSION +1 -1
  7. data/lib/stripe.rb +5 -3
  8. data/lib/stripe/account.rb +31 -17
  9. data/lib/stripe/alipay_account.rb +10 -3
  10. data/lib/stripe/api_operations/nested_resource.rb +12 -6
  11. data/lib/stripe/api_operations/request.rb +3 -7
  12. data/lib/stripe/api_operations/save.rb +1 -3
  13. data/lib/stripe/api_resource.rb +11 -3
  14. data/lib/stripe/application_fee.rb +2 -1
  15. data/lib/stripe/application_fee_refund.rb +11 -3
  16. data/lib/stripe/bank_account.rb +16 -4
  17. data/lib/stripe/bitcoin_receiver.rb +2 -1
  18. data/lib/stripe/capability.rb +10 -3
  19. data/lib/stripe/card.rb +16 -5
  20. data/lib/stripe/charge.rb +4 -6
  21. data/lib/stripe/customer.rb +5 -7
  22. data/lib/stripe/ephemeral_key.rb +4 -1
  23. data/lib/stripe/errors.rb +8 -8
  24. data/lib/stripe/invoice.rb +2 -1
  25. data/lib/stripe/list_object.rb +9 -4
  26. data/lib/stripe/login_link.rb +4 -1
  27. data/lib/stripe/order.rb +3 -5
  28. data/lib/stripe/person.rb +7 -2
  29. data/lib/stripe/reversal.rb +10 -3
  30. data/lib/stripe/singleton_api_resource.rb +3 -1
  31. data/lib/stripe/source.rb +4 -2
  32. data/lib/stripe/stripe_client.rb +84 -65
  33. data/lib/stripe/stripe_object.rb +50 -36
  34. data/lib/stripe/subscription.rb +1 -3
  35. data/lib/stripe/subscription_item.rb +2 -1
  36. data/lib/stripe/subscription_schedule_revision.rb +13 -4
  37. data/lib/stripe/tax_id.rb +7 -3
  38. data/lib/stripe/transfer.rb +2 -1
  39. data/lib/stripe/usage_record.rb +12 -3
  40. data/lib/stripe/util.rb +40 -24
  41. data/lib/stripe/version.rb +1 -1
  42. data/lib/stripe/webhook.rb +4 -2
  43. data/stripe.gemspec +4 -2
  44. data/test/stripe/account_link_test.rb +1 -1
  45. data/test/stripe/account_test.rb +1 -1
  46. data/test/stripe/alipay_account_test.rb +1 -1
  47. data/test/stripe/api_operations_test.rb +1 -2
  48. data/test/stripe/api_resource_test.rb +5 -8
  49. data/test/stripe/apple_pay_domain_test.rb +1 -1
  50. data/test/stripe/application_fee_refund_test.rb +1 -1
  51. data/test/stripe/application_fee_test.rb +1 -1
  52. data/test/stripe/balance_test.rb +1 -1
  53. data/test/stripe/bank_account_test.rb +1 -1
  54. data/test/stripe/capability_test.rb +1 -1
  55. data/test/stripe/charge_test.rb +1 -1
  56. data/test/stripe/checkout/session_test.rb +1 -1
  57. data/test/stripe/country_spec_test.rb +1 -1
  58. data/test/stripe/coupon_test.rb +1 -1
  59. data/test/stripe/credit_note_test.rb +1 -1
  60. data/test/stripe/customer_card_test.rb +1 -1
  61. data/test/stripe/customer_test.rb +1 -1
  62. data/test/stripe/dispute_test.rb +1 -1
  63. data/test/stripe/ephemeral_key_test.rb +1 -1
  64. data/test/stripe/errors_test.rb +1 -1
  65. data/test/stripe/exchange_rate_test.rb +1 -1
  66. data/test/stripe/file_link_test.rb +1 -1
  67. data/test/stripe/file_test.rb +1 -1
  68. data/test/stripe/file_upload_test.rb +1 -1
  69. data/test/stripe/invoice_item_test.rb +1 -1
  70. data/test/stripe/invoice_line_item_test.rb +1 -1
  71. data/test/stripe/invoice_test.rb +1 -1
  72. data/test/stripe/issuer_fraud_record_test.rb +1 -1
  73. data/test/stripe/issuing/authorization_test.rb +1 -1
  74. data/test/stripe/issuing/card_test.rb +1 -1
  75. data/test/stripe/issuing/cardholder_test.rb +1 -1
  76. data/test/stripe/issuing/dispute_test.rb +1 -1
  77. data/test/stripe/issuing/transaction_test.rb +1 -1
  78. data/test/stripe/list_object_test.rb +1 -1
  79. data/test/stripe/login_link_test.rb +1 -1
  80. data/test/stripe/oauth_test.rb +1 -1
  81. data/test/stripe/order_return_test.rb +1 -1
  82. data/test/stripe/order_test.rb +8 -1
  83. data/test/stripe/payment_intent_test.rb +1 -1
  84. data/test/stripe/payment_method_test.rb +1 -1
  85. data/test/stripe/payout_test.rb +1 -1
  86. data/test/stripe/person_test.rb +1 -1
  87. data/test/stripe/plan_test.rb +1 -1
  88. data/test/stripe/product_test.rb +1 -1
  89. data/test/stripe/radar/early_fraud_warning_test.rb +1 -1
  90. data/test/stripe/radar/value_list_item_test.rb +1 -1
  91. data/test/stripe/radar/value_list_test.rb +1 -1
  92. data/test/stripe/recipient_test.rb +1 -1
  93. data/test/stripe/refund_test.rb +1 -1
  94. data/test/stripe/reporting/report_run_test.rb +1 -1
  95. data/test/stripe/reporting/report_type_test.rb +1 -1
  96. data/test/stripe/reversal_test.rb +1 -1
  97. data/test/stripe/review_test.rb +1 -1
  98. data/test/stripe/sigma/scheduled_query_run_test.rb +1 -1
  99. data/test/stripe/sku_test.rb +1 -1
  100. data/test/stripe/source_test.rb +1 -1
  101. data/test/stripe/source_transaction_test.rb +1 -1
  102. data/test/stripe/stripe_client_test.rb +1 -1
  103. data/test/stripe/stripe_object_test.rb +1 -1
  104. data/test/stripe/stripe_response_test.rb +1 -1
  105. data/test/stripe/subscription_item_test.rb +1 -1
  106. data/test/stripe/subscription_schedule_revision_test.rb +1 -1
  107. data/test/stripe/subscription_schedule_test.rb +1 -1
  108. data/test/stripe/subscription_test.rb +1 -1
  109. data/test/stripe/tax_id_test.rb +1 -1
  110. data/test/stripe/tax_rate_test.rb +1 -1
  111. data/test/stripe/terminal/connection_token_test.rb +1 -1
  112. data/test/stripe/terminal/location_test.rb +1 -1
  113. data/test/stripe/terminal/reader_test.rb +1 -1
  114. data/test/stripe/three_d_secure_test.rb +1 -1
  115. data/test/stripe/topup_test.rb +1 -1
  116. data/test/stripe/transfer_test.rb +1 -1
  117. data/test/stripe/usage_record_summary_test.rb +1 -1
  118. data/test/stripe/usage_record_test.rb +1 -1
  119. data/test/stripe/util_test.rb +1 -1
  120. data/test/stripe/webhook_endpoint_test.rb +1 -1
  121. data/test/stripe/webhook_test.rb +2 -2
  122. data/test/stripe_test.rb +1 -1
  123. data/test/test_helper.rb +4 -6
  124. metadata +2 -2
@@ -4,7 +4,7 @@ module Stripe
4
4
  class StripeObject
5
5
  include Enumerable
6
6
 
7
- @@permanent_attributes = Set.new([:id])
7
+ @@permanent_attributes = Set.new([:id]) # rubocop:disable Style/ClassVars
8
8
 
9
9
  # The default :id method is deprecated and isn't useful to us
10
10
  undef :id if method_defined?(:id)
@@ -93,10 +93,12 @@ module Stripe
93
93
  # considered to be equal if they have the same set of values and each one
94
94
  # of those values is the same.
95
95
  def ==(other)
96
- other.is_a?(StripeObject) && @values == other.instance_variable_get(:@values)
96
+ other.is_a?(StripeObject) &&
97
+ @values == other.instance_variable_get(:@values)
97
98
  end
98
99
 
99
- # Hash equality. As with `#==`, we consider two equivalent Stripe objects equal.
100
+ # Hash equality. As with `#==`, we consider two equivalent Stripe objects
101
+ # equal.
100
102
  def eql?(other)
101
103
  # Defer to the implementation on `#==`.
102
104
  self == other
@@ -121,7 +123,8 @@ module Stripe
121
123
 
122
124
  def inspect
123
125
  id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : ""
124
- "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
126
+ "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " +
127
+ JSON.pretty_generate(@values)
125
128
  end
126
129
 
127
130
  # Re-initializes the object based on a hash of values (usually one that's
@@ -162,12 +165,12 @@ module Stripe
162
165
  end
163
166
  end
164
167
 
165
- def [](k)
166
- @values[k.to_sym]
168
+ def [](key)
169
+ @values[key.to_sym]
167
170
  end
168
171
 
169
- def []=(k, v)
170
- send(:"#{k}=", v)
172
+ def []=(key, value)
173
+ send(:"#{key}=", value)
171
174
  end
172
175
 
173
176
  def keys
@@ -178,12 +181,13 @@ module Stripe
178
181
  @values.values
179
182
  end
180
183
 
181
- def to_json(*_a)
184
+ def to_json(*_opts)
185
+ # TODO: pass opts to JSON.generate?
182
186
  JSON.generate(@values)
183
187
  end
184
188
 
185
- def as_json(*a)
186
- @values.as_json(*a)
189
+ def as_json(*opts)
190
+ @values.as_json(*opts)
187
191
  end
188
192
 
189
193
  def to_hash
@@ -251,10 +255,10 @@ module Stripe
251
255
  # values within in that its parent StripeObject doesn't know about.
252
256
  #
253
257
  unsaved = @unsaved_values.include?(k)
254
- if options[:force] || unsaved || v.is_a?(StripeObject)
255
- update_hash[k.to_sym] =
256
- serialize_params_value(@values[k], @original_values[k], unsaved, options[:force], key: k)
257
- end
258
+ next unless options[:force] || unsaved || v.is_a?(StripeObject)
259
+ update_hash[k.to_sym] = serialize_params_value(
260
+ @values[k], @original_values[k], unsaved, options[:force], key: k
261
+ )
258
262
  end
259
263
 
260
264
  # a `nil` that makes it out of `#serialize_params_value` signals an empty
@@ -281,13 +285,11 @@ module Stripe
281
285
  []
282
286
  end
283
287
 
284
- protected
285
-
286
- def metaclass
288
+ protected def metaclass
287
289
  class << self; self; end
288
290
  end
289
291
 
290
- def remove_accessors(keys)
292
+ protected def remove_accessors(keys)
291
293
  # not available in the #instance_eval below
292
294
  protected_fields = self.class.protected_fields
293
295
 
@@ -313,7 +315,7 @@ module Stripe
313
315
  #
314
316
  # Here we swallow that error and issue a warning so at least
315
317
  # the program doesn't crash.
316
- $stderr.puts("WARNING: Unable to remove method `#{method_name}`; " \
318
+ warn("WARNING: Unable to remove method `#{method_name}`; " \
317
319
  "if custom, please consider renaming to a name that doesn't " \
318
320
  "collide with an API property name.")
319
321
  end
@@ -322,7 +324,7 @@ module Stripe
322
324
  end
323
325
  end
324
326
 
325
- def add_accessors(keys, values)
327
+ protected def add_accessors(keys, values)
326
328
  # not available in the #instance_eval below
327
329
  protected_fields = self.class.protected_fields
328
330
 
@@ -359,7 +361,11 @@ module Stripe
359
361
  end
360
362
  end
361
363
 
362
- def method_missing(name, *args)
364
+ # Disabling the cop because it's confused by the fact that the methods are
365
+ # protected, but we do define `#respond_to_missing?` just below. Hopefully
366
+ # this is fixed in more recent Rubocop versions.
367
+ # rubocop:disable Style/MissingRespondToMissing
368
+ protected def method_missing(name, *args)
363
369
  # TODO: only allow setting in updateable classes.
364
370
  if name.to_s.end_with?("=")
365
371
  attr = name.to_s[0...-1].to_sym
@@ -375,7 +381,9 @@ module Stripe
375
381
  begin
376
382
  mth = method(name)
377
383
  rescue NameError
378
- raise NoMethodError, "Cannot set #{attr} on this object. HINT: you can't set: #{@@permanent_attributes.to_a.join(', ')}"
384
+ raise NoMethodError,
385
+ "Cannot set #{attr} on this object. HINT: you can't set: " \
386
+ "#{@@permanent_attributes.to_a.join(', ')}"
379
387
  end
380
388
  return mth.call(args[0])
381
389
  elsif @values.key?(name)
@@ -390,11 +398,17 @@ module Stripe
390
398
  # raise right away.
391
399
  raise unless @transient_values.include?(name)
392
400
 
393
- raise NoMethodError, e.message + ". HINT: The '#{name}' attribute was set in the past, however. It was then wiped when refreshing the object with the result returned by Stripe's API, probably as a result of a save(). The attributes currently available on this object are: #{@values.keys.join(', ')}"
401
+ raise NoMethodError,
402
+ e.message + ". HINT: The '#{name}' attribute was set in the " \
403
+ "past, however. It was then wiped when refreshing the object " \
404
+ "with the result returned by Stripe's API, probably as a " \
405
+ "result of a save(). The attributes currently available on " \
406
+ "this object are: #{@values.keys.join(', ')}"
394
407
  end
395
408
  end
409
+ # rubocop:enable Style/MissingRespondToMissing
396
410
 
397
- def respond_to_missing?(symbol, include_private = false)
411
+ protected def respond_to_missing?(symbol, include_private = false)
398
412
  @values && @values.key?(symbol) || super
399
413
  end
400
414
 
@@ -410,7 +424,7 @@ module Stripe
410
424
  # * +:opts:+ Options for StripeObject like an API key.
411
425
  # * +:partial:+ Indicates that the re-initialization should not attempt to
412
426
  # remove accessors.
413
- def initialize_from(values, opts, partial = false)
427
+ protected def initialize_from(values, opts, partial = false)
414
428
  @opts = Util.normalize_opts(opts)
415
429
 
416
430
  # the `#send` is here so that we can keep this method private
@@ -420,8 +434,8 @@ module Stripe
420
434
  added = Set.new(values.keys - @values.keys)
421
435
 
422
436
  # Wipe old state before setting new. This is useful for e.g. updating a
423
- # customer, where there is no persistent card parameter. Mark those values
424
- # which don't persist as transient
437
+ # customer, where there is no persistent card parameter. Mark those
438
+ # values which don't persist as transient
425
439
 
426
440
  remove_accessors(removed)
427
441
  add_accessors(added, values)
@@ -441,7 +455,8 @@ module Stripe
441
455
  self
442
456
  end
443
457
 
444
- def serialize_params_value(value, original, unsaved, force, key: nil)
458
+ protected def serialize_params_value(value, original, unsaved, force,
459
+ key: nil)
445
460
  if value.nil?
446
461
  ""
447
462
 
@@ -516,11 +531,9 @@ module Stripe
516
531
  end
517
532
  end
518
533
 
519
- private
520
-
521
534
  # Produces a deep copy of the given object including support for arrays,
522
535
  # hashes, and StripeObjects.
523
- def self.deep_copy(obj)
536
+ private_class_method def self.deep_copy(obj)
524
537
  case obj
525
538
  when Array
526
539
  obj.map { |e| deep_copy(e) }
@@ -540,9 +553,8 @@ module Stripe
540
553
  obj
541
554
  end
542
555
  end
543
- private_class_method :deep_copy
544
556
 
545
- def dirty_value!(value)
557
+ private def dirty_value!(value)
546
558
  case value
547
559
  when Array
548
560
  value.map { |v| dirty_value!(v) }
@@ -553,12 +565,14 @@ module Stripe
553
565
 
554
566
  # Returns a hash of empty values for all the values that are in the given
555
567
  # StripeObject.
556
- def empty_values(obj)
568
+ private def empty_values(obj)
557
569
  values = case obj
558
570
  when Hash then obj
559
571
  when StripeObject then obj.instance_variable_get(:@values)
560
572
  else
561
- raise ArgumentError, "#empty_values got unexpected object type: #{obj.class.name}"
573
+ raise ArgumentError,
574
+ "#empty_values got unexpected object type: " \
575
+ "#{obj.class.name}"
562
576
  end
563
577
 
564
578
  values.each_with_object({}) do |(k, _), update|
@@ -18,9 +18,7 @@ module Stripe
18
18
  initialize_from({ discount: nil }, opts, true)
19
19
  end
20
20
 
21
- private
22
-
23
- def discount_url
21
+ private def discount_url
24
22
  resource_url + "/discount"
25
23
  end
26
24
  end
@@ -10,7 +10,8 @@ module Stripe
10
10
  OBJECT_NAME = "subscription_item".freeze
11
11
 
12
12
  def usage_record_summaries(params = {}, opts = {})
13
- resp, opts = request(:get, resource_url + "/usage_record_summaries", params, opts)
13
+ resp, opts = request(:get, resource_url + "/usage_record_summaries",
14
+ params, opts)
14
15
  Util.convert_to_stripe_object(resp.data, opts)
15
16
  end
16
17
  end
@@ -9,17 +9,26 @@ module Stripe
9
9
  def resource_url
10
10
  if !respond_to?(:schedule) || schedule.nil?
11
11
  raise NotImplementedError,
12
- "Subscription Schedule Revisions cannot be accessed without a Subscription Schedule ID."
12
+ "Subscription schedule revisions cannot be accessed without a " \
13
+ "subscription schedule ID."
13
14
  end
14
- "#{SubscriptionSchedule.resource_url}/#{CGI.escape(schedule)}/revisions/#{CGI.escape(id)}"
15
+ "#{SubscriptionSchedule.resource_url}/#{CGI.escape(schedule)}" \
16
+ "/revisions/#{CGI.escape(id)}"
15
17
  end
16
18
 
17
19
  def self.retrieve(_id, _opts = {})
18
- raise NotImplementedError, "Subscription Schedule Revisions cannot be retrieved without a Subscription Schedule ID. Retrieve it using schedule.revisions.retrieve('revision_id')"
20
+ raise NotImplementedError,
21
+ "Subscription schedule revisions cannot be retrieved without a " \
22
+ "subscription schedule ID. Retrieve a subscribtion schedule " \
23
+ "revision using `SubscriptionSchedule.retrieve_revision(" \
24
+ "'schedule_id', 'revision_id')`"
19
25
  end
20
26
 
21
27
  def self.list(_id, _opts = {})
22
- raise NotImplementedError, "Subscription Schedule Revisions cannot be listed without a Subscription Schedule ID. List those using schedule.revisions"
28
+ raise NotImplementedError,
29
+ "Subscription schedule revisions cannot be listed without a " \
30
+ "subscription schedule ID. List subscribtion schedule revisions " \
31
+ "using `SubscriptionSchedule.list_revisions('schedule_id')`"
23
32
  end
24
33
  end
25
34
  end
@@ -10,13 +10,17 @@ module Stripe
10
10
  def resource_url
11
11
  if !respond_to?(:customer) || customer.nil?
12
12
  raise NotImplementedError,
13
- "Tax Ids cannot be accessed without a customer ID."
13
+ "Tax IDs cannot be accessed without a customer ID."
14
14
  end
15
- "#{Customer.resource_url}/#{CGI.escape(customer)}/tax_ids/#{CGI.escape(id)}"
15
+ "#{Customer.resource_url}/#{CGI.escape(customer)}/tax_ids" \
16
+ "/#{CGI.escape(id)}"
16
17
  end
17
18
 
18
19
  def self.retrieve(_id, _opts = {})
19
- raise NotImplementedError, "Tax Ids cannot be retrieved without a customer ID. Retrieve a tax id using Customer.retrieve_tax_id('tax_id')"
20
+ raise NotImplementedError,
21
+ "Tax IDs cannot be retrieved without a customer ID. Retrieve a " \
22
+ "tax ID using `Customer.retrieve_tax_id('customer_id', " \
23
+ "'tax_id_id')`"
20
24
  end
21
25
  end
22
26
  end
@@ -11,7 +11,8 @@ module Stripe
11
11
 
12
12
  custom_method :cancel, http_verb: :post
13
13
 
14
- nested_resource_class_methods :reversal, operations: %i[create retrieve update list]
14
+ nested_resource_class_methods :reversal,
15
+ operations: %i[create retrieve update list]
15
16
 
16
17
  def cancel
17
18
  resp, api_key = request(:post, cancel_url)
@@ -5,9 +5,18 @@ module Stripe
5
5
  OBJECT_NAME = "usage_record".freeze
6
6
 
7
7
  def self.create(params = {}, opts = {})
8
- raise(ArgumentError, "Params must have a subscription_item key") unless params.key?(:subscription_item)
9
- req_params = params.clone.delete_if { |key, _value| key == :subscription_item }
10
- resp, opts = request(:post, "/v1/subscription_items/#{params[:subscription_item]}/usage_records", req_params, opts)
8
+ unless params.key?(:subscription_item)
9
+ raise ArgumentError, "Params must have a subscription_item key"
10
+ end
11
+ req_params = params.clone.delete_if do |key, _value|
12
+ key == :subscription_item
13
+ end
14
+ resp, opts = request(
15
+ :post,
16
+ "/v1/subscription_items/#{params[:subscription_item]}/usage_records",
17
+ req_params,
18
+ opts
19
+ )
11
20
  Util.convert_to_stripe_object(resp.data, opts)
12
21
  end
13
22
  end
@@ -24,22 +24,23 @@ module Stripe
24
24
  OPTS_USER_SPECIFIED + Set[:client] - Set[:idempotency_key]
25
25
  ).freeze
26
26
 
27
- def self.objects_to_ids(h)
28
- case h
27
+ def self.objects_to_ids(obj)
28
+ case obj
29
29
  when APIResource
30
- h.id
30
+ obj.id
31
31
  when Hash
32
32
  res = {}
33
- h.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
33
+ obj.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
34
34
  res
35
35
  when Array
36
- h.map { |v| objects_to_ids(v) }
36
+ obj.map { |v| objects_to_ids(v) }
37
37
  else
38
- h
38
+ obj
39
39
  end
40
40
  end
41
41
 
42
42
  def self.object_classes # rubocop:disable Metrics/MethodLength
43
+ # rubocop:disable Metrics/LineLength
43
44
  @object_classes ||= {
44
45
  # data structures
45
46
  ListObject::OBJECT_NAME => ListObject,
@@ -122,6 +123,7 @@ module Stripe
122
123
  UsageRecordSummary::OBJECT_NAME => UsageRecordSummary,
123
124
  WebhookEndpoint::OBJECT_NAME => WebhookEndpoint,
124
125
  }
126
+ # rubocop:enable Metrics/LineLength
125
127
  end
126
128
 
127
129
  # Converts a hash of fields or an array of hashes into a +StripeObject+ or
@@ -143,8 +145,10 @@ module Stripe
143
145
  when Array
144
146
  data.map { |i| convert_to_stripe_object(i, opts) }
145
147
  when Hash
146
- # Try converting to a known object class. If none available, fall back to generic StripeObject
147
- object_classes.fetch(data[:object], StripeObject).construct_from(data, opts)
148
+ # Try converting to a known object class. If none available, fall back
149
+ # to generic StripeObject
150
+ object_classes.fetch(data[:object], StripeObject)
151
+ .construct_from(data, opts)
148
152
  else
149
153
  data
150
154
  end
@@ -153,24 +157,24 @@ module Stripe
153
157
  def self.log_error(message, data = {})
154
158
  if !Stripe.logger.nil? ||
155
159
  !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_ERROR
156
- log_internal(message, data, color: :cyan,
157
- level: Stripe::LEVEL_ERROR, logger: Stripe.logger, out: $stderr)
160
+ log_internal(message, data, color: :cyan, level: Stripe::LEVEL_ERROR,
161
+ logger: Stripe.logger, out: $stderr)
158
162
  end
159
163
  end
160
164
 
161
165
  def self.log_info(message, data = {})
162
166
  if !Stripe.logger.nil? ||
163
167
  !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_INFO
164
- log_internal(message, data, color: :cyan,
165
- level: Stripe::LEVEL_INFO, logger: Stripe.logger, out: $stdout)
168
+ log_internal(message, data, color: :cyan, level: Stripe::LEVEL_INFO,
169
+ logger: Stripe.logger, out: $stdout)
166
170
  end
167
171
  end
168
172
 
169
173
  def self.log_debug(message, data = {})
170
174
  if !Stripe.logger.nil? ||
171
175
  !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_DEBUG
172
- log_internal(message, data, color: :blue,
173
- level: Stripe::LEVEL_DEBUG, logger: Stripe.logger, out: $stdout)
176
+ log_internal(message, data, color: :blue, level: Stripe::LEVEL_DEBUG,
177
+ logger: Stripe.logger, out: $stdout)
174
178
  end
175
179
  end
176
180
 
@@ -305,13 +309,13 @@ module Stripe
305
309
 
306
310
  # Constant time string comparison to prevent timing attacks
307
311
  # Code borrowed from ActiveSupport
308
- def self.secure_compare(a, b)
309
- return false unless a.bytesize == b.bytesize
312
+ def self.secure_compare(str_a, str_b)
313
+ return false unless str_a.bytesize == str_b.bytesize
310
314
 
311
- l = a.unpack "C#{a.bytesize}"
315
+ l = str_a.unpack "C#{str_a.bytesize}"
312
316
 
313
317
  res = 0
314
- b.each_byte { |byte| res |= byte ^ l.shift }
318
+ str_b.each_byte { |byte| res |= byte ^ l.shift }
315
319
  res.zero?
316
320
  end
317
321
 
@@ -358,21 +362,33 @@ module Stripe
358
362
 
359
363
  # TODO: Make these named required arguments when we drop support for Ruby
360
364
  # 2.0.
361
- def self.log_internal(message, data = {}, color: nil, level: nil, logger: nil, out: nil)
365
+ def self.log_internal(message, data = {}, color: nil, level: nil,
366
+ logger: nil, out: nil)
362
367
  data_str = data.reject { |_k, v| v.nil? }
363
368
  .map do |(k, v)|
364
- format("%s=%s", colorize(k, color, logger.nil? && !out.nil? && out.isatty), wrap_logfmt_value(v))
369
+ format("%<key>s=%<value>s",
370
+ key: colorize(k, color, logger.nil? && !out.nil? && out.isatty),
371
+ value: wrap_logfmt_value(v))
365
372
  end.join(" ")
366
373
 
367
374
  if !logger.nil?
368
375
  # the library's log levels are mapped to the same values as the
369
376
  # standard library's logger
370
377
  logger.log(level,
371
- format("message=%s %s", wrap_logfmt_value(message), data_str))
378
+ format("message=%<message>s %<data_str>s",
379
+ message: wrap_logfmt_value(message),
380
+ data_str: data_str))
372
381
  elsif out.isatty
373
- out.puts format("%s %s %s", colorize(level_name(level)[0, 4].upcase, color, out.isatty), message, data_str)
382
+ out.puts format("%<level>s %<message>s %<data_str>s",
383
+ level: colorize(level_name(level)[0, 4].upcase,
384
+ color, out.isatty),
385
+ message: message,
386
+ data_str: data_str)
374
387
  else
375
- out.puts format("message=%s level=%s %s", wrap_logfmt_value(message), level_name(level), data_str)
388
+ out.puts format("message=%<message>s level=%<level>s %<data_str>s",
389
+ message: wrap_logfmt_value(message),
390
+ level: level_name(level),
391
+ data_str: data_str)
376
392
  end
377
393
  end
378
394
  private_class_method :log_internal
@@ -390,7 +406,7 @@ module Stripe
390
406
  if %r{[^\w\-/]} =~ val
391
407
  # If the string contains any special characters, escape any double
392
408
  # quotes it has, remove newlines, and wrap the whole thing in quotes.
393
- format(%("%s"), val.gsub('"', '\"').delete("\n"))
409
+ format(%("%<value>s"), value: val.gsub('"', '\"').delete("\n"))
394
410
  else
395
411
  # Otherwise use the basic value if it looks like a standard set of
396
412
  # characters (and allow a few special characters like hyphens, and