stripe 4.9.0 → 5.1.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.
- checksums.yaml +4 -4
- data/.editorconfig +10 -0
- data/.rubocop.yml +28 -4
- data/.rubocop_todo.yml +11 -22
- data/.travis.yml +3 -6
- data/.vscode/extensions.json +7 -0
- data/.vscode/settings.json +8 -0
- data/CHANGELOG.md +102 -2
- data/Gemfile +2 -10
- data/README.md +96 -40
- data/Rakefile +8 -7
- data/VERSION +1 -1
- data/lib/stripe.rb +64 -85
- data/lib/stripe/api_operations/delete.rb +23 -1
- data/lib/stripe/api_operations/list.rb +0 -6
- data/lib/stripe/api_operations/nested_resource.rb +14 -7
- data/lib/stripe/api_operations/request.rb +3 -7
- data/lib/stripe/api_operations/save.rb +1 -3
- data/lib/stripe/api_resource.rb +50 -2
- data/lib/stripe/connection_manager.rb +141 -0
- data/lib/stripe/error_object.rb +94 -0
- data/lib/stripe/errors.rb +22 -9
- data/lib/stripe/list_object.rb +11 -5
- data/lib/stripe/multipart_encoder.rb +131 -0
- data/lib/stripe/object_types.rb +94 -0
- data/lib/stripe/resources.rb +77 -0
- data/lib/stripe/{account.rb → resources/account.rb} +49 -27
- data/lib/stripe/{account_link.rb → resources/account_link.rb} +1 -1
- data/lib/stripe/resources/alipay_account.rb +34 -0
- data/lib/stripe/{apple_pay_domain.rb → resources/apple_pay_domain.rb} +1 -1
- data/lib/stripe/resources/application_fee.rb +13 -0
- data/lib/stripe/resources/application_fee_refund.rb +30 -0
- data/lib/stripe/{balance.rb → resources/balance.rb} +1 -1
- data/lib/stripe/{balance_transaction.rb → resources/balance_transaction.rb} +1 -5
- data/lib/stripe/{bank_account.rb → resources/bank_account.rb} +14 -4
- data/lib/stripe/{bitcoin_receiver.rb → resources/bitcoin_receiver.rb} +3 -3
- data/lib/stripe/{bitcoin_transaction.rb → resources/bitcoin_transaction.rb} +1 -1
- data/lib/stripe/resources/capability.rb +33 -0
- data/lib/stripe/{card.rb → resources/card.rb} +12 -4
- data/lib/stripe/resources/charge.rb +22 -0
- data/lib/stripe/{checkout → resources/checkout}/session.rb +2 -2
- data/lib/stripe/{country_spec.rb → resources/country_spec.rb} +1 -1
- data/lib/stripe/{coupon.rb → resources/coupon.rb} +2 -2
- data/lib/stripe/resources/credit_note.rb +22 -0
- data/lib/stripe/resources/customer.rb +35 -0
- data/lib/stripe/resources/customer_balance_transaction.rb +30 -0
- data/lib/stripe/resources/discount.rb +7 -0
- data/lib/stripe/{dispute.rb → resources/dispute.rb} +9 -7
- data/lib/stripe/{ephemeral_key.rb → resources/ephemeral_key.rb} +5 -2
- data/lib/stripe/{event.rb → resources/event.rb} +1 -1
- data/lib/stripe/{exchange_rate.rb → resources/exchange_rate.rb} +1 -1
- data/lib/stripe/{file.rb → resources/file.rb} +8 -11
- data/lib/stripe/{file_link.rb → resources/file_link.rb} +2 -2
- data/lib/stripe/resources/invoice.rb +73 -0
- data/lib/stripe/{invoice_item.rb → resources/invoice_item.rb} +2 -2
- data/lib/stripe/{invoice_line_item.rb → resources/invoice_line_item.rb} +1 -1
- data/lib/stripe/resources/issuing/authorization.rb +33 -0
- data/lib/stripe/resources/issuing/card.rb +24 -0
- data/lib/stripe/{issuing → resources/issuing}/card_details.rb +1 -1
- data/lib/stripe/{issuing → resources/issuing}/cardholder.rb +2 -2
- data/lib/stripe/{issuing → resources/issuing}/dispute.rb +2 -2
- data/lib/stripe/{issuing → resources/issuing}/transaction.rb +2 -2
- data/lib/stripe/resources/login_link.rb +14 -0
- data/lib/stripe/resources/order.rb +32 -0
- data/lib/stripe/{order_return.rb → resources/order_return.rb} +1 -1
- data/lib/stripe/resources/payment_intent.rb +42 -0
- data/lib/stripe/resources/payment_method.rb +32 -0
- data/lib/stripe/resources/payout.rb +22 -0
- data/lib/stripe/{person.rb → resources/person.rb} +8 -3
- data/lib/stripe/{plan.rb → resources/plan.rb} +1 -1
- data/lib/stripe/{product.rb → resources/product.rb} +3 -3
- data/lib/stripe/resources/radar/early_fraud_warning.rb +11 -0
- data/lib/stripe/{radar → resources/radar}/value_list.rb +2 -2
- data/lib/stripe/{radar → resources/radar}/value_list_item.rb +2 -2
- data/lib/stripe/{recipient.rb → resources/recipient.rb} +2 -6
- data/lib/stripe/{recipient_transfer.rb → resources/recipient_transfer.rb} +1 -1
- data/lib/stripe/{refund.rb → resources/refund.rb} +1 -1
- data/lib/stripe/{reporting → resources/reporting}/report_run.rb +2 -2
- data/lib/stripe/{reporting → resources/reporting}/report_type.rb +2 -2
- data/lib/stripe/resources/reversal.rb +29 -0
- data/lib/stripe/resources/review.rb +20 -0
- data/lib/stripe/resources/setup_intent.rb +32 -0
- data/lib/stripe/{sigma → resources/sigma}/scheduled_query_run.rb +2 -2
- data/lib/stripe/{sku.rb → resources/sku.rb} +3 -3
- data/lib/stripe/{source.rb → resources/source.rb} +17 -15
- data/lib/stripe/{source_transaction.rb → resources/source_transaction.rb} +1 -1
- data/lib/stripe/resources/subscription.rb +25 -0
- data/lib/stripe/{subscription_item.rb → resources/subscription_item.rb} +5 -2
- data/lib/stripe/resources/subscription_schedule.rb +32 -0
- data/lib/stripe/resources/tax_id.rb +26 -0
- data/lib/stripe/resources/tax_rate.rb +11 -0
- data/lib/stripe/{terminal → resources/terminal}/connection_token.rb +2 -2
- data/lib/stripe/{terminal → resources/terminal}/location.rb +3 -2
- data/lib/stripe/{terminal → resources/terminal}/reader.rb +3 -2
- data/lib/stripe/{three_d_secure.rb → resources/three_d_secure.rb} +1 -1
- data/lib/stripe/{token.rb → resources/token.rb} +1 -1
- data/lib/stripe/resources/topup.rb +22 -0
- data/lib/stripe/resources/transfer.rb +26 -0
- data/lib/stripe/resources/usage_record.rb +7 -0
- data/lib/stripe/{usage_record_summary.rb → resources/usage_record_summary.rb} +1 -1
- data/lib/stripe/{webhook_endpoint.rb → resources/webhook_endpoint.rb} +2 -2
- data/lib/stripe/singleton_api_resource.rb +3 -1
- data/lib/stripe/stripe_client.rb +347 -218
- data/lib/stripe/stripe_object.rb +72 -59
- data/lib/stripe/stripe_response.rb +53 -21
- data/lib/stripe/util.rb +54 -109
- data/lib/stripe/version.rb +1 -1
- data/lib/stripe/webhook.rb +5 -3
- data/stripe.gemspec +14 -5
- data/test/stripe/account_link_test.rb +1 -1
- data/test/stripe/account_test.rb +193 -32
- data/test/stripe/alipay_account_test.rb +1 -1
- data/test/stripe/api_operations_test.rb +3 -4
- data/test/stripe/api_resource_test.rb +119 -30
- data/test/stripe/apple_pay_domain_test.rb +18 -5
- data/test/stripe/application_fee_refund_test.rb +1 -1
- data/test/stripe/application_fee_test.rb +45 -1
- data/test/stripe/balance_test.rb +1 -1
- data/test/stripe/balance_transaction_test.rb +20 -0
- data/test/stripe/bank_account_test.rb +1 -1
- data/test/stripe/capability_test.rb +45 -0
- data/test/stripe/charge_test.rb +13 -8
- data/test/stripe/checkout/session_test.rb +7 -1
- data/test/stripe/connection_manager_test.rb +138 -0
- data/test/stripe/country_spec_test.rb +1 -1
- data/test/stripe/coupon_test.rb +16 -6
- data/test/stripe/credit_note_test.rb +61 -0
- data/test/stripe/customer_balance_transaction_test.rb +37 -0
- data/test/stripe/customer_card_test.rb +1 -1
- data/test/stripe/customer_test.rb +151 -40
- data/test/stripe/dispute_test.rb +10 -1
- data/test/stripe/ephemeral_key_test.rb +8 -1
- data/test/stripe/errors_test.rb +30 -9
- data/test/stripe/exchange_rate_test.rb +1 -1
- data/test/stripe/file_link_test.rb +1 -1
- data/test/stripe/file_test.rb +19 -5
- data/test/stripe/invoice_item_test.rb +18 -7
- data/test/stripe/invoice_line_item_test.rb +1 -1
- data/test/stripe/invoice_test.rb +77 -9
- data/test/stripe/issuing/authorization_test.rb +33 -11
- data/test/stripe/issuing/card_test.rb +15 -6
- data/test/stripe/issuing/cardholder_test.rb +1 -1
- data/test/stripe/issuing/dispute_test.rb +1 -1
- data/test/stripe/issuing/transaction_test.rb +1 -1
- data/test/stripe/list_object_test.rb +1 -17
- data/test/stripe/login_link_test.rb +2 -2
- data/test/stripe/multipart_encoder_test.rb +130 -0
- data/test/stripe/oauth_test.rb +1 -1
- data/test/stripe/order_return_test.rb +1 -1
- data/test/stripe/order_test.rb +28 -3
- data/test/stripe/payment_intent_test.rb +31 -4
- data/test/stripe/payment_method_test.rb +84 -0
- data/test/stripe/payout_test.rb +8 -1
- data/test/stripe/person_test.rb +1 -1
- data/test/stripe/plan_test.rb +26 -20
- data/test/stripe/product_test.rb +16 -6
- data/test/stripe/radar/early_fraud_warning_test.rb +22 -0
- data/test/stripe/radar/value_list_item_test.rb +16 -6
- data/test/stripe/radar/value_list_test.rb +16 -6
- data/test/stripe/recipient_test.rb +18 -5
- data/test/stripe/refund_test.rb +1 -1
- data/test/stripe/reporting/report_run_test.rb +1 -1
- data/test/stripe/reporting/report_type_test.rb +1 -1
- data/test/stripe/reversal_test.rb +1 -1
- data/test/stripe/review_test.rb +1 -1
- data/test/stripe/setup_intent_test.rb +84 -0
- data/test/stripe/sigma/scheduled_query_run_test.rb +1 -1
- data/test/stripe/sku_test.rb +16 -6
- data/test/stripe/source_test.rb +14 -19
- data/test/stripe/source_transaction_test.rb +1 -1
- data/test/stripe/stripe_client_test.rb +242 -26
- data/test/stripe/stripe_object_test.rb +8 -36
- data/test/stripe/stripe_response_test.rb +71 -25
- data/test/stripe/subscription_item_test.rb +28 -6
- data/test/stripe/subscription_schedule_test.rb +19 -1
- data/test/stripe/subscription_test.rb +29 -9
- data/test/stripe/tax_id_test.rb +31 -0
- data/test/stripe/tax_rate_test.rb +43 -0
- data/test/stripe/terminal/connection_token_test.rb +1 -1
- data/test/stripe/terminal/location_test.rb +18 -1
- data/test/stripe/terminal/reader_test.rb +18 -1
- data/test/stripe/three_d_secure_test.rb +1 -1
- data/test/stripe/topup_test.rb +9 -1
- data/test/stripe/transfer_test.rb +46 -1
- data/test/stripe/usage_record_summary_test.rb +1 -1
- data/test/stripe/util_test.rb +1 -1
- data/test/stripe/webhook_endpoint_test.rb +18 -1
- data/test/stripe/webhook_test.rb +4 -4
- data/test/stripe_mock.rb +4 -3
- data/test/stripe_test.rb +1 -14
- data/test/test_helper.rb +14 -11
- metadata +117 -125
- data/lib/stripe/alipay_account.rb +0 -27
- data/lib/stripe/application_fee.rb +0 -23
- data/lib/stripe/application_fee_refund.rb +0 -22
- data/lib/stripe/charge.rb +0 -84
- data/lib/stripe/customer.rb +0 -90
- data/lib/stripe/invoice.rb +0 -48
- data/lib/stripe/issuer_fraud_record.rb +0 -9
- data/lib/stripe/issuing/authorization.rb +0 -22
- data/lib/stripe/issuing/card.rb +0 -18
- data/lib/stripe/login_link.rb +0 -11
- data/lib/stripe/order.rb +0 -31
- data/lib/stripe/payment_intent.rb +0 -26
- data/lib/stripe/payout.rb +0 -20
- data/lib/stripe/reversal.rb +0 -22
- data/lib/stripe/review.rb +0 -14
- data/lib/stripe/subscription.rb +0 -25
- data/lib/stripe/subscription_schedule.rb +0 -32
- data/lib/stripe/subscription_schedule_revision.rb +0 -25
- data/lib/stripe/topup.rb +0 -16
- data/lib/stripe/transfer.rb +0 -23
- data/lib/stripe/usage_record.rb +0 -14
- data/test/stripe/account_external_accounts_operations_test.rb +0 -69
- data/test/stripe/account_login_links_operations_test.rb +0 -21
- data/test/stripe/account_persons_operations_test.rb +0 -70
- data/test/stripe/application_fee_refunds_operations_test.rb +0 -56
- data/test/stripe/customer_sources_operations_test.rb +0 -64
- data/test/stripe/file_upload_test.rb +0 -76
- data/test/stripe/issuer_fraud_record_test.rb +0 -20
- data/test/stripe/subscription_schedule_revision_test.rb +0 -37
- data/test/stripe/subscription_schedule_revisions_operations_test.rb +0 -35
- data/test/stripe/transfer_reversals_operations_test.rb +0 -57
- data/test/stripe/usage_record_test.rb +0 -28
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stripe
|
4
|
+
# Manages connections across multiple hosts which is useful because the
|
5
|
+
# library may connect to multiple hosts during a typical session (main API,
|
6
|
+
# Connect, Uploads). Ruby doesn't provide an easy way to make this happen
|
7
|
+
# easily, so this class is designed to track what we're connected to and
|
8
|
+
# manage the lifecycle of those connections.
|
9
|
+
#
|
10
|
+
# Note that this class in itself is *not* thread safe. We expect it to be
|
11
|
+
# instantiated once per thread.
|
12
|
+
#
|
13
|
+
# Note also that this class doesn't currently clean up after itself because
|
14
|
+
# it expects to only ever have a few connections (unless `.clear` is called
|
15
|
+
# manually). It'd be possible to tank memory by constantly changing the value
|
16
|
+
# of `Stripe.api_base` or the like. A possible improvement might be to detect
|
17
|
+
# and prune old connections whenever a request is executed.
|
18
|
+
class ConnectionManager
|
19
|
+
def initialize
|
20
|
+
@active_connections = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Finishes any active connections by closing their TCP connection and
|
24
|
+
# clears them from internal tracking.
|
25
|
+
def clear
|
26
|
+
@active_connections.each do |_, connection|
|
27
|
+
connection.finish
|
28
|
+
end
|
29
|
+
@active_connections = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gets a connection for a given URI. This is for internal use only as it's
|
33
|
+
# subject to change (we've moved between HTTP client schemes in the past
|
34
|
+
# and may do it again).
|
35
|
+
#
|
36
|
+
# `uri` is expected to be a string.
|
37
|
+
def connection_for(uri)
|
38
|
+
u = URI.parse(uri)
|
39
|
+
connection = @active_connections[[u.host, u.port]]
|
40
|
+
|
41
|
+
if connection.nil?
|
42
|
+
connection = create_connection(u)
|
43
|
+
connection.start
|
44
|
+
|
45
|
+
@active_connections[[u.host, u.port]] = connection
|
46
|
+
end
|
47
|
+
|
48
|
+
connection
|
49
|
+
end
|
50
|
+
|
51
|
+
# Executes an HTTP request to the given URI with the given method. Also
|
52
|
+
# allows a request body, headers, and query string to be specified.
|
53
|
+
def execute_request(method, uri, body: nil, headers: nil, query: nil)
|
54
|
+
# Perform some basic argument validation because it's easy to get
|
55
|
+
# confused between strings and hashes for things like body and query
|
56
|
+
# parameters.
|
57
|
+
raise ArgumentError, "method should be a symbol" \
|
58
|
+
unless method.is_a?(Symbol)
|
59
|
+
raise ArgumentError, "uri should be a string" \
|
60
|
+
unless uri.is_a?(String)
|
61
|
+
raise ArgumentError, "body should be a string" \
|
62
|
+
if body && !body.is_a?(String)
|
63
|
+
raise ArgumentError, "headers should be a hash" \
|
64
|
+
if headers && !headers.is_a?(Hash)
|
65
|
+
raise ArgumentError, "query should be a string" \
|
66
|
+
if query && !query.is_a?(String)
|
67
|
+
|
68
|
+
connection = connection_for(uri)
|
69
|
+
|
70
|
+
u = URI.parse(uri)
|
71
|
+
path = if query
|
72
|
+
u.path + "?" + query
|
73
|
+
else
|
74
|
+
u.path
|
75
|
+
end
|
76
|
+
|
77
|
+
connection.send_request(method.to_s.upcase, path, body, headers)
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# private
|
82
|
+
#
|
83
|
+
|
84
|
+
# `uri` should be a parsed `URI` object.
|
85
|
+
private def create_connection(uri)
|
86
|
+
# These all come back as `nil` if no proxy is configured.
|
87
|
+
proxy_host, proxy_port, proxy_user, proxy_pass = proxy_parts
|
88
|
+
|
89
|
+
connection = Net::HTTP.new(uri.host, uri.port,
|
90
|
+
proxy_host, proxy_port,
|
91
|
+
proxy_user, proxy_pass)
|
92
|
+
|
93
|
+
# Time in seconds within which Net::HTTP will try to reuse an already
|
94
|
+
# open connection when issuing a new operation. Outside this window, Ruby
|
95
|
+
# will transparently close and re-open the connection without trying to
|
96
|
+
# reuse it.
|
97
|
+
#
|
98
|
+
# Ruby's default of 2 seconds is almost certainly too short. Here I've
|
99
|
+
# reused Go's default for `DefaultTransport`.
|
100
|
+
connection.keep_alive_timeout = 30
|
101
|
+
|
102
|
+
connection.open_timeout = Stripe.open_timeout
|
103
|
+
connection.read_timeout = Stripe.read_timeout
|
104
|
+
|
105
|
+
connection.use_ssl = uri.scheme == "https"
|
106
|
+
|
107
|
+
if Stripe.verify_ssl_certs
|
108
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
109
|
+
connection.cert_store = Stripe.ca_store
|
110
|
+
else
|
111
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
112
|
+
warn_ssl_verify_none
|
113
|
+
end
|
114
|
+
|
115
|
+
connection
|
116
|
+
end
|
117
|
+
|
118
|
+
# `Net::HTTP` somewhat awkwardly requires each component of a proxy URI
|
119
|
+
# (host, port, etc.) rather than the URI itself. This method simply parses
|
120
|
+
# out those pieces to make passing them into a new connection a little less
|
121
|
+
# ugly.
|
122
|
+
private def proxy_parts
|
123
|
+
if Stripe.proxy.nil?
|
124
|
+
[nil, nil, nil, nil]
|
125
|
+
else
|
126
|
+
u = URI.parse(Stripe.proxy)
|
127
|
+
[u.host, u.port, u.user, u.password]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private def warn_ssl_verify_none
|
132
|
+
return if @verify_ssl_warned
|
133
|
+
|
134
|
+
@verify_ssl_warned = true
|
135
|
+
warn("WARNING: Running without SSL cert verification. " \
|
136
|
+
"You should never do this in production. " \
|
137
|
+
"Execute `Stripe.verify_ssl_certs = true` to enable " \
|
138
|
+
"verification.")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stripe
|
4
|
+
# Represents an error object as returned by the API.
|
5
|
+
#
|
6
|
+
# @see https://stripe.com/docs/api/errors
|
7
|
+
class ErrorObject < StripeObject
|
8
|
+
# Unlike other objects, we explicitly declare getter methods here. This
|
9
|
+
# is because the API doesn't return `null` values for fields on this
|
10
|
+
# object, rather the fields are omitted entirely. Not declaring the getter
|
11
|
+
# methods would cause users to run into `NoMethodError` exceptions and
|
12
|
+
# get in the way of generic error handling.
|
13
|
+
|
14
|
+
# For card errors, the ID of the failed charge.
|
15
|
+
def charge
|
16
|
+
@values[:charge]
|
17
|
+
end
|
18
|
+
|
19
|
+
# For some errors that could be handled programmatically, a short string
|
20
|
+
# indicating the error code reported.
|
21
|
+
def code
|
22
|
+
@values[:code]
|
23
|
+
end
|
24
|
+
|
25
|
+
# For card errors resulting from a card issuer decline, a short string
|
26
|
+
# indicating the card issuer's reason for the decline if they provide one.
|
27
|
+
def decline_code
|
28
|
+
@values[:decline_code]
|
29
|
+
end
|
30
|
+
|
31
|
+
# A URL to more information about the error code reported.
|
32
|
+
def doc_url
|
33
|
+
@values[:doc_url]
|
34
|
+
end
|
35
|
+
|
36
|
+
# A human-readable message providing more details about the error. For card
|
37
|
+
# errors, these messages can be shown to your users.
|
38
|
+
def message
|
39
|
+
@values[:message]
|
40
|
+
end
|
41
|
+
|
42
|
+
# If the error is parameter-specific, the parameter related to the error.
|
43
|
+
# For example, you can use this to display a message near the correct form
|
44
|
+
# field.
|
45
|
+
def param
|
46
|
+
@values[:param]
|
47
|
+
end
|
48
|
+
|
49
|
+
# The PaymentIntent object for errors returned on a request involving a
|
50
|
+
# PaymentIntent.
|
51
|
+
def payment_intent
|
52
|
+
@values[:payment_intent]
|
53
|
+
end
|
54
|
+
|
55
|
+
# The PaymentMethod object for errors returned on a request involving a
|
56
|
+
# PaymentMethod.
|
57
|
+
def payment_method
|
58
|
+
@values[:payment_method]
|
59
|
+
end
|
60
|
+
|
61
|
+
# The SetupIntent object for errors returned on a request involving a
|
62
|
+
# SetupIntent.
|
63
|
+
def setup_intent
|
64
|
+
@values[:setup_intent]
|
65
|
+
end
|
66
|
+
|
67
|
+
# The source object for errors returned on a request involving a source.
|
68
|
+
def source
|
69
|
+
@values[:source]
|
70
|
+
end
|
71
|
+
|
72
|
+
# The type of error returned. One of `api_connection_error`, `api_error`,
|
73
|
+
# `authentication_error`, `card_error`, `idempotency_error`,
|
74
|
+
# `invalid_request_error`, or `rate_limit_error`.
|
75
|
+
def type
|
76
|
+
@values[:type]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Represents on OAuth error returned by the OAuth API.
|
81
|
+
#
|
82
|
+
# @see https://stripe.com/docs/connect/oauth-reference#post-token-errors
|
83
|
+
class OAuthErrorObject < StripeObject
|
84
|
+
# A unique error code per error type.
|
85
|
+
def error
|
86
|
+
@values[:error]
|
87
|
+
end
|
88
|
+
|
89
|
+
# A human readable description of the error.
|
90
|
+
def error_description
|
91
|
+
@values[:error_description]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/stripe/errors.rb
CHANGED
@@ -11,6 +11,7 @@ module Stripe
|
|
11
11
|
attr_accessor :response
|
12
12
|
|
13
13
|
attr_reader :code
|
14
|
+
attr_reader :error
|
14
15
|
attr_reader :http_body
|
15
16
|
attr_reader :http_headers
|
16
17
|
attr_reader :http_status
|
@@ -18,8 +19,8 @@ module Stripe
|
|
18
19
|
attr_reader :request_id
|
19
20
|
|
20
21
|
# Initializes a StripeError.
|
21
|
-
def initialize(message = nil, http_status: nil, http_body: nil,
|
22
|
-
http_headers: nil, code: nil)
|
22
|
+
def initialize(message = nil, http_status: nil, http_body: nil,
|
23
|
+
json_body: nil, http_headers: nil, code: nil)
|
23
24
|
@message = message
|
24
25
|
@http_status = http_status
|
25
26
|
@http_body = http_body
|
@@ -27,6 +28,13 @@ module Stripe
|
|
27
28
|
@json_body = json_body
|
28
29
|
@code = code
|
29
30
|
@request_id = @http_headers[:request_id]
|
31
|
+
@error = construct_error_object
|
32
|
+
end
|
33
|
+
|
34
|
+
def construct_error_object
|
35
|
+
return nil if @json_body.nil? || !@json_body.key?(:error)
|
36
|
+
|
37
|
+
ErrorObject.construct_from(@json_body[:error])
|
30
38
|
end
|
31
39
|
|
32
40
|
def to_s
|
@@ -59,9 +67,8 @@ module Stripe
|
|
59
67
|
class CardError < StripeError
|
60
68
|
attr_reader :param
|
61
69
|
|
62
|
-
|
63
|
-
|
64
|
-
http_headers: nil)
|
70
|
+
def initialize(message, param, code: nil, http_status: nil, http_body: nil,
|
71
|
+
json_body: nil, http_headers: nil)
|
65
72
|
super(message, http_status: http_status, http_body: http_body,
|
66
73
|
json_body: json_body, http_headers: http_headers,
|
67
74
|
code: code)
|
@@ -79,8 +86,8 @@ module Stripe
|
|
79
86
|
class InvalidRequestError < StripeError
|
80
87
|
attr_accessor :param
|
81
88
|
|
82
|
-
def initialize(message, param, http_status: nil, http_body: nil,
|
83
|
-
http_headers: nil, code: nil)
|
89
|
+
def initialize(message, param, http_status: nil, http_body: nil,
|
90
|
+
json_body: nil, http_headers: nil, code: nil)
|
84
91
|
super(message, http_status: http_status, http_body: http_body,
|
85
92
|
json_body: json_body, http_headers: http_headers,
|
86
93
|
code: code)
|
@@ -113,12 +120,18 @@ module Stripe
|
|
113
120
|
module OAuth
|
114
121
|
# OAuthError is raised when the OAuth API returns an error.
|
115
122
|
class OAuthError < StripeError
|
116
|
-
def initialize(code, description, http_status: nil, http_body: nil,
|
117
|
-
http_headers: nil)
|
123
|
+
def initialize(code, description, http_status: nil, http_body: nil,
|
124
|
+
json_body: nil, http_headers: nil)
|
118
125
|
super(description, http_status: http_status, http_body: http_body,
|
119
126
|
json_body: json_body, http_headers: http_headers,
|
120
127
|
code: code)
|
121
128
|
end
|
129
|
+
|
130
|
+
def construct_error_object
|
131
|
+
return nil if @json_body.nil?
|
132
|
+
|
133
|
+
OAuthErrorObject.construct_from(@json_body)
|
134
|
+
end
|
122
135
|
end
|
123
136
|
|
124
137
|
# InvalidClientError is raised when the client doesn't belong to you, or
|
data/lib/stripe/list_object.rb
CHANGED
@@ -7,7 +7,7 @@ module Stripe
|
|
7
7
|
include Stripe::APIOperations::Request
|
8
8
|
include Stripe::APIOperations::Create
|
9
9
|
|
10
|
-
OBJECT_NAME = "list"
|
10
|
+
OBJECT_NAME = "list"
|
11
11
|
|
12
12
|
# This accessor allows a `ListObject` to inherit various filters that were
|
13
13
|
# given to a predecessor. This allows for things like consistent limits,
|
@@ -26,12 +26,16 @@ module Stripe
|
|
26
26
|
self.filters = {}
|
27
27
|
end
|
28
28
|
|
29
|
-
def [](
|
30
|
-
case
|
29
|
+
def [](key)
|
30
|
+
case key
|
31
31
|
when String, Symbol
|
32
32
|
super
|
33
33
|
else
|
34
|
-
raise ArgumentError,
|
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)}",
|
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
|
|
@@ -78,6 +83,7 @@ module Stripe
|
|
78
83
|
# was given, the default limit will be fetched again.
|
79
84
|
def next_page(params = {}, opts = {})
|
80
85
|
return self.class.empty_list(opts) unless has_more
|
86
|
+
|
81
87
|
last_id = data.last.id
|
82
88
|
|
83
89
|
params = filters.merge(starting_after: last_id).merge(params)
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
require "tempfile"
|
5
|
+
|
6
|
+
module Stripe
|
7
|
+
# Encodes parameters into a `multipart/form-data` payload as described by RFC
|
8
|
+
# 2388:
|
9
|
+
#
|
10
|
+
# https://tools.ietf.org/html/rfc2388
|
11
|
+
#
|
12
|
+
# This is most useful for transferring file-like objects.
|
13
|
+
#
|
14
|
+
# Parameters should be added with `#encode`. When ready, use `#body` to get
|
15
|
+
# the encoded result and `#content_type` to get the value that should be
|
16
|
+
# placed in the `Content-Type` header of a subsequent request (which includes
|
17
|
+
# a boundary value).
|
18
|
+
class MultipartEncoder
|
19
|
+
MULTIPART_FORM_DATA = "multipart/form-data"
|
20
|
+
|
21
|
+
# A shortcut for encoding a single set of parameters and finalizing a
|
22
|
+
# result.
|
23
|
+
#
|
24
|
+
# Returns an encoded body and the value that should be set in the content
|
25
|
+
# type header of a subsequent request.
|
26
|
+
def self.encode(params)
|
27
|
+
encoder = MultipartEncoder.new
|
28
|
+
encoder.encode(params)
|
29
|
+
encoder.close
|
30
|
+
[encoder.body, encoder.content_type]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Gets the object's randomly generated boundary string.
|
34
|
+
attr_reader :boundary
|
35
|
+
|
36
|
+
# Initializes a new multipart encoder.
|
37
|
+
def initialize
|
38
|
+
# Kind of weird, but required by Rubocop because the unary plus operator
|
39
|
+
# is considered faster than `Stripe.new`.
|
40
|
+
@body = +""
|
41
|
+
|
42
|
+
# Chose the same number of random bytes that Go uses in its standard
|
43
|
+
# library implementation. Easily enough entropy to ensure that it won't
|
44
|
+
# be present in a file we're sending.
|
45
|
+
@boundary = SecureRandom.hex(30)
|
46
|
+
|
47
|
+
@closed = false
|
48
|
+
@first_field = true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gets the encoded body. `#close` must be called first.
|
52
|
+
def body
|
53
|
+
raise "object must be closed before getting body" unless @closed
|
54
|
+
|
55
|
+
@body
|
56
|
+
end
|
57
|
+
|
58
|
+
# Finalizes the object by writing the final boundary.
|
59
|
+
def close
|
60
|
+
raise "object already closed" if @closed
|
61
|
+
|
62
|
+
@body << "\r\n"
|
63
|
+
@body << "--#{@boundary}--"
|
64
|
+
|
65
|
+
@closed = true
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# Gets the value including boundary that should be put into a multipart
|
71
|
+
# request's `Content-Type`.
|
72
|
+
def content_type
|
73
|
+
"#{MULTIPART_FORM_DATA}; boundary=#{@boundary}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Encodes a set of parameters to the body.
|
77
|
+
#
|
78
|
+
# Note that parameters are expected to be a hash, but a "flat" hash such
|
79
|
+
# that complex substructures like hashes and arrays have already been
|
80
|
+
# appropriately Stripe-encoded. Pass a complex structure through
|
81
|
+
# `Util.flatten_params` first before handing it off to this method.
|
82
|
+
def encode(params)
|
83
|
+
raise "no more parameters can be written to closed object" if @closed
|
84
|
+
|
85
|
+
params.each do |name, val|
|
86
|
+
if val.is_a?(::File) || val.is_a?(::Tempfile)
|
87
|
+
write_field(name, val.read, filename: ::File.basename(val.path))
|
88
|
+
elsif val.respond_to?(:read)
|
89
|
+
write_field(name, val.read, filename: "blob")
|
90
|
+
else
|
91
|
+
write_field(name, val, filename: nil)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# private
|
100
|
+
#
|
101
|
+
|
102
|
+
# Escapes double quotes so that the given value can be used in a
|
103
|
+
# double-quoted string and replaces any linebreak characters with spaces.
|
104
|
+
private def escape(str)
|
105
|
+
str.gsub('"', "%22").tr("\n", " ").tr("\r", " ")
|
106
|
+
end
|
107
|
+
|
108
|
+
private def write_field(name, data, filename:)
|
109
|
+
if !@first_field
|
110
|
+
@body << "\r\n"
|
111
|
+
else
|
112
|
+
@first_field = false
|
113
|
+
end
|
114
|
+
|
115
|
+
@body << "--#{@boundary}\r\n"
|
116
|
+
|
117
|
+
if filename
|
118
|
+
@body << %(Content-Disposition: form-data) +
|
119
|
+
%(; name="#{escape(name.to_s)}") +
|
120
|
+
%(; filename="#{escape(filename)}"\r\n)
|
121
|
+
@body << %(Content-Type: application/octet-stream\r\n)
|
122
|
+
else
|
123
|
+
@body << %(Content-Disposition: form-data) +
|
124
|
+
%(; name="#{escape(name.to_s)}"\r\n)
|
125
|
+
end
|
126
|
+
|
127
|
+
@body << "\r\n"
|
128
|
+
@body << data.to_s
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|