stripe 10.1.0 → 12.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +215 -21
- data/Gemfile +6 -5
- data/Makefile +8 -1
- data/OPENAPI_VERSION +1 -1
- data/README.md +46 -14
- data/Rakefile +7 -5
- data/VERSION +1 -1
- data/{bin → exe}/stripe-console +1 -1
- data/lib/stripe/api_operations/nested_resource.rb +22 -2
- data/lib/stripe/api_operations/request.rb +22 -18
- data/lib/stripe/api_operations/save.rb +7 -9
- data/lib/stripe/api_operations/search.rb +5 -0
- data/lib/stripe/api_operations/singleton_save.rb +86 -0
- data/lib/stripe/api_resource.rb +13 -4
- data/lib/stripe/api_resource_test_helpers.rb +7 -3
- data/lib/stripe/api_version.rb +1 -1
- data/lib/stripe/connection_manager.rb +4 -6
- data/lib/stripe/errors.rb +3 -11
- data/lib/stripe/instrumentation.rb +5 -21
- data/lib/stripe/list_object.rb +3 -0
- data/lib/stripe/multipart_encoder.rb +7 -7
- data/lib/stripe/oauth.rb +6 -6
- data/lib/stripe/object_types.rb +135 -116
- data/lib/stripe/resources/account.rb +103 -25
- data/lib/stripe/resources/account_link.rb +8 -0
- data/lib/stripe/resources/account_session.rb +8 -0
- data/lib/stripe/resources/alipay_account.rb +1 -1
- data/lib/stripe/resources/apple_pay_domain.rb +43 -0
- data/lib/stripe/resources/application_fee.rb +8 -0
- data/lib/stripe/resources/application_fee_refund.rb +4 -2
- data/lib/stripe/resources/apps/secret.rb +15 -0
- data/lib/stripe/resources/balance.rb +3 -0
- data/lib/stripe/resources/balance_transaction.rb +15 -0
- data/lib/stripe/resources/bank_account.rb +49 -7
- data/lib/stripe/resources/billing/alert.rb +87 -0
- data/lib/stripe/resources/billing/meter.rb +83 -0
- data/lib/stripe/resources/billing/meter_event.rb +27 -0
- data/lib/stripe/resources/billing/meter_event_adjustment.rb +26 -0
- data/lib/stripe/resources/billing/meter_event_summary.rb +15 -0
- data/lib/stripe/resources/billing_portal/configuration.rb +33 -0
- data/lib/stripe/resources/billing_portal/session.rb +14 -1
- data/lib/stripe/resources/capability.rb +4 -2
- data/lib/stripe/resources/card.rb +28 -0
- data/lib/stripe/resources/cash_balance.rb +3 -0
- data/lib/stripe/resources/charge.rb +39 -1
- data/lib/stripe/resources/checkout/session.rb +47 -5
- data/lib/stripe/resources/climate/order.rb +67 -0
- data/lib/stripe/resources/climate/product.rb +27 -0
- data/lib/stripe/resources/climate/supplier.rb +26 -0
- data/lib/stripe/resources/confirmation_token.rb +39 -0
- data/lib/stripe/resources/country_spec.rb +8 -0
- data/lib/stripe/resources/coupon.rb +45 -0
- data/lib/stripe/resources/credit_note.rb +47 -7
- data/lib/stripe/resources/credit_note_line_item.rb +3 -0
- data/lib/stripe/resources/customer.rb +89 -26
- data/lib/stripe/resources/customer_balance_transaction.rb +3 -1
- data/lib/stripe/resources/customer_cash_balance_transaction.rb +3 -2
- data/lib/stripe/resources/customer_session.rb +29 -0
- data/lib/stripe/resources/discount.rb +3 -0
- data/lib/stripe/resources/dispute.rb +26 -0
- data/lib/stripe/resources/entitlements/active_entitlement.rb +26 -0
- data/lib/stripe/resources/entitlements/feature.rb +49 -0
- data/lib/stripe/resources/ephemeral_key.rb +23 -0
- data/lib/stripe/resources/event.rb +11 -3
- data/lib/stripe/resources/exchange_rate.rb +8 -0
- data/lib/stripe/resources/file.rb +29 -16
- data/lib/stripe/resources/file_link.rb +23 -0
- data/lib/stripe/resources/financial_connections/account.rb +66 -7
- data/lib/stripe/resources/financial_connections/account_owner.rb +3 -0
- data/lib/stripe/resources/financial_connections/account_ownership.rb +3 -0
- data/lib/stripe/resources/financial_connections/session.rb +13 -0
- data/lib/stripe/resources/financial_connections/transaction.rb +26 -0
- data/lib/stripe/resources/forwarding/request.rb +52 -0
- data/lib/stripe/resources/funding_instructions.rb +3 -0
- data/lib/stripe/resources/identity/verification_report.rb +14 -1
- data/lib/stripe/resources/identity/verification_session.rb +90 -4
- data/lib/stripe/resources/invoice.rb +170 -17
- data/lib/stripe/resources/invoice_item.rb +43 -0
- data/lib/stripe/resources/invoice_line_item.rb +21 -0
- data/lib/stripe/resources/invoice_rendering_template.rb +63 -0
- data/lib/stripe/resources/issuing/authorization.rb +88 -14
- data/lib/stripe/resources/issuing/card.rb +50 -16
- data/lib/stripe/resources/issuing/cardholder.rb +33 -0
- data/lib/stripe/resources/issuing/dispute.rb +35 -0
- data/lib/stripe/resources/issuing/personalization_design.rb +119 -0
- data/lib/stripe/resources/issuing/physical_bundle.rb +26 -0
- data/lib/stripe/resources/issuing/token.rb +18 -0
- data/lib/stripe/resources/issuing/transaction.rb +30 -0
- data/lib/stripe/resources/line_item.rb +3 -0
- data/lib/stripe/resources/login_link.rb +4 -1
- data/lib/stripe/resources/mandate.rb +3 -0
- data/lib/stripe/resources/payment_intent.rb +190 -25
- data/lib/stripe/resources/payment_link.rb +25 -0
- data/lib/stripe/resources/payment_method.rb +57 -4
- data/lib/stripe/resources/payment_method_configuration.rb +33 -0
- data/lib/stripe/resources/payment_method_domain.rb +46 -1
- data/lib/stripe/resources/payout.rb +39 -4
- data/lib/stripe/resources/person.rb +5 -4
- data/lib/stripe/resources/plan.rb +43 -0
- data/lib/stripe/resources/price.rb +24 -1
- data/lib/stripe/resources/product.rb +47 -1
- data/lib/stripe/resources/product_feature.rb +13 -0
- data/lib/stripe/resources/promotion_code.rb +23 -0
- data/lib/stripe/resources/quote.rb +67 -32
- data/lib/stripe/resources/radar/early_fraud_warning.rb +13 -0
- data/lib/stripe/resources/radar/value_list.rb +53 -0
- data/lib/stripe/resources/radar/value_list_item.rb +43 -0
- data/lib/stripe/resources/refund.rb +46 -0
- data/lib/stripe/resources/reporting/report_run.rb +23 -0
- data/lib/stripe/resources/reporting/report_type.rb +13 -0
- data/lib/stripe/resources/reversal.rb +5 -3
- data/lib/stripe/resources/review.rb +10 -0
- data/lib/stripe/resources/setup_attempt.rb +8 -0
- data/lib/stripe/resources/setup_intent.rb +72 -10
- data/lib/stripe/resources/shipping_rate.rb +23 -0
- data/lib/stripe/resources/sigma/scheduled_query_run.rb +13 -0
- data/lib/stripe/resources/source.rb +23 -1
- data/lib/stripe/resources/source_transaction.rb +3 -0
- data/lib/stripe/resources/subscription.rb +81 -13
- data/lib/stripe/resources/subscription_item.rb +54 -1
- data/lib/stripe/resources/subscription_schedule.rb +41 -4
- data/lib/stripe/resources/tax/calculation.rb +15 -0
- data/lib/stripe/resources/tax/calculation_line_item.rb +3 -0
- data/lib/stripe/resources/tax/registration.rb +35 -0
- data/lib/stripe/resources/tax/settings.rb +4 -2
- data/lib/stripe/resources/tax/transaction.rb +15 -8
- data/lib/stripe/resources/tax/transaction_line_item.rb +3 -0
- data/lib/stripe/resources/tax_code.rb +8 -0
- data/lib/stripe/resources/tax_id.rb +30 -12
- data/lib/stripe/resources/tax_rate.rb +23 -0
- data/lib/stripe/resources/terminal/configuration.rb +53 -0
- data/lib/stripe/resources/terminal/connection_token.rb +13 -0
- data/lib/stripe/resources/terminal/location.rb +54 -0
- data/lib/stripe/resources/terminal/reader.rb +80 -12
- data/lib/stripe/resources/test_helpers/test_clock.rb +45 -0
- data/lib/stripe/resources/token.rb +10 -1
- data/lib/stripe/resources/topup.rb +25 -0
- data/lib/stripe/resources/transfer.rb +26 -1
- data/lib/stripe/resources/treasury/credit_reversal.rb +23 -0
- data/lib/stripe/resources/treasury/debit_reversal.rb +23 -0
- data/lib/stripe/resources/treasury/financial_account.rb +42 -5
- data/lib/stripe/resources/treasury/financial_account_features.rb +3 -0
- data/lib/stripe/resources/treasury/inbound_transfer.rb +47 -11
- data/lib/stripe/resources/treasury/outbound_payment.rb +64 -8
- data/lib/stripe/resources/treasury/outbound_transfer.rb +64 -8
- data/lib/stripe/resources/treasury/received_credit.rb +17 -0
- data/lib/stripe/resources/treasury/received_debit.rb +17 -0
- data/lib/stripe/resources/treasury/transaction.rb +13 -0
- data/lib/stripe/resources/treasury/transaction_entry.rb +13 -0
- data/lib/stripe/resources/usage_record.rb +5 -0
- data/lib/stripe/resources/usage_record_summary.rb +3 -0
- data/lib/stripe/resources/webhook_endpoint.rb +55 -2
- data/lib/stripe/resources.rb +18 -0
- data/lib/stripe/search_result_object.rb +4 -1
- data/lib/stripe/singleton_api_resource.rb +20 -3
- data/lib/stripe/stripe_client.rb +61 -63
- data/lib/stripe/stripe_configuration.rb +13 -29
- data/lib/stripe/stripe_object.rb +23 -21
- data/lib/stripe/stripe_response.rb +1 -3
- data/lib/stripe/util.rb +13 -15
- data/lib/stripe/version.rb +1 -1
- data/lib/stripe.rb +26 -0
- data/stripe.gemspec +7 -4
- 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
|
@@ -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/
|
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/
|
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
|
data/lib/stripe/resources.rb
CHANGED
@@ -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
|
-
|
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/#{
|
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(
|
21
|
-
|
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
|
data/lib/stripe/stripe_client.rb
CHANGED
@@ -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
|
-
|
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
|
151
|
+
# Retry on 500, 503, and other internal errors.
|
150
152
|
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
|
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
|
-
|
291
|
-
|
292
|
-
|
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
|
-
|
296
|
-
|
297
|
-
|
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
|
-
|
303
|
-
|
304
|
-
|
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
|
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(
|
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
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
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
|
-
|
528
|
-
|
529
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
"
|
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
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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?
|