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
@@ -14,7 +14,8 @@ module Stripe
14
14
 
15
15
  def resource_url
16
16
  if respond_to?(:customer) && !customer.nil? && customer != ""
17
- "#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
17
+ "#{Customer.resource_url}/#{CGI.escape(customer)}/sources" \
18
+ "/#{CGI.escape(id)}"
18
19
  else
19
20
  "#{self.class.resource_url}/#{CGI.escape(id)}"
20
21
  end
@@ -12,15 +12,22 @@ module Stripe
12
12
  raise NotImplementedError,
13
13
  "Capabilities cannot be accessed without an account ID."
14
14
  end
15
- "#{Account.resource_url}/#{CGI.escape(account)}/capabilities/#{CGI.escape(id)}"
15
+ "#{Account.resource_url}/#{CGI.escape(account)}/capabilities" \
16
+ "/#{CGI.escape(id)}"
16
17
  end
17
18
 
18
19
  def self.retrieve(_id, _opts = {})
19
- raise NotImplementedError, "Capabilities cannot be retrieved without an account ID. Retrieve a capability using account.retrieve_capability('acct_123', 'acap_123')"
20
+ raise NotImplementedError,
21
+ "Capabilities cannot be retrieve without an account ID. " \
22
+ "Retrieve a capability using Account.retrieve_capability(" \
23
+ "'account_id', 'capability_id')`"
20
24
  end
21
25
 
22
26
  def self.update(_id, _params = nil, _opts = nil)
23
- raise NotImplementedError, "Capabilities cannot be updated without an account ID. Update a capability using `p = account.update_capability('acct_123', 'acap_123', params)"
27
+ raise NotImplementedError,
28
+ "Capabilities cannot be updated without an account ID. Update a " \
29
+ "capability using Account.update_capability('account_id', " \
30
+ "'capability_id', update_params)`"
24
31
  end
25
32
  end
26
33
  end
@@ -10,20 +10,31 @@ module Stripe
10
10
 
11
11
  def resource_url
12
12
  if respond_to?(:recipient) && !recipient.nil? && !recipient.empty?
13
- "#{Recipient.resource_url}/#{CGI.escape(recipient)}/cards/#{CGI.escape(id)}"
13
+ "#{Recipient.resource_url}/#{CGI.escape(recipient)}/cards" \
14
+ "/#{CGI.escape(id)}"
14
15
  elsif respond_to?(:customer) && !customer.nil? && !customer.empty?
15
- "#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
16
+ "#{Customer.resource_url}/#{CGI.escape(customer)}/sources" \
17
+ "/#{CGI.escape(id)}"
16
18
  elsif respond_to?(:account) && !account.nil? && !account.empty?
17
- "#{Account.resource_url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
19
+ "#{Account.resource_url}/#{CGI.escape(account)}/external_accounts" \
20
+ "/#{CGI.escape(id)}"
18
21
  end
19
22
  end
20
23
 
21
24
  def self.update(_id, _params = nil, _opts = nil)
22
- raise NotImplementedError, "Cards cannot be updated without a customer ID. Update a card using `c = customer.sources.retrieve('card_id'); c.save`"
25
+ raise NotImplementedError,
26
+ "Card cannot be updated without a customer ID or an account ID. " \
27
+ "Update a card using `Customer.update_source('customer_id', " \
28
+ "'card_id', update_params)` or `Account.update_external_account(" \
29
+ "'account_id', 'card_id', update_params)`"
23
30
  end
24
31
 
25
32
  def self.retrieve(_id, _opts = nil)
26
- raise NotImplementedError, "Cards cannot be retrieved without a customer ID. Retrieve a card using customer.sources.retrieve('card_id')"
33
+ raise NotImplementedError,
34
+ "Card cannot be retrieved without a customer ID or an account " \
35
+ "ID. Retrieve a card using `Customer.retrieve_source(" \
36
+ "'customer_id', 'card_id')` or " \
37
+ "`Account.retrieve_external_account('account_id', 'card_id')`"
27
38
  end
28
39
  end
29
40
  end
@@ -63,23 +63,21 @@ module Stripe
63
63
  initialize_from(resp.data, opts)
64
64
  end
65
65
 
66
- private
67
-
68
- def capture_url
66
+ private def capture_url
69
67
  resource_url + "/capture"
70
68
  end
71
69
 
72
- def dispute_url
70
+ private def dispute_url
73
71
  resource_url + "/dispute"
74
72
  end
75
73
 
76
- def close_dispute_url
74
+ private def close_dispute_url
77
75
  resource_url + "/dispute/close"
78
76
  end
79
77
 
80
78
  # Note that this is actually the *old* refund URL and its use is no longer
81
79
  # preferred.
82
- def refund_url
80
+ private def refund_url
83
81
  resource_url + "/refund"
84
82
  end
85
83
  end
@@ -14,8 +14,8 @@ module Stripe
14
14
 
15
15
  save_nested_resource :source
16
16
  nested_resource_class_methods :source,
17
- operations: %i[create retrieve update delete list]
18
-
17
+ operations: %i[create retrieve update delete
18
+ list]
19
19
  nested_resource_class_methods :tax_id,
20
20
  operations: %i[create retrieve delete list]
21
21
 
@@ -78,17 +78,15 @@ module Stripe
78
78
  initialize_from({ discount: nil }, opts, true)
79
79
  end
80
80
 
81
- private
82
-
83
- def discount_url
81
+ private def discount_url
84
82
  resource_url + "/discount"
85
83
  end
86
84
 
87
- def subscription_url
85
+ private def subscription_url
88
86
  resource_url + "/subscription"
89
87
  end
90
88
 
91
- def subscriptions_url
89
+ private def subscriptions_url
92
90
  resource_url + "/subscriptions"
93
91
  end
94
92
  end
@@ -9,7 +9,10 @@ module Stripe
9
9
 
10
10
  def self.create(params = {}, opts = {})
11
11
  opts = Util.normalize_opts(opts)
12
- raise ArgumentError, "stripe_version must be specified to create an ephemeral key" unless opts[:stripe_version]
12
+ unless opts[:stripe_version]
13
+ raise ArgumentError,
14
+ "stripe_version must be specified to create an ephemeral key"
15
+ end
13
16
  super
14
17
  end
15
18
  end
@@ -18,8 +18,8 @@ module Stripe
18
18
  attr_reader :request_id
19
19
 
20
20
  # Initializes a StripeError.
21
- def initialize(message = nil, http_status: nil, http_body: nil, json_body: nil,
22
- http_headers: nil, code: nil)
21
+ def initialize(message = nil, http_status: nil, http_body: nil,
22
+ json_body: nil, http_headers: nil, code: nil)
23
23
  @message = message
24
24
  @http_status = http_status
25
25
  @http_body = http_body
@@ -60,8 +60,8 @@ module Stripe
60
60
  attr_reader :param
61
61
 
62
62
  # TODO: make code a keyword arg in next major release
63
- def initialize(message, param, code, http_status: nil, http_body: nil, json_body: nil,
64
- http_headers: nil)
63
+ def initialize(message, param, code, http_status: nil, http_body: nil,
64
+ json_body: nil, http_headers: nil)
65
65
  super(message, http_status: http_status, http_body: http_body,
66
66
  json_body: json_body, http_headers: http_headers,
67
67
  code: code)
@@ -79,8 +79,8 @@ module Stripe
79
79
  class InvalidRequestError < StripeError
80
80
  attr_accessor :param
81
81
 
82
- def initialize(message, param, http_status: nil, http_body: nil, json_body: nil,
83
- http_headers: nil, code: nil)
82
+ def initialize(message, param, http_status: nil, http_body: nil,
83
+ json_body: nil, http_headers: nil, code: nil)
84
84
  super(message, http_status: http_status, http_body: http_body,
85
85
  json_body: json_body, http_headers: http_headers,
86
86
  code: code)
@@ -113,8 +113,8 @@ module Stripe
113
113
  module OAuth
114
114
  # OAuthError is raised when the OAuth API returns an error.
115
115
  class OAuthError < StripeError
116
- def initialize(code, description, http_status: nil, http_body: nil, json_body: nil,
117
- http_headers: nil)
116
+ def initialize(code, description, http_status: nil, http_body: nil,
117
+ json_body: nil, http_headers: nil)
118
118
  super(description, http_status: http_status, http_body: http_body,
119
119
  json_body: json_body, http_headers: http_headers,
120
120
  code: code)
@@ -21,7 +21,8 @@ module Stripe
21
21
  end
22
22
 
23
23
  def mark_uncollectible(params = {}, opts = {})
24
- resp, opts = request(:post, resource_url + "/mark_uncollectible", params, opts)
24
+ resp, opts = request(:post, resource_url + "/mark_uncollectible", params,
25
+ opts)
25
26
  initialize_from(resp.data, opts)
26
27
  end
27
28
 
@@ -26,12 +26,16 @@ module Stripe
26
26
  self.filters = {}
27
27
  end
28
28
 
29
- def [](k)
30
- case k
29
+ def [](key)
30
+ case key
31
31
  when String, Symbol
32
32
  super
33
33
  else
34
- raise ArgumentError, "You tried to access the #{k.inspect} index, but ListObject types only support String keys. (HINT: List calls return an object with a 'data' (which is the data array). You likely want to call #data[#{k.inspect}])"
34
+ raise ArgumentError,
35
+ "You tried to access the #{key.inspect} index, but ListObject " \
36
+ "types only support String keys. (HINT: List calls return an " \
37
+ "object with a 'data' (which is the data array). You likely " \
38
+ "want to call #data[#{key.inspect}])"
35
39
  end
36
40
  end
37
41
 
@@ -68,7 +72,8 @@ module Stripe
68
72
 
69
73
  def retrieve(id, opts = {})
70
74
  id, retrieve_params = Util.normalize_id(id)
71
- resp, opts = request(:get, "#{resource_url}/#{CGI.escape(id)}", retrieve_params, opts)
75
+ resp, opts = request(:get, "#{resource_url}/#{CGI.escape(id)}",
76
+ retrieve_params, opts)
72
77
  Util.convert_to_stripe_object(resp.data, opts)
73
78
  end
74
79
 
@@ -5,7 +5,10 @@ module Stripe
5
5
  OBJECT_NAME = "login_link".freeze
6
6
 
7
7
  def self.retrieve(_id, _opts = nil)
8
- raise NotImplementedError, "Login links do not have IDs and cannot be retrieved. They can only be created using accounts.login_links.create"
8
+ raise NotImplementedError,
9
+ "Login links do not have IDs and cannot be retrieved. They can " \
10
+ "only be created using `Account.create_login_link('account_id', " \
11
+ "create_params)`"
9
12
  end
10
13
  end
11
14
  end
@@ -11,7 +11,7 @@ module Stripe
11
11
  custom_method :pay, http_verb: :post
12
12
  custom_method :return_order, http_verb: :post, http_path: "returns"
13
13
 
14
- def pay(params, opts = {})
14
+ def pay(params = {}, opts = {})
15
15
  resp, opts = request(:post, pay_url, params, opts)
16
16
  initialize_from(resp.data, opts)
17
17
  end
@@ -21,13 +21,11 @@ module Stripe
21
21
  Util.convert_to_stripe_object(resp.data, opts)
22
22
  end
23
23
 
24
- private
25
-
26
- def pay_url
24
+ private def pay_url
27
25
  resource_url + "/pay"
28
26
  end
29
27
 
30
- def returns_url
28
+ private def returns_url
31
29
  resource_url + "/returns"
32
30
  end
33
31
  end
@@ -16,11 +16,16 @@ module Stripe
16
16
  end
17
17
 
18
18
  def self.retrieve(_id, _opts = {})
19
- raise NotImplementedError, "Persons cannot be retrieved without an account ID. Retrieve a person using account.persons.retrieve('person_id')"
19
+ raise NotImplementedError,
20
+ "Persons cannot be retrieved without an account ID. Retrieve a " \
21
+ "person using `Account.retrieve_person('account_id', 'person_id')`"
20
22
  end
21
23
 
22
24
  def self.update(_id, _params = nil, _opts = nil)
23
- raise NotImplementedError, "Persons cannot be updated without an account ID. Update a person using `p = account.persons.retrieve('person_id'); p.save`"
25
+ raise NotImplementedError,
26
+ "Persons cannot be updated without an account ID. Update a " \
27
+ "person using `Account.update_person('account_id', 'person_id', " \
28
+ "update_params)`"
24
29
  end
25
30
  end
26
31
  end
@@ -8,15 +8,22 @@ module Stripe
8
8
  OBJECT_NAME = "transfer_reversal".freeze
9
9
 
10
10
  def resource_url
11
- "#{Transfer.resource_url}/#{CGI.escape(transfer)}/reversals/#{CGI.escape(id)}"
11
+ "#{Transfer.resource_url}/#{CGI.escape(transfer)}/reversals" \
12
+ "/#{CGI.escape(id)}"
12
13
  end
13
14
 
14
15
  def self.update(_id, _params = nil, _opts = nil)
15
- raise NotImplementedError, "Reversals cannot be updated without a transfer ID. Update a reversal using `r = transfer.reversals.retrieve('reversal_id'); r.save`"
16
+ raise NotImplementedError,
17
+ "Reversals cannot be updated without a transfer ID. Update a " \
18
+ "reversal using `r = Transfer.update_reversal('transfer_id', " \
19
+ "'reversal_id', update_params)`"
16
20
  end
17
21
 
18
22
  def self.retrieve(_id, _opts = {})
19
- raise NotImplementedError, "Reversals cannot be retrieved without a transfer ID. Retrieve a reversal using transfer.reversals.retrieve('reversal_id')"
23
+ raise NotImplementedError,
24
+ "Reversals cannot be retrieved without a transfer ID. Retrieve " \
25
+ "a reversal using `Transfer.retrieve_reversal('transfer_id', " \
26
+ "'reversal_id')`"
20
27
  end
21
28
  end
22
29
  end
@@ -4,7 +4,9 @@ module Stripe
4
4
  class SingletonAPIResource < APIResource
5
5
  def self.resource_url
6
6
  if self == SingletonAPIResource
7
- raise NotImplementedError, "SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Account, etc.)"
7
+ raise NotImplementedError,
8
+ "SingletonAPIResource is an abstract class. You should " \
9
+ "perform actions on its subclasses (Balance, etc.)"
8
10
  end
9
11
  # Namespaces are separated in object names with periods (.) and in URLs
10
12
  # with forward slashes (/), so replace the former with the latter.
@@ -16,7 +16,8 @@ module Stripe
16
16
  "to a customer object."
17
17
  end
18
18
 
19
- url = "#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
19
+ url = "#{Customer.resource_url}/#{CGI.escape(customer)}/sources" \
20
+ "/#{CGI.escape(id)}"
20
21
  resp, opts = request(:delete, url, params, opts)
21
22
  initialize_from(resp.data, opts)
22
23
  end
@@ -28,7 +29,8 @@ module Stripe
28
29
  deprecate :delete, "#detach", 2017, 10
29
30
 
30
31
  def source_transactions(params = {}, opts = {})
31
- resp, opts = request(:get, resource_url + "/source_transactions", params, opts)
32
+ resp, opts = request(:get, resource_url + "/source_transactions", params,
33
+ opts)
32
34
  Util.convert_to_stripe_object(resp.data, opts)
33
35
  end
34
36
 
@@ -20,7 +20,8 @@ module Stripe
20
20
  end
21
21
 
22
22
  def self.default_client
23
- Thread.current[:stripe_client_default_client] ||= StripeClient.new(default_conn)
23
+ Thread.current[:stripe_client_default_client] ||=
24
+ StripeClient.new(default_conn)
24
25
  end
25
26
 
26
27
  # A default Faraday connection to be used when one isn't configured. This
@@ -55,9 +56,10 @@ module Stripe
55
56
 
56
57
  unless @verify_ssl_warned
57
58
  @verify_ssl_warned = true
58
- $stderr.puts("WARNING: Running without SSL cert verification. " \
59
+ warn("WARNING: Running without SSL cert verification. " \
59
60
  "You should never do this in production. " \
60
- "Execute 'Stripe.verify_ssl_certs = true' to enable verification.")
61
+ "Execute `Stripe.verify_ssl_certs = true` to enable " \
62
+ "verification.")
61
63
  end
62
64
  end
63
65
 
@@ -65,23 +67,23 @@ module Stripe
65
67
  end
66
68
  end
67
69
 
68
- # Checks if an error is a problem that we should retry on. This includes both
69
- # socket errors that may represent an intermittent problem and some special
70
- # HTTP statuses.
71
- def self.should_retry?(e, num_retries)
70
+ # Checks if an error is a problem that we should retry on. This includes
71
+ # both socket errors that may represent an intermittent problem and some
72
+ # special HTTP statuses.
73
+ def self.should_retry?(error, num_retries)
72
74
  return false if num_retries >= Stripe.max_network_retries
73
75
 
74
76
  # Retry on timeout-related problems (either on open or read).
75
- return true if e.is_a?(Faraday::TimeoutError)
77
+ return true if error.is_a?(Faraday::TimeoutError)
76
78
 
77
79
  # Destination refused the connection, the connection was reset, or a
78
80
  # variety of other connection failures. This could occur from a single
79
81
  # saturated server, so retry in case it's intermittent.
80
- return true if e.is_a?(Faraday::ConnectionFailed)
82
+ return true if error.is_a?(Faraday::ConnectionFailed)
81
83
 
82
- if e.is_a?(Faraday::ClientError) && e.response
84
+ if error.is_a?(Faraday::ClientError) && error.response
83
85
  # 409 conflict
84
- return true if e.response[:status] == 409
86
+ return true if error.response[:status] == 409
85
87
  end
86
88
 
87
89
  false
@@ -89,12 +91,15 @@ module Stripe
89
91
 
90
92
  def self.sleep_time(num_retries)
91
93
  # Apply exponential backoff with initial_network_retry_delay on the
92
- # number of num_retries so far as inputs. Do not allow the number to exceed
93
- # max_network_retry_delay.
94
- sleep_seconds = [Stripe.initial_network_retry_delay * (2**(num_retries - 1)), Stripe.max_network_retry_delay].min
95
-
96
- # Apply some jitter by randomizing the value in the range of (sleep_seconds
97
- # / 2) to (sleep_seconds).
94
+ # number of num_retries so far as inputs. Do not allow the number to
95
+ # exceed max_network_retry_delay.
96
+ sleep_seconds = [
97
+ Stripe.initial_network_retry_delay * (2**(num_retries - 1)),
98
+ Stripe.max_network_retry_delay,
99
+ ].min
100
+
101
+ # Apply some jitter by randomizing the value in the range of
102
+ # (sleep_seconds / 2) to (sleep_seconds).
98
103
  sleep_seconds *= (0.5 * (1 + rand))
99
104
 
100
105
  # But never sleep less than the base sleep seconds.
@@ -170,7 +175,9 @@ module Stripe
170
175
  context.idempotency_key = headers["Idempotency-Key"]
171
176
  context.method = method
172
177
  context.path = path
173
- context.query_params = query_params ? params_encoder.encode(query_params) : nil
178
+ context.query_params = if query_params
179
+ params_encoder.encode(query_params)
180
+ end
174
181
 
175
182
  # note that both request body and query params will be passed through
176
183
  # `FaradayStripeEncoder`
@@ -194,8 +201,6 @@ module Stripe
194
201
  [resp, api_key]
195
202
  end
196
203
 
197
- private
198
-
199
204
  # Used to workaround buggy behavior in Faraday: the library will try to
200
205
  # reshape anything that we pass to `req.params` with one of its default
201
206
  # encoders. I don't think this process is supposed to be lossy, but it is
@@ -227,21 +232,22 @@ module Stripe
227
232
 
228
233
  # We should never need to do this so it's not implemented.
229
234
  def decode(_str)
230
- raise NotImplementedError, "#{self.class.name} does not implement #decode"
235
+ raise NotImplementedError,
236
+ "#{self.class.name} does not implement #decode"
231
237
  end
232
238
  end
233
239
 
234
- def api_url(url = "", api_base = nil)
240
+ private def api_url(url = "", api_base = nil)
235
241
  (api_base || Stripe.api_base) + url
236
242
  end
237
243
 
238
- def check_api_key!(api_key)
244
+ private def check_api_key!(api_key)
239
245
  unless api_key
240
246
  raise AuthenticationError, "No API key provided. " \
241
247
  'Set your API key using "Stripe.api_key = <API-KEY>". ' \
242
248
  "You can generate API keys from the Stripe web interface. " \
243
- "See https://stripe.com/api for details, or email support@stripe.com " \
244
- "if you have any questions."
249
+ "See https://stripe.com/api for details, or email " \
250
+ "support@stripe.com if you have any questions."
245
251
  end
246
252
 
247
253
  return unless api_key =~ /\s/
@@ -252,7 +258,7 @@ module Stripe
252
258
  "email support@stripe.com if you have any questions.)"
253
259
  end
254
260
 
255
- def execute_request_with_rescues(api_base, context)
261
+ private def execute_request_with_rescues(api_base, context)
256
262
  num_retries = 0
257
263
  begin
258
264
  request_start = Time.now
@@ -263,12 +269,13 @@ module Stripe
263
269
 
264
270
  if Stripe.enable_telemetry? && context.request_id
265
271
  request_duration_ms = ((Time.now - request_start) * 1000).to_int
266
- @last_request_metrics = StripeRequestMetrics.new(context.request_id, request_duration_ms)
272
+ @last_request_metrics =
273
+ StripeRequestMetrics.new(context.request_id, request_duration_ms)
267
274
  end
268
275
 
269
276
  # We rescue all exceptions from a request so that we have an easy spot to
270
- # implement our retry logic across the board. We'll re-raise if it's a type
271
- # of exception that we didn't expect to handle.
277
+ # implement our retry logic across the board. We'll re-raise if it's a
278
+ # type of exception that we didn't expect to handle.
272
279
  rescue StandardError => e
273
280
  # If we modify context we copy it into a new variable so as not to
274
281
  # taint the original on a retry.
@@ -306,7 +313,7 @@ module Stripe
306
313
  resp
307
314
  end
308
315
 
309
- def general_api_error(status, body)
316
+ private def general_api_error(status, body)
310
317
  APIError.new("Invalid response object from API: #{body.inspect} " \
311
318
  "(HTTP response code was #{status})",
312
319
  http_status: status, http_body: body)
@@ -316,14 +323,14 @@ module Stripe
316
323
  # end of a User-Agent string where it'll be fairly prominent in places like
317
324
  # the Dashboard. Note that this formatting has been implemented to match
318
325
  # other libraries, and shouldn't be changed without universal consensus.
319
- def format_app_info(info)
326
+ private def format_app_info(info)
320
327
  str = info[:name]
321
328
  str = "#{str}/#{info[:version]}" unless info[:version].nil?
322
329
  str = "#{str} (#{info[:url]})" unless info[:url].nil?
323
330
  str
324
331
  end
325
332
 
326
- def handle_error_response(http_resp, context)
333
+ private def handle_error_response(http_resp, context)
327
334
  begin
328
335
  resp = StripeResponse.from_faraday_hash(http_resp)
329
336
  error_data = resp.data[:error]
@@ -343,7 +350,7 @@ module Stripe
343
350
  raise(error)
344
351
  end
345
352
 
346
- def specific_api_error(resp, error_data, context)
353
+ private def specific_api_error(resp, error_data, context)
347
354
  Util.log_error("Stripe API error",
348
355
  status: resp.http_status,
349
356
  error_code: error_data[:code],
@@ -395,7 +402,7 @@ module Stripe
395
402
 
396
403
  # Attempts to look at a response's error code and return an OAuth error if
397
404
  # one matches. Will return `nil` if the code isn't recognized.
398
- def specific_oauth_error(resp, error_code, context)
405
+ private def specific_oauth_error(resp, error_code, context)
399
406
  description = resp.data[:error_description] || error_code
400
407
 
401
408
  Util.log_error("Stripe OAuth error",
@@ -411,12 +418,18 @@ module Stripe
411
418
  },]
412
419
 
413
420
  case error_code
414
- when "invalid_client" then OAuth::InvalidClientError.new(*args)
415
- when "invalid_grant" then OAuth::InvalidGrantError.new(*args)
416
- when "invalid_request" then OAuth::InvalidRequestError.new(*args)
417
- when "invalid_scope" then OAuth::InvalidScopeError.new(*args)
418
- when "unsupported_grant_type" then OAuth::UnsupportedGrantTypeError.new(*args)
419
- when "unsupported_response_type" then OAuth::UnsupportedResponseTypeError.new(*args)
421
+ when "invalid_client"
422
+ OAuth::InvalidClientError.new(*args)
423
+ when "invalid_grant"
424
+ OAuth::InvalidGrantError.new(*args)
425
+ when "invalid_request"
426
+ OAuth::InvalidRequestError.new(*args)
427
+ when "invalid_scope"
428
+ OAuth::InvalidScopeError.new(*args)
429
+ when "unsupported_grant_type"
430
+ OAuth::UnsupportedGrantTypeError.new(*args)
431
+ when "unsupported_response_type"
432
+ OAuth::UnsupportedResponseTypeError.new(*args)
420
433
  else
421
434
  # We'd prefer that all errors are typed, but we create a generic
422
435
  # OAuthError in case we run into a code that we don't recognize.
@@ -424,30 +437,33 @@ module Stripe
424
437
  end
425
438
  end
426
439
 
427
- def handle_network_error(e, context, num_retries, api_base = nil)
440
+ private def handle_network_error(error, context, num_retries,
441
+ api_base = nil)
428
442
  Util.log_error("Stripe network error",
429
- error_message: e.message,
443
+ error_message: error.message,
430
444
  idempotency_key: context.idempotency_key,
431
445
  request_id: context.request_id)
432
446
 
433
- case e
447
+ case error
434
448
  when Faraday::ConnectionFailed
435
- message = "Unexpected error communicating when trying to connect to Stripe. " \
436
- "You may be seeing this message because your DNS is not working. " \
437
- "To check, try running 'host stripe.com' from the command line."
449
+ message = "Unexpected error communicating when trying to connect to " \
450
+ "Stripe. You may be seeing this message because your DNS is not" \
451
+ "working. To check, try running `host stripe.com` from the " \
452
+ "command line."
438
453
 
439
454
  when Faraday::SSLError
440
- message = "Could not establish a secure connection to Stripe, you may " \
441
- "need to upgrade your OpenSSL version. To check, try running " \
442
- "'openssl s_client -connect api.stripe.com:443' from the " \
443
- "command line."
455
+ message = "Could not establish a secure connection to Stripe, you " \
456
+ "may need to upgrade your OpenSSL version. To check, try running " \
457
+ "`openssl s_client -connect api.stripe.com:443` from the command " \
458
+ "line."
444
459
 
445
460
  when Faraday::TimeoutError
446
461
  api_base ||= Stripe.api_base
447
462
  message = "Could not connect to Stripe (#{api_base}). " \
448
463
  "Please check your internet connection and try again. " \
449
- "If this problem persists, you should check Stripe's service status at " \
450
- "https://twitter.com/stripestatus, or let us know at support@stripe.com."
464
+ "If this problem persists, you should check Stripe's service " \
465
+ "status at https://status.stripe.com, or let us know at " \
466
+ "support@stripe.com."
451
467
 
452
468
  else
453
469
  message = "Unexpected error communicating with Stripe. " \
@@ -457,10 +473,11 @@ module Stripe
457
473
 
458
474
  message += " Request was retried #{num_retries} times." if num_retries > 0
459
475
 
460
- raise APIConnectionError, message + "\n\n(Network error: #{e.message})"
476
+ raise APIConnectionError,
477
+ message + "\n\n(Network error: #{error.message})"
461
478
  end
462
479
 
463
- def request_headers(api_key, method)
480
+ private def request_headers(api_key, method)
464
481
  user_agent = "Stripe/v1 RubyBindings/#{Stripe::VERSION}"
465
482
  unless Stripe.app_info.nil?
466
483
  user_agent += " " + format_app_info(Stripe.app_info)
@@ -473,7 +490,9 @@ module Stripe
473
490
  }
474
491
 
475
492
  if Stripe.enable_telemetry? && !@last_request_metrics.nil?
476
- headers["X-Stripe-Client-Telemetry"] = JSON.generate(last_request_metrics: @last_request_metrics.payload)
493
+ headers["X-Stripe-Client-Telemetry"] = JSON.generate(
494
+ last_request_metrics: @last_request_metrics.payload
495
+ )
477
496
  end
478
497
 
479
498
  # It is only safe to retry network failures on post and delete
@@ -500,7 +519,7 @@ module Stripe
500
519
  headers
501
520
  end
502
521
 
503
- def log_request(context, num_retries)
522
+ private def log_request(context, num_retries)
504
523
  Util.log_info("Request to Stripe API",
505
524
  account: context.account,
506
525
  api_version: context.api_version,
@@ -513,9 +532,8 @@ module Stripe
513
532
  idempotency_key: context.idempotency_key,
514
533
  query_params: context.query_params)
515
534
  end
516
- private :log_request
517
535
 
518
- def log_response(context, request_start, status, body)
536
+ private def log_response(context, request_start, status, body)
519
537
  Util.log_info("Response from Stripe API",
520
538
  account: context.account,
521
539
  api_version: context.api_version,
@@ -535,19 +553,18 @@ module Stripe
535
553
  Util.log_debug("Dashboard link for request",
536
554
  idempotency_key: context.idempotency_key,
537
555
  request_id: context.request_id,
538
- url: Util.request_id_dashboard_url(context.request_id, context.api_key))
556
+ url: Util.request_id_dashboard_url(context.request_id,
557
+ context.api_key))
539
558
  end
540
- private :log_response
541
559
 
542
- def log_response_error(context, request_start, e)
560
+ private def log_response_error(context, request_start, error)
543
561
  Util.log_error("Request error",
544
562
  elapsed: Time.now - request_start,
545
- error_message: e.message,
563
+ error_message: error.message,
546
564
  idempotency_key: context.idempotency_key,
547
565
  method: context.method,
548
566
  path: context.path)
549
567
  end
550
- private :log_response_error
551
568
 
552
569
  # RequestLogContext stores information about a request that's begin made so
553
570
  # that we can log certain information. It's useful because it means that we
@@ -630,7 +647,8 @@ module Stripe
630
647
  end
631
648
 
632
649
  def user_agent
633
- lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
650
+ lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} " \
651
+ "(#{RUBY_RELEASE_DATE})"
634
652
 
635
653
  {
636
654
  application: Stripe.app_info,
@@ -646,7 +664,8 @@ module Stripe
646
664
  end
647
665
  end
648
666
 
649
- # StripeRequestMetrics tracks metadata to be reported to stripe for metrics collection
667
+ # StripeRequestMetrics tracks metadata to be reported to stripe for metrics
668
+ # collection
650
669
  class StripeRequestMetrics
651
670
  # The Stripe request ID of the response.
652
671
  attr_accessor :request_id