stripe 10.1.0 → 12.6.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.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +215 -21
  3. data/Gemfile +6 -5
  4. data/Makefile +8 -1
  5. data/OPENAPI_VERSION +1 -1
  6. data/README.md +46 -14
  7. data/Rakefile +7 -5
  8. data/VERSION +1 -1
  9. data/{bin → exe}/stripe-console +1 -1
  10. data/lib/stripe/api_operations/nested_resource.rb +22 -2
  11. data/lib/stripe/api_operations/request.rb +22 -18
  12. data/lib/stripe/api_operations/save.rb +7 -9
  13. data/lib/stripe/api_operations/search.rb +5 -0
  14. data/lib/stripe/api_operations/singleton_save.rb +86 -0
  15. data/lib/stripe/api_resource.rb +13 -4
  16. data/lib/stripe/api_resource_test_helpers.rb +7 -3
  17. data/lib/stripe/api_version.rb +1 -1
  18. data/lib/stripe/connection_manager.rb +4 -6
  19. data/lib/stripe/errors.rb +3 -11
  20. data/lib/stripe/instrumentation.rb +5 -21
  21. data/lib/stripe/list_object.rb +3 -0
  22. data/lib/stripe/multipart_encoder.rb +7 -7
  23. data/lib/stripe/oauth.rb +6 -6
  24. data/lib/stripe/object_types.rb +135 -116
  25. data/lib/stripe/resources/account.rb +103 -25
  26. data/lib/stripe/resources/account_link.rb +8 -0
  27. data/lib/stripe/resources/account_session.rb +8 -0
  28. data/lib/stripe/resources/alipay_account.rb +1 -1
  29. data/lib/stripe/resources/apple_pay_domain.rb +43 -0
  30. data/lib/stripe/resources/application_fee.rb +8 -0
  31. data/lib/stripe/resources/application_fee_refund.rb +4 -2
  32. data/lib/stripe/resources/apps/secret.rb +15 -0
  33. data/lib/stripe/resources/balance.rb +3 -0
  34. data/lib/stripe/resources/balance_transaction.rb +15 -0
  35. data/lib/stripe/resources/bank_account.rb +49 -7
  36. data/lib/stripe/resources/billing/alert.rb +87 -0
  37. data/lib/stripe/resources/billing/meter.rb +83 -0
  38. data/lib/stripe/resources/billing/meter_event.rb +27 -0
  39. data/lib/stripe/resources/billing/meter_event_adjustment.rb +26 -0
  40. data/lib/stripe/resources/billing/meter_event_summary.rb +15 -0
  41. data/lib/stripe/resources/billing_portal/configuration.rb +33 -0
  42. data/lib/stripe/resources/billing_portal/session.rb +14 -1
  43. data/lib/stripe/resources/capability.rb +4 -2
  44. data/lib/stripe/resources/card.rb +28 -0
  45. data/lib/stripe/resources/cash_balance.rb +3 -0
  46. data/lib/stripe/resources/charge.rb +39 -1
  47. data/lib/stripe/resources/checkout/session.rb +47 -5
  48. data/lib/stripe/resources/climate/order.rb +67 -0
  49. data/lib/stripe/resources/climate/product.rb +27 -0
  50. data/lib/stripe/resources/climate/supplier.rb +26 -0
  51. data/lib/stripe/resources/confirmation_token.rb +39 -0
  52. data/lib/stripe/resources/country_spec.rb +8 -0
  53. data/lib/stripe/resources/coupon.rb +45 -0
  54. data/lib/stripe/resources/credit_note.rb +47 -7
  55. data/lib/stripe/resources/credit_note_line_item.rb +3 -0
  56. data/lib/stripe/resources/customer.rb +89 -26
  57. data/lib/stripe/resources/customer_balance_transaction.rb +3 -1
  58. data/lib/stripe/resources/customer_cash_balance_transaction.rb +3 -2
  59. data/lib/stripe/resources/customer_session.rb +29 -0
  60. data/lib/stripe/resources/discount.rb +3 -0
  61. data/lib/stripe/resources/dispute.rb +26 -0
  62. data/lib/stripe/resources/entitlements/active_entitlement.rb +26 -0
  63. data/lib/stripe/resources/entitlements/feature.rb +49 -0
  64. data/lib/stripe/resources/ephemeral_key.rb +23 -0
  65. data/lib/stripe/resources/event.rb +11 -3
  66. data/lib/stripe/resources/exchange_rate.rb +8 -0
  67. data/lib/stripe/resources/file.rb +29 -16
  68. data/lib/stripe/resources/file_link.rb +23 -0
  69. data/lib/stripe/resources/financial_connections/account.rb +66 -7
  70. data/lib/stripe/resources/financial_connections/account_owner.rb +3 -0
  71. data/lib/stripe/resources/financial_connections/account_ownership.rb +3 -0
  72. data/lib/stripe/resources/financial_connections/session.rb +13 -0
  73. data/lib/stripe/resources/financial_connections/transaction.rb +26 -0
  74. data/lib/stripe/resources/forwarding/request.rb +52 -0
  75. data/lib/stripe/resources/funding_instructions.rb +3 -0
  76. data/lib/stripe/resources/identity/verification_report.rb +14 -1
  77. data/lib/stripe/resources/identity/verification_session.rb +90 -4
  78. data/lib/stripe/resources/invoice.rb +170 -17
  79. data/lib/stripe/resources/invoice_item.rb +43 -0
  80. data/lib/stripe/resources/invoice_line_item.rb +21 -0
  81. data/lib/stripe/resources/invoice_rendering_template.rb +63 -0
  82. data/lib/stripe/resources/issuing/authorization.rb +88 -14
  83. data/lib/stripe/resources/issuing/card.rb +50 -16
  84. data/lib/stripe/resources/issuing/cardholder.rb +33 -0
  85. data/lib/stripe/resources/issuing/dispute.rb +35 -0
  86. data/lib/stripe/resources/issuing/personalization_design.rb +119 -0
  87. data/lib/stripe/resources/issuing/physical_bundle.rb +26 -0
  88. data/lib/stripe/resources/issuing/token.rb +18 -0
  89. data/lib/stripe/resources/issuing/transaction.rb +30 -0
  90. data/lib/stripe/resources/line_item.rb +3 -0
  91. data/lib/stripe/resources/login_link.rb +4 -1
  92. data/lib/stripe/resources/mandate.rb +3 -0
  93. data/lib/stripe/resources/payment_intent.rb +190 -25
  94. data/lib/stripe/resources/payment_link.rb +25 -0
  95. data/lib/stripe/resources/payment_method.rb +57 -4
  96. data/lib/stripe/resources/payment_method_configuration.rb +33 -0
  97. data/lib/stripe/resources/payment_method_domain.rb +46 -1
  98. data/lib/stripe/resources/payout.rb +39 -4
  99. data/lib/stripe/resources/person.rb +5 -4
  100. data/lib/stripe/resources/plan.rb +43 -0
  101. data/lib/stripe/resources/price.rb +24 -1
  102. data/lib/stripe/resources/product.rb +47 -1
  103. data/lib/stripe/resources/product_feature.rb +13 -0
  104. data/lib/stripe/resources/promotion_code.rb +23 -0
  105. data/lib/stripe/resources/quote.rb +67 -32
  106. data/lib/stripe/resources/radar/early_fraud_warning.rb +13 -0
  107. data/lib/stripe/resources/radar/value_list.rb +53 -0
  108. data/lib/stripe/resources/radar/value_list_item.rb +43 -0
  109. data/lib/stripe/resources/refund.rb +46 -0
  110. data/lib/stripe/resources/reporting/report_run.rb +23 -0
  111. data/lib/stripe/resources/reporting/report_type.rb +13 -0
  112. data/lib/stripe/resources/reversal.rb +5 -3
  113. data/lib/stripe/resources/review.rb +10 -0
  114. data/lib/stripe/resources/setup_attempt.rb +8 -0
  115. data/lib/stripe/resources/setup_intent.rb +72 -10
  116. data/lib/stripe/resources/shipping_rate.rb +23 -0
  117. data/lib/stripe/resources/sigma/scheduled_query_run.rb +13 -0
  118. data/lib/stripe/resources/source.rb +23 -1
  119. data/lib/stripe/resources/source_transaction.rb +3 -0
  120. data/lib/stripe/resources/subscription.rb +81 -13
  121. data/lib/stripe/resources/subscription_item.rb +54 -1
  122. data/lib/stripe/resources/subscription_schedule.rb +41 -4
  123. data/lib/stripe/resources/tax/calculation.rb +15 -0
  124. data/lib/stripe/resources/tax/calculation_line_item.rb +3 -0
  125. data/lib/stripe/resources/tax/registration.rb +35 -0
  126. data/lib/stripe/resources/tax/settings.rb +4 -2
  127. data/lib/stripe/resources/tax/transaction.rb +15 -8
  128. data/lib/stripe/resources/tax/transaction_line_item.rb +3 -0
  129. data/lib/stripe/resources/tax_code.rb +8 -0
  130. data/lib/stripe/resources/tax_id.rb +30 -12
  131. data/lib/stripe/resources/tax_rate.rb +23 -0
  132. data/lib/stripe/resources/terminal/configuration.rb +53 -0
  133. data/lib/stripe/resources/terminal/connection_token.rb +13 -0
  134. data/lib/stripe/resources/terminal/location.rb +54 -0
  135. data/lib/stripe/resources/terminal/reader.rb +80 -12
  136. data/lib/stripe/resources/test_helpers/test_clock.rb +45 -0
  137. data/lib/stripe/resources/token.rb +10 -1
  138. data/lib/stripe/resources/topup.rb +25 -0
  139. data/lib/stripe/resources/transfer.rb +26 -1
  140. data/lib/stripe/resources/treasury/credit_reversal.rb +23 -0
  141. data/lib/stripe/resources/treasury/debit_reversal.rb +23 -0
  142. data/lib/stripe/resources/treasury/financial_account.rb +42 -5
  143. data/lib/stripe/resources/treasury/financial_account_features.rb +3 -0
  144. data/lib/stripe/resources/treasury/inbound_transfer.rb +47 -11
  145. data/lib/stripe/resources/treasury/outbound_payment.rb +64 -8
  146. data/lib/stripe/resources/treasury/outbound_transfer.rb +64 -8
  147. data/lib/stripe/resources/treasury/received_credit.rb +17 -0
  148. data/lib/stripe/resources/treasury/received_debit.rb +17 -0
  149. data/lib/stripe/resources/treasury/transaction.rb +13 -0
  150. data/lib/stripe/resources/treasury/transaction_entry.rb +13 -0
  151. data/lib/stripe/resources/usage_record.rb +5 -0
  152. data/lib/stripe/resources/usage_record_summary.rb +3 -0
  153. data/lib/stripe/resources/webhook_endpoint.rb +55 -2
  154. data/lib/stripe/resources.rb +18 -0
  155. data/lib/stripe/search_result_object.rb +4 -1
  156. data/lib/stripe/singleton_api_resource.rb +20 -3
  157. data/lib/stripe/stripe_client.rb +61 -63
  158. data/lib/stripe/stripe_configuration.rb +13 -29
  159. data/lib/stripe/stripe_object.rb +23 -21
  160. data/lib/stripe/stripe_response.rb +1 -3
  161. data/lib/stripe/util.rb +13 -15
  162. data/lib/stripe/version.rb +1 -1
  163. data/lib/stripe.rb +26 -0
  164. data/stripe.gemspec +7 -4
  165. metadata +25 -5
@@ -8,6 +8,19 @@ module Stripe
8
8
  extend Stripe::APIOperations::List
9
9
 
10
10
  OBJECT_NAME = "treasury.transaction"
11
+ def self.object_name
12
+ "treasury.transaction"
13
+ end
14
+
15
+ # Retrieves a list of Transaction objects.
16
+ def self.list(filters = {}, opts = {})
17
+ request_stripe_object(
18
+ method: :get,
19
+ path: "/v1/treasury/transactions",
20
+ params: filters,
21
+ opts: opts
22
+ )
23
+ end
11
24
  end
12
25
  end
13
26
  end
@@ -8,6 +8,19 @@ module Stripe
8
8
  extend Stripe::APIOperations::List
9
9
 
10
10
  OBJECT_NAME = "treasury.transaction_entry"
11
+ def self.object_name
12
+ "treasury.transaction_entry"
13
+ end
14
+
15
+ # Retrieves a list of TransactionEntry objects.
16
+ def self.list(filters = {}, opts = {})
17
+ request_stripe_object(
18
+ method: :get,
19
+ path: "/v1/treasury/transaction_entries",
20
+ params: filters,
21
+ opts: opts
22
+ )
23
+ end
11
24
 
12
25
  def self.resource_url
13
26
  "/v1/treasury/transaction_entries"
@@ -6,7 +6,12 @@ module Stripe
6
6
  # metered billing of subscription prices.
7
7
  #
8
8
  # Related guide: [Metered billing](https://stripe.com/docs/billing/subscriptions/metered-billing)
9
+ #
10
+ # This is our legacy usage-based billing API. See the [updated usage-based billing docs](https://docs.stripe.com/billing/subscriptions/usage-based).
9
11
  class UsageRecord < APIResource
10
12
  OBJECT_NAME = "usage_record"
13
+ def self.object_name
14
+ "usage_record"
15
+ end
11
16
  end
12
17
  end
@@ -4,5 +4,8 @@
4
4
  module Stripe
5
5
  class UsageRecordSummary < StripeObject
6
6
  OBJECT_NAME = "usage_record_summary"
7
+ def self.object_name
8
+ "usage_record_summary"
9
+ end
7
10
  end
8
11
  end
@@ -2,13 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Stripe
5
- # You can configure [webhook endpoints](https://stripe.com/docs/webhooks/) via the API to be
5
+ # You can configure [webhook endpoints](https://docs.stripe.com/webhooks/) via the API to be
6
6
  # notified about events that happen in your Stripe account or connected
7
7
  # accounts.
8
8
  #
9
9
  # Most users configure webhooks from [the dashboard](https://dashboard.stripe.com/webhooks), which provides a user interface for registering and testing your webhook endpoints.
10
10
  #
11
- # Related guide: [Setting up webhooks](https://stripe.com/docs/webhooks/configure)
11
+ # Related guide: [Setting up webhooks](https://docs.stripe.com/webhooks/configure)
12
12
  class WebhookEndpoint < APIResource
13
13
  extend Stripe::APIOperations::Create
14
14
  include Stripe::APIOperations::Delete
@@ -16,5 +16,58 @@ module Stripe
16
16
  include Stripe::APIOperations::Save
17
17
 
18
18
  OBJECT_NAME = "webhook_endpoint"
19
+ def self.object_name
20
+ "webhook_endpoint"
21
+ end
22
+
23
+ # A webhook endpoint must have a url and a list of enabled_events. You may optionally specify the Boolean connect parameter. If set to true, then a Connect webhook endpoint that notifies the specified url about events from all connected accounts is created; otherwise an account webhook endpoint that notifies the specified url only about events from your account is created. You can also create webhook endpoints in the [webhooks settings](https://dashboard.stripe.com/account/webhooks) section of the Dashboard.
24
+ def self.create(params = {}, opts = {})
25
+ request_stripe_object(
26
+ method: :post,
27
+ path: "/v1/webhook_endpoints",
28
+ params: params,
29
+ opts: opts
30
+ )
31
+ end
32
+
33
+ # You can also delete webhook endpoints via the [webhook endpoint management](https://dashboard.stripe.com/account/webhooks) page of the Stripe dashboard.
34
+ def self.delete(id, params = {}, opts = {})
35
+ request_stripe_object(
36
+ method: :delete,
37
+ path: format("/v1/webhook_endpoints/%<id>s", { id: CGI.escape(id) }),
38
+ params: params,
39
+ opts: opts
40
+ )
41
+ end
42
+
43
+ # You can also delete webhook endpoints via the [webhook endpoint management](https://dashboard.stripe.com/account/webhooks) page of the Stripe dashboard.
44
+ def delete(params = {}, opts = {})
45
+ request_stripe_object(
46
+ method: :delete,
47
+ path: format("/v1/webhook_endpoints/%<webhook_endpoint>s", { webhook_endpoint: CGI.escape(self["id"]) }),
48
+ params: params,
49
+ opts: opts
50
+ )
51
+ end
52
+
53
+ # Returns a list of your webhook endpoints.
54
+ def self.list(filters = {}, opts = {})
55
+ request_stripe_object(
56
+ method: :get,
57
+ path: "/v1/webhook_endpoints",
58
+ params: filters,
59
+ opts: opts
60
+ )
61
+ end
62
+
63
+ # Updates the webhook endpoint. You may edit the url, the list of enabled_events, and the status of your endpoint.
64
+ def self.update(id, params = {}, opts = {})
65
+ request_stripe_object(
66
+ method: :post,
67
+ path: format("/v1/webhook_endpoints/%<id>s", { id: CGI.escape(id) }),
68
+ params: params,
69
+ opts: opts
70
+ )
71
+ end
19
72
  end
20
73
  end
@@ -11,6 +11,11 @@ require "stripe/resources/apps/secret"
11
11
  require "stripe/resources/balance"
12
12
  require "stripe/resources/balance_transaction"
13
13
  require "stripe/resources/bank_account"
14
+ require "stripe/resources/billing/alert"
15
+ require "stripe/resources/billing/meter"
16
+ require "stripe/resources/billing/meter_event"
17
+ require "stripe/resources/billing/meter_event_adjustment"
18
+ require "stripe/resources/billing/meter_event_summary"
14
19
  require "stripe/resources/billing_portal/configuration"
15
20
  require "stripe/resources/billing_portal/session"
16
21
  require "stripe/resources/capability"
@@ -18,6 +23,10 @@ require "stripe/resources/card"
18
23
  require "stripe/resources/cash_balance"
19
24
  require "stripe/resources/charge"
20
25
  require "stripe/resources/checkout/session"
26
+ require "stripe/resources/climate/order"
27
+ require "stripe/resources/climate/product"
28
+ require "stripe/resources/climate/supplier"
29
+ require "stripe/resources/confirmation_token"
21
30
  require "stripe/resources/country_spec"
22
31
  require "stripe/resources/coupon"
23
32
  require "stripe/resources/credit_note"
@@ -25,8 +34,11 @@ require "stripe/resources/credit_note_line_item"
25
34
  require "stripe/resources/customer"
26
35
  require "stripe/resources/customer_balance_transaction"
27
36
  require "stripe/resources/customer_cash_balance_transaction"
37
+ require "stripe/resources/customer_session"
28
38
  require "stripe/resources/discount"
29
39
  require "stripe/resources/dispute"
40
+ require "stripe/resources/entitlements/active_entitlement"
41
+ require "stripe/resources/entitlements/feature"
30
42
  require "stripe/resources/ephemeral_key"
31
43
  require "stripe/resources/event"
32
44
  require "stripe/resources/exchange_rate"
@@ -36,16 +48,21 @@ require "stripe/resources/financial_connections/account"
36
48
  require "stripe/resources/financial_connections/account_owner"
37
49
  require "stripe/resources/financial_connections/account_ownership"
38
50
  require "stripe/resources/financial_connections/session"
51
+ require "stripe/resources/financial_connections/transaction"
52
+ require "stripe/resources/forwarding/request"
39
53
  require "stripe/resources/funding_instructions"
40
54
  require "stripe/resources/identity/verification_report"
41
55
  require "stripe/resources/identity/verification_session"
42
56
  require "stripe/resources/invoice"
43
57
  require "stripe/resources/invoice_item"
44
58
  require "stripe/resources/invoice_line_item"
59
+ require "stripe/resources/invoice_rendering_template"
45
60
  require "stripe/resources/issuing/authorization"
46
61
  require "stripe/resources/issuing/card"
47
62
  require "stripe/resources/issuing/cardholder"
48
63
  require "stripe/resources/issuing/dispute"
64
+ require "stripe/resources/issuing/personalization_design"
65
+ require "stripe/resources/issuing/physical_bundle"
49
66
  require "stripe/resources/issuing/token"
50
67
  require "stripe/resources/issuing/transaction"
51
68
  require "stripe/resources/line_item"
@@ -61,6 +78,7 @@ require "stripe/resources/person"
61
78
  require "stripe/resources/plan"
62
79
  require "stripe/resources/price"
63
80
  require "stripe/resources/product"
81
+ require "stripe/resources/product_feature"
64
82
  require "stripe/resources/promotion_code"
65
83
  require "stripe/resources/quote"
66
84
  require "stripe/resources/radar/early_fraud_warning"
@@ -7,6 +7,9 @@ module Stripe
7
7
  include Stripe::APIOperations::Request
8
8
 
9
9
  OBJECT_NAME = "search_result"
10
+ def self.object_name
11
+ "search_result"
12
+ end
10
13
 
11
14
  # This accessor allows a `SearchResultObject` to inherit various filters
12
15
  # that were given to a predecessor. This allows for things like consistent
@@ -80,7 +83,7 @@ module Stripe
80
83
 
81
84
  params = filters.merge(page: next_page).merge(params)
82
85
 
83
- _search(url, params, opts)
86
+ request_stripe_object(method: :get, path: url, params: params, opts: opts)
84
87
  end
85
88
  end
86
89
  end
@@ -10,15 +10,32 @@ module Stripe
10
10
  end
11
11
  # Namespaces are separated in object names with periods (.) and in URLs
12
12
  # with forward slashes (/), so replace the former with the latter.
13
- "/v1/#{self::OBJECT_NAME.downcase.tr('.', '/')}"
13
+ "/v1/#{object_name.downcase.tr('.', '/')}"
14
14
  end
15
15
 
16
16
  def resource_url
17
17
  self.class.resource_url
18
18
  end
19
19
 
20
- def self.retrieve(opts = {})
21
- instance = new(nil, Util.normalize_opts(opts))
20
+ def self.retrieve(params_or_opts = {}, definitely_opts = nil)
21
+ opts = nil
22
+ params = nil
23
+ if definitely_opts.nil?
24
+ unrecognized_key = params_or_opts.keys.find { |k| !Util::OPTS_USER_SPECIFIED.include?(k) }
25
+ if unrecognized_key
26
+ raise ArgumentError,
27
+ "Unrecognized request option: #{unrecognized_key}. Did you mean to specify this as retrieve params? " \
28
+ "If so, you must explicitly pass an opts hash as a second argument. " \
29
+ "For example: .retrieve({#{unrecognized_key}: 'foo'}, {})"
30
+ end
31
+
32
+ opts = params_or_opts
33
+ else
34
+ opts = definitely_opts
35
+ params = params_or_opts
36
+ end
37
+
38
+ instance = new(params, Util.normalize_opts(opts))
22
39
  instance.refresh
23
40
  instance
24
41
  end
@@ -18,6 +18,11 @@ module Stripe
18
18
  @system_profiler = SystemProfiler.new
19
19
  @last_request_metrics = nil
20
20
 
21
+ # The following attribute is only used to log whether or not
22
+ # StripeClient#request has been called. To be removed in a
23
+ # future major version.
24
+ @usage = []
25
+
21
26
  @config = case config_arg
22
27
  when Hash
23
28
  Stripe.config.reverse_duplicate_merge(config_arg)
@@ -36,8 +41,7 @@ module Stripe
36
41
  end
37
42
  end
38
43
 
39
- attr_reader :config
40
- attr_reader :options
44
+ attr_reader :config, :options
41
45
 
42
46
  # Gets a currently active `StripeClient`. Set for the current thread when
43
47
  # `StripeClient#request` is being run so that API operations being executed
@@ -80,9 +84,7 @@ module Stripe
80
84
  end
81
85
  end
82
86
 
83
- if thread_context.default_connection_managers.empty?
84
- pruned_contexts << thread_context
85
- end
87
+ pruned_contexts << thread_context if thread_context.default_connection_managers.empty?
86
88
  end
87
89
 
88
90
  @thread_contexts_with_connection_managers.subtract(pruned_contexts)
@@ -113,14 +115,14 @@ module Stripe
113
115
  # both socket errors that may represent an intermittent problem and some
114
116
  # special HTTP statuses.
115
117
  def self.should_retry?(error,
116
- method:, num_retries:, config: Stripe.config)
118
+ num_retries:, config: Stripe.config)
117
119
  return false if num_retries >= config.max_network_retries
118
120
 
119
121
  case error
120
122
  when Net::OpenTimeout, Net::ReadTimeout
121
123
  # Retry on timeout-related problems (either on open or read).
122
124
  true
123
- when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET,
125
+ when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET, # rubocop:todo Lint/DuplicateBranch
124
126
  Errno::EHOSTUNREACH, Errno::ETIMEDOUT, SocketError
125
127
  # Destination refused the connection, the connection was reset, or a
126
128
  # variety of other connection failures. This could occur from a single
@@ -146,15 +148,12 @@ module Stripe
146
148
  # These 429s are safe to retry.
147
149
  return true if error.http_status == 429 && error.code == "lock_timeout"
148
150
 
149
- # 500 Internal Server Error
151
+ # Retry on 500, 503, and other internal errors.
150
152
  #
151
- # We only bother retrying these for non-POST requests. POSTs end up
152
- # being cached by the idempotency layer so there's no purpose in
153
- # retrying them.
154
- return true if error.http_status == 500 && method != :post
155
-
156
- # 503 Service Unavailable
157
- error.http_status == 503
153
+ # Note that we expect the stripe-should-retry header to be false
154
+ # in most cases when a 500 is returned, since our idempotency framework
155
+ # would typically replay it anyway.
156
+ true if error.http_status >= 500
158
157
  else
159
158
  false
160
159
  end
@@ -191,7 +190,9 @@ module Stripe
191
190
  # client = StripeClient.new
192
191
  # charge, resp = client.request { Charge.create }
193
192
  #
193
+
194
194
  def request
195
+ @usage = ["stripe_client_request"]
195
196
  old_stripe_client = self.class.current_thread_context.active_client
196
197
  self.class.current_thread_context.active_client = self
197
198
 
@@ -206,15 +207,19 @@ module Stripe
206
207
  res = yield
207
208
  [res, self.class.current_thread_context.last_responses[object_id]]
208
209
  ensure
210
+ @usage = []
209
211
  self.class.current_thread_context.active_client = old_stripe_client
210
212
  self.class.current_thread_context.last_responses.delete(object_id)
211
213
  end
212
214
  end
215
+ deprecate :request, "the `last_response` property on the returned resource (see " \
216
+ "https://github.com/stripe/stripe-ruby?tab=readme-ov-file#accessing-a-response-object " \
217
+ "for usage examples)", 2024, 6
213
218
 
214
219
  def execute_request(method, path,
215
- api_base: nil, api_key: nil, headers: {}, params: {})
220
+ api_base: nil, api_key: nil, headers: {}, params: {}, usage: [])
216
221
  http_resp, api_key = execute_request_internal(
217
- method, path, api_base, api_key, headers, params
222
+ method, path, api_base, api_key, headers, params, usage
218
223
  )
219
224
 
220
225
  begin
@@ -243,7 +248,7 @@ module Stripe
243
248
  # passed, then a StripeStreamResponse is returned containing an IO stream
244
249
  # with the response body.
245
250
  def execute_request_stream(method, path,
246
- api_base: nil, api_key: nil,
251
+ api_base: nil, api_key: nil, usage: [],
247
252
  headers: {}, params: {},
248
253
  &read_body_chunk_block)
249
254
  unless block_given?
@@ -252,7 +257,7 @@ module Stripe
252
257
  end
253
258
 
254
259
  http_resp, api_key = execute_request_internal(
255
- method, path, api_base, api_key, headers, params, &read_body_chunk_block
260
+ method, path, api_base, api_key, headers, params, usage, &read_body_chunk_block
256
261
  )
257
262
 
258
263
  # When the read_body_chunk_block is given, we no longer have access to the
@@ -287,21 +292,21 @@ module Stripe
287
292
 
288
293
  ERROR_MESSAGE_CONNECTION =
289
294
  "Unexpected error communicating when trying to connect to " \
290
- "Stripe (%s). You may be seeing this message because your DNS is not " \
291
- "working or you don't have an internet connection. To check, try " \
292
- "running `host stripe.com` from the command line."
295
+ "Stripe (%s). You may be seeing this message because your DNS is not " \
296
+ "working or you don't have an internet connection. To check, try " \
297
+ "running `host stripe.com` from the command line."
293
298
  ERROR_MESSAGE_SSL =
294
299
  "Could not establish a secure connection to Stripe (%s), you " \
295
- "may need to upgrade your OpenSSL version. To check, try running " \
296
- "`openssl s_client -connect api.stripe.com:443` from the command " \
297
- "line."
300
+ "may need to upgrade your OpenSSL version. To check, try running " \
301
+ "`openssl s_client -connect api.stripe.com:443` from the command " \
302
+ "line."
298
303
 
299
304
  # Common error suffix sared by both connect and read timeout messages.
300
305
  ERROR_MESSAGE_TIMEOUT_SUFFIX =
301
306
  "Please check your internet connection and try again. " \
302
- "If this problem persists, you should check Stripe's service " \
303
- "status at https://status.stripe.com, or let us know at " \
304
- "support@stripe.com."
307
+ "If this problem persists, you should check Stripe's service " \
308
+ "status at https://status.stripe.com, or let us know at " \
309
+ "support@stripe.com."
305
310
 
306
311
  ERROR_MESSAGE_TIMEOUT_CONNECT = (
307
312
  "Timed out connecting to Stripe (%s). " +
@@ -361,7 +366,7 @@ module Stripe
361
366
  # garbage in `Thread.current`.
362
367
  attr_accessor :last_responses
363
368
 
364
- # A map of connection mangers for the thread. Normally shared between
369
+ # A map of connection managers for the thread. Normally shared between
365
370
  # all `StripeClient` objects on a particular thread, and created so as to
366
371
  # minimize the number of open connections that an application needs.
367
372
  def default_connection_managers
@@ -431,7 +436,7 @@ module Stripe
431
436
  end
432
437
 
433
438
  private def execute_request_internal(method, path,
434
- api_base, api_key, headers, params,
439
+ api_base, api_key, headers, params, usage,
435
440
  &read_body_chunk_block)
436
441
  raise ArgumentError, "method should be a symbol" \
437
442
  unless method.is_a?(Symbol)
@@ -457,6 +462,7 @@ module Stripe
457
462
 
458
463
  headers = request_headers(api_key, method)
459
464
  .update(Util.normalize_headers(headers))
465
+
460
466
  url = api_url(path, api_base)
461
467
 
462
468
  # Merge given query parameters with any already encoded in the path.
@@ -488,14 +494,12 @@ module Stripe
488
494
  response_block =
489
495
  if block_given?
490
496
  lambda do |response|
491
- unless should_handle_as_error(response.code.to_i)
492
- response.read_body(&read_body_chunk_block)
493
- end
497
+ response.read_body(&read_body_chunk_block) unless should_handle_as_error(response.code.to_i)
494
498
  end
495
499
  end
496
500
 
497
501
  http_resp =
498
- execute_request_with_rescues(method, api_base, headers, context) do
502
+ execute_request_with_rescues(api_base, headers, usage, context) do
499
503
  self.class
500
504
  .default_connection_manager(config)
501
505
  .execute_request(method, url,
@@ -515,18 +519,18 @@ module Stripe
515
519
  private def check_api_key!(api_key)
516
520
  unless api_key
517
521
  raise AuthenticationError, "No API key provided. " \
518
- 'Set your API key using "Stripe.api_key = <API-KEY>". ' \
519
- "You can generate API keys from the Stripe web interface. " \
520
- "See https://stripe.com/api for details, or email " \
521
- "support@stripe.com if you have any questions."
522
+ 'Set your API key using "Stripe.api_key = <API-KEY>". ' \
523
+ "You can generate API keys from the Stripe web interface. " \
524
+ "See https://stripe.com/api for details, or email " \
525
+ "support@stripe.com if you have any questions."
522
526
  end
523
527
 
524
528
  return unless api_key =~ /\s/
525
529
 
526
530
  raise AuthenticationError, "Your API key is invalid, as it contains " \
527
- "whitespace. (HINT: You can double-check your API key from the " \
528
- "Stripe web interface. See https://stripe.com/api for details, or " \
529
- "email support@stripe.com if you have any questions.)"
531
+ "whitespace. (HINT: You can double-check your API key from the " \
532
+ "Stripe web interface. See https://stripe.com/api for details, or " \
533
+ "email support@stripe.com if you have any questions.)"
530
534
  end
531
535
 
532
536
  # Encodes a set of body parameters using multipart if `Content-Type` is set
@@ -565,7 +569,7 @@ module Stripe
565
569
  http_status >= 400
566
570
  end
567
571
 
568
- private def execute_request_with_rescues(method, api_base, headers, context)
572
+ private def execute_request_with_rescues(api_base, headers, usage, context)
569
573
  num_retries = 0
570
574
 
571
575
  begin
@@ -582,9 +586,7 @@ module Stripe
582
586
  http_status = resp.code.to_i
583
587
  context = context.dup_from_response_headers(resp)
584
588
 
585
- if should_handle_as_error(http_status)
586
- handle_error_response(resp, context)
587
- end
589
+ handle_error_response(resp, context) if should_handle_as_error(http_status)
588
590
 
589
591
  log_response(context, request_start, http_status, resp.body, resp)
590
592
  notify_request_end(context, request_duration, http_status,
@@ -593,7 +595,7 @@ module Stripe
593
595
  if config.enable_telemetry? && context.request_id
594
596
  request_duration_ms = (request_duration * 1000).to_i
595
597
  @last_request_metrics =
596
- StripeRequestMetrics.new(context.request_id, request_duration_ms)
598
+ StripeRequestMetrics.new(context.request_id, request_duration_ms, usage: usage + @usage)
597
599
  end
598
600
 
599
601
  # We rescue all exceptions from a request so that we have an easy spot to
@@ -618,7 +620,6 @@ module Stripe
618
620
  user_data, resp, headers)
619
621
 
620
622
  if self.class.should_retry?(e,
621
- method: method,
622
623
  num_retries: num_retries,
623
624
  config: config)
624
625
  num_retries += 1
@@ -634,7 +635,7 @@ module Stripe
634
635
 
635
636
  # Only handle errors when we know we can do so, and re-raise otherwise.
636
637
  # This should be pretty infrequent.
637
- else
638
+ else # rubocop:todo Lint/DuplicateBranch
638
639
  raise
639
640
  end
640
641
  end
@@ -844,7 +845,7 @@ module Stripe
844
845
 
845
846
  if errors.nil?
846
847
  message = "Unexpected error #{error.class.name} communicating " \
847
- "with Stripe. Please let us know at support@stripe.com."
848
+ "with Stripe. Please let us know at support@stripe.com."
848
849
  end
849
850
 
850
851
  api_base ||= config.api_base
@@ -858,9 +859,7 @@ module Stripe
858
859
 
859
860
  private def request_headers(api_key, method)
860
861
  user_agent = "Stripe/v1 RubyBindings/#{Stripe::VERSION}"
861
- unless Stripe.app_info.nil?
862
- user_agent += " " + format_app_info(Stripe.app_info)
863
- end
862
+ user_agent += " " + format_app_info(Stripe.app_info) unless Stripe.app_info.nil?
864
863
 
865
864
  headers = {
866
865
  "User-Agent" => user_agent,
@@ -881,6 +880,7 @@ module Stripe
881
880
  end
882
881
 
883
882
  headers["Stripe-Version"] = config.api_version if config.api_version
883
+
884
884
  headers["Stripe-Account"] = config.stripe_account if config.stripe_account
885
885
 
886
886
  user_agent = @system_profiler.user_agent
@@ -963,15 +963,7 @@ module Stripe
963
963
  # that we can log certain information. It's useful because it means that we
964
964
  # don't have to pass around as many parameters.
965
965
  class RequestLogContext
966
- attr_accessor :body
967
- attr_accessor :account
968
- attr_accessor :api_key
969
- attr_accessor :api_version
970
- attr_accessor :idempotency_key
971
- attr_accessor :method
972
- attr_accessor :path
973
- attr_accessor :query
974
- attr_accessor :request_id
966
+ attr_accessor :body, :account, :api_key, :api_version, :idempotency_key, :method, :path, :query, :request_id
975
967
 
976
968
  # The idea with this method is that we might want to update some of
977
969
  # context information because a response that we've received from the API
@@ -1055,13 +1047,19 @@ module Stripe
1055
1047
  # Request duration in milliseconds
1056
1048
  attr_accessor :request_duration_ms
1057
1049
 
1058
- def initialize(request_id, request_duration_ms)
1050
+ # list of names of tracked behaviors associated with this request
1051
+ attr_accessor :usage
1052
+
1053
+ def initialize(request_id, request_duration_ms, usage: [])
1059
1054
  self.request_id = request_id
1060
1055
  self.request_duration_ms = request_duration_ms
1056
+ self.usage = usage
1061
1057
  end
1062
1058
 
1063
1059
  def payload
1064
- { request_id: request_id, request_duration_ms: request_duration_ms }
1060
+ ret = { request_id: request_id, request_duration_ms: request_duration_ms }
1061
+ ret[:usage] = usage if !usage.nil? && !usage.empty?
1062
+ ret
1065
1063
  end
1066
1064
  end
1067
1065
  end
@@ -25,26 +25,12 @@ module Stripe
25
25
  # If `.logger` is set, the value of `.log_level` is ignored. The decision on
26
26
  # what levels to print is entirely deferred to the logger.
27
27
  class StripeConfiguration
28
- attr_accessor :api_key
29
- attr_accessor :api_version
30
- attr_accessor :client_id
31
- attr_accessor :enable_telemetry
32
- attr_accessor :logger
33
- attr_accessor :stripe_account
34
-
35
- attr_reader :api_base
36
- attr_reader :uploads_base
37
- attr_reader :connect_base
38
- attr_reader :ca_bundle_path
39
- attr_reader :log_level
40
- attr_reader :initial_network_retry_delay
41
- attr_reader :max_network_retries
42
- attr_reader :max_network_retry_delay
43
- attr_reader :open_timeout
44
- attr_reader :read_timeout
45
- attr_reader :write_timeout
46
- attr_reader :proxy
47
- attr_reader :verify_ssl_certs
28
+ attr_accessor :api_key, :api_version, :client_id, :enable_telemetry, :logger, :stripe_account
29
+
30
+ attr_reader :api_base, :uploads_base, :connect_base, :ca_bundle_path, :log_level, :initial_network_retry_delay,
31
+ # rubocop:todo Layout/LineLength
32
+ :max_network_retries, :max_network_retry_delay, :open_timeout, :read_timeout, :write_timeout, :proxy, :verify_ssl_certs
33
+ # rubocop:enable Layout/LineLength
48
34
 
49
35
  def self.setup
50
36
  new.tap do |instance|
@@ -95,8 +81,8 @@ module Stripe
95
81
 
96
82
  if !val.nil? && !levels.include?(val)
97
83
  raise ArgumentError,
98
- "log_level should only be set to `nil`, `debug`, `info`," \
99
- " or `error`"
84
+ "log_level should only be set to `nil`, `debug`, `info`, " \
85
+ "or `error`"
100
86
  end
101
87
  @log_level = val
102
88
  end
@@ -124,9 +110,7 @@ module Stripe
124
110
  end
125
111
 
126
112
  def write_timeout=(write_timeout)
127
- unless Net::HTTP.instance_methods.include?(:write_timeout=)
128
- raise NotImplementedError
129
- end
113
+ raise NotImplementedError unless Net::HTTP.instance_methods.include?(:write_timeout=)
130
114
 
131
115
  @write_timeout = write_timeout
132
116
  StripeClient.clear_all_connection_managers(config: self)
@@ -177,10 +161,10 @@ module Stripe
177
161
  # and is itself not thread safe.
178
162
  def ca_store
179
163
  @ca_store ||= begin
180
- store = OpenSSL::X509::Store.new
181
- store.add_file(ca_bundle_path)
182
- store
183
- end
164
+ store = OpenSSL::X509::Store.new
165
+ store.add_file(ca_bundle_path)
166
+ store
167
+ end
184
168
  end
185
169
 
186
170
  def enable_telemetry?