stripe 1.58.0 → 2.0.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/.gitattributes +4 -0
- data/.travis.yml +1 -2
- data/Gemfile +11 -12
- data/History.txt +8 -0
- data/README.md +44 -31
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/stripe.rb +4 -344
- data/lib/stripe/account.rb +4 -4
- data/lib/stripe/api_operations/create.rb +2 -2
- data/lib/stripe/api_operations/delete.rb +2 -2
- data/lib/stripe/api_operations/list.rb +2 -2
- data/lib/stripe/api_operations/request.rb +9 -3
- data/lib/stripe/api_operations/save.rb +4 -6
- data/lib/stripe/api_resource.rb +2 -2
- data/lib/stripe/bank_account.rb +2 -2
- data/lib/stripe/bitcoin_receiver.rb +1 -1
- data/lib/stripe/charge.rb +12 -12
- data/lib/stripe/customer.rb +6 -6
- data/lib/stripe/dispute.rb +2 -3
- data/lib/stripe/errors.rb +20 -10
- data/lib/stripe/invoice.rb +4 -4
- data/lib/stripe/list_object.rb +2 -2
- data/lib/stripe/order.rb +4 -4
- data/lib/stripe/reversal.rb +1 -1
- data/lib/stripe/source.rb +2 -2
- data/lib/stripe/stripe_client.rb +396 -0
- data/lib/stripe/stripe_response.rb +48 -0
- data/lib/stripe/transfer.rb +2 -2
- data/lib/stripe/util.rb +6 -6
- data/lib/stripe/version.rb +1 -1
- data/spec/fixtures.json +0 -0
- data/spec/fixtures.yaml +0 -0
- data/spec/spec.json +0 -0
- data/spec/spec.yaml +0 -0
- data/stripe.gemspec +1 -1
- data/test/api_fixtures.rb +29 -0
- data/test/api_stub_helpers.rb +125 -0
- data/test/stripe/account_test.rb +153 -247
- data/test/stripe/alipay_account_test.rb +10 -2
- data/test/stripe/api_operations_test.rb +3 -3
- data/test/stripe/api_resource_test.rb +139 -499
- data/test/stripe/apple_pay_domain_test.rb +22 -23
- data/test/stripe/application_fee_refund_test.rb +22 -31
- data/test/stripe/application_fee_test.rb +6 -17
- data/test/stripe/balance_test.rb +3 -3
- data/test/stripe/bank_account_test.rb +31 -11
- data/test/stripe/bitcoin_receiver_test.rb +51 -42
- data/test/stripe/bitcoin_transaction_test.rb +11 -19
- data/test/stripe/charge_test.rb +39 -126
- data/test/stripe/country_spec_test.rb +7 -30
- data/test/stripe/coupon_test.rb +33 -17
- data/test/stripe/customer_card_test.rb +25 -46
- data/test/stripe/customer_test.rb +86 -81
- data/test/stripe/dispute_test.rb +27 -38
- data/test/stripe/errors_test.rb +2 -2
- data/test/stripe/file_upload_test.rb +32 -24
- data/test/stripe/invoice_item_test.rb +46 -10
- data/test/stripe/invoice_test.rb +48 -48
- data/test/stripe/list_object_test.rb +22 -31
- data/test/stripe/order_return_test.rb +11 -15
- data/test/stripe/order_test.rb +38 -51
- data/test/stripe/plan_test.rb +39 -18
- data/test/stripe/product_test.rb +29 -33
- data/test/stripe/recipient_card_test.rb +23 -40
- data/test/stripe/recipient_test.rb +39 -10
- data/test/stripe/refund_test.rb +20 -45
- data/test/stripe/reversal_test.rb +27 -31
- data/test/stripe/sku_test.rb +36 -19
- data/test/stripe/source_test.rb +26 -66
- data/test/stripe/stripe_client_test.rb +428 -0
- data/test/stripe/stripe_object_test.rb +6 -2
- data/test/stripe/stripe_response_test.rb +46 -0
- data/test/stripe/subscription_item_test.rb +37 -59
- data/test/stripe/subscription_test.rb +40 -176
- data/test/stripe/three_d_secure_test.rb +13 -12
- data/test/stripe/transfer_test.rb +36 -19
- data/test/stripe_test.rb +3 -36
- data/test/test_data.rb +5 -931
- data/test/test_helper.rb +21 -25
- metadata +22 -17
- data/test/stripe/charge_refund_test.rb +0 -67
- data/test/stripe/metadata_test.rb +0 -129
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe6ecafb3e94d2c21da1cad428be4ac9fda47ed9
|
4
|
+
data.tar.gz: d69bf4b5289a9661d3d8a9383bb4acea4cb2c0b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 381878036316652650840edfa24814e60b21ce6813a9e8cc4a5e58ff000349434d7947e63e51390d962d817755e0b40b68a1370781262b982cef93aa90296879
|
7
|
+
data.tar.gz: 9afa8b57e838b7a44264f302afbb2c9b62c40176dc699a17ff83fb5fe50c4c481f0cf7de3f83dd7c7ec70211dc466d5a22e290b3157cbb2ed34bc10562871bac
|
data/.gitattributes
ADDED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,23 +3,21 @@ source "https://rubygems.org"
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :development do
|
6
|
+
gem 'committee', '2.0.0.pre6'
|
6
7
|
gem 'mocha', '~> 0.13.2'
|
7
|
-
gem 'pry'
|
8
8
|
gem 'rake'
|
9
9
|
gem 'shoulda-context'
|
10
|
+
gem 'sinatra'
|
10
11
|
gem 'test-unit'
|
12
|
+
gem 'webmock'
|
11
13
|
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
|
21
|
-
gem 'mime-types', '2.6.2'
|
22
|
-
gem 'rest-client', '1.8.0'
|
14
|
+
# Rack 2.0+ requires Ruby >= 2.2.2 which is problematic for the test suite on
|
15
|
+
# older Ruby versions. Check Ruby the version here and put a maximum
|
16
|
+
# constraint on Rack if necessary.
|
17
|
+
if RUBY_VERSION >= '2.2.2'
|
18
|
+
gem "rack", ">= 1.5"
|
19
|
+
else
|
20
|
+
gem "rack", ">= 1.5", "< 2.0"
|
23
21
|
end
|
24
22
|
|
25
23
|
platforms :mri do
|
@@ -27,6 +25,7 @@ group :development do
|
|
27
25
|
# it's known to work well
|
28
26
|
if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0')
|
29
27
|
gem 'byebug'
|
28
|
+
gem 'pry'
|
30
29
|
gem 'pry-byebug'
|
31
30
|
end
|
32
31
|
end
|
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 2.0.0 2017-02-14
|
2
|
+
|
3
|
+
* Drop support for Ruby 1.9
|
4
|
+
* Allow HTTP client that makes Stripe calls to be configured via Faraday
|
5
|
+
* Drop RestClient
|
6
|
+
* Switch to OpenAPI 2.0 spec and generated fixtures in test suite
|
7
|
+
* Switch to Webmock in test suite
|
8
|
+
|
1
9
|
=== 1.58.0 2017-01-19
|
2
10
|
|
3
11
|
* Remove erroneously added list methods for `Source` model
|
data/README.md
CHANGED
@@ -32,8 +32,7 @@ If you want to build the gem from source:
|
|
32
32
|
|
33
33
|
### Requirements
|
34
34
|
|
35
|
-
* Ruby
|
36
|
-
* rest-client
|
35
|
+
* Ruby 2.0+.
|
37
36
|
|
38
37
|
### Bundler
|
39
38
|
|
@@ -51,8 +50,8 @@ gem 'stripe'
|
|
51
50
|
## Usage
|
52
51
|
|
53
52
|
The library needs to be configured with your account's secret key which is
|
54
|
-
available in
|
55
|
-
|
53
|
+
available in your [Stripe Dashboard][dashboard]. Set `Stripe.api_key` to its
|
54
|
+
value:
|
56
55
|
|
57
56
|
``` ruby
|
58
57
|
require "stripe"
|
@@ -67,14 +66,11 @@ Stripe::Charge.retrieve(
|
|
67
66
|
)
|
68
67
|
```
|
69
68
|
|
70
|
-
|
71
|
-
This is often useful for Connect applications that use multiple API keys during
|
72
|
-
the lifetime of a process.
|
69
|
+
### Per-request Configuration
|
73
70
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
For example:
|
71
|
+
For apps that need to use multiple keys during the lifetime of a process, like
|
72
|
+
one that uses [Stripe Connect][connect], it's also possible to set a
|
73
|
+
per-request key and/or account:
|
78
74
|
|
79
75
|
``` ruby
|
80
76
|
require "stripe"
|
@@ -92,6 +88,40 @@ Stripe::Charge.retrieve(
|
|
92
88
|
)
|
93
89
|
```
|
94
90
|
|
91
|
+
### Configuring a Client
|
92
|
+
|
93
|
+
While a default HTTP client is used by default, it's also possible to have the
|
94
|
+
library use any client supported by [Faraday][faraday] by initializing a
|
95
|
+
`Stripe::StripeClient` object and giving it a connection:
|
96
|
+
|
97
|
+
``` ruby
|
98
|
+
conn = Faraday.new
|
99
|
+
client = Stripe::StripeClient.new(conn)
|
100
|
+
client.request do
|
101
|
+
charge, resp = Stripe::Charge.retrieve(
|
102
|
+
"ch_18atAXCdGbJFKhCuBAa4532Z",
|
103
|
+
)
|
104
|
+
end
|
105
|
+
puts resp.request_id
|
106
|
+
```
|
107
|
+
|
108
|
+
### Configuring CA Bundles
|
109
|
+
|
110
|
+
By default, the library will use its own internal bundle of known CA
|
111
|
+
certificates, but it's possible to configure your own:
|
112
|
+
|
113
|
+
Stripe.ca_bundle_path = "path/to/ca/bundle"
|
114
|
+
|
115
|
+
### Configuring Automatic Retries
|
116
|
+
|
117
|
+
The library can be configured to automatically retry requests that fail due to
|
118
|
+
an intermittent network problem:
|
119
|
+
|
120
|
+
Stripe.max_network_retries = 2
|
121
|
+
|
122
|
+
[Idempotency keys][idempotency-keys] are added to requests to guarantee that
|
123
|
+
retries are safe.
|
124
|
+
|
95
125
|
## Development
|
96
126
|
|
97
127
|
Run all tests:
|
@@ -110,25 +140,8 @@ Update bundled CA certificates from the [Mozilla cURL release][curl]:
|
|
110
140
|
|
111
141
|
bundle exec rake update_certs
|
112
142
|
|
113
|
-
|
114
|
-
|
115
|
-
### ca_bundle_path
|
116
|
-
|
117
|
-
The location of a file containing a bundle of CA certificates. By default the
|
118
|
-
library will use an included bundle that can successfully validate Stripe
|
119
|
-
certificates.
|
120
|
-
|
121
|
-
### max_network_retries
|
122
|
-
|
123
|
-
When `max_network_retries` is set to a positive integer, stripe will retry
|
124
|
-
requests that fail on a network error. Idempotency keys will be added to `POST`
|
125
|
-
and `DELETE` requests to ensure the safety of retrying. There will be a short delay
|
126
|
-
between each retry, with an exponential backoff algorithm used to determine the
|
127
|
-
length of the delay. Default value is 0.
|
128
|
-
|
129
|
-
Example:
|
130
|
-
|
131
|
-
Stripe.max_network_retries = 2
|
132
|
-
|
143
|
+
[connect]: https://stripe.com/connect
|
133
144
|
[curl]: http://curl.haxx.se/docs/caextract.html
|
145
|
+
[faraday]: https://github.com/lostisland/faraday
|
146
|
+
[idempotency-keys]: https://stripe.com/docs/api/ruby#idempotent_requests
|
134
147
|
[dashboard]: https://dashboard.stripe.com/account
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ desc "update bundled certs"
|
|
10
10
|
task :update_certs do
|
11
11
|
require "restclient"
|
12
12
|
File.open(File.join(File.dirname(__FILE__), 'lib', 'data', 'ca-certificates.crt'), 'w') do |file|
|
13
|
-
resp =
|
13
|
+
resp = Faraday.get "https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt"
|
14
14
|
abort("bad response when fetching bundle") unless resp.code == 200
|
15
15
|
file.write(resp.to_str)
|
16
16
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/lib/stripe.rb
CHANGED
@@ -6,7 +6,7 @@ require 'rbconfig'
|
|
6
6
|
require 'set'
|
7
7
|
require 'socket'
|
8
8
|
|
9
|
-
require '
|
9
|
+
require 'faraday'
|
10
10
|
require 'json'
|
11
11
|
|
12
12
|
# Version
|
@@ -22,7 +22,9 @@ require 'stripe/api_operations/request'
|
|
22
22
|
# API resource support classes
|
23
23
|
require 'stripe/errors'
|
24
24
|
require 'stripe/util'
|
25
|
+
require 'stripe/stripe_client'
|
25
26
|
require 'stripe/stripe_object'
|
27
|
+
require 'stripe/stripe_response'
|
26
28
|
require 'stripe/list_object'
|
27
29
|
require 'stripe/api_resource'
|
28
30
|
require 'stripe/singleton_api_resource'
|
@@ -66,35 +68,6 @@ require 'stripe/transfer'
|
|
66
68
|
module Stripe
|
67
69
|
DEFAULT_CA_BUNDLE_PATH = File.dirname(__FILE__) + '/data/ca-certificates.crt'
|
68
70
|
|
69
|
-
# Exceptions which we'd like to retry. This includes both socket errors that
|
70
|
-
# may represent an intermittent problem and some special HTTP statuses.
|
71
|
-
RETRY_EXCEPTIONS = [
|
72
|
-
# Destination refused the connection. This could occur from a single
|
73
|
-
# saturated server, so retry in case it's intermittent.
|
74
|
-
Errno::ECONNREFUSED,
|
75
|
-
|
76
|
-
# Connection reset. This occasionally occurs on a server problem, and
|
77
|
-
# deserves a retry because the server should terminate all requests
|
78
|
-
# properly even if they were invalid.
|
79
|
-
Errno::ECONNRESET,
|
80
|
-
|
81
|
-
# Timed out making the connection. It's worth retrying under this
|
82
|
-
# circumstance.
|
83
|
-
Errno::ETIMEDOUT,
|
84
|
-
|
85
|
-
# A server may respond with a 409 to indicate that there is a concurrent
|
86
|
-
# request executing with the same idempotency key. In the case that a
|
87
|
-
# request failed due to a connection problem and the client has retried too
|
88
|
-
# early, but the server is still executing the old request, we would like
|
89
|
-
# the client to continue retrying until getting a "real" response status
|
90
|
-
# back.
|
91
|
-
RestClient::Conflict,
|
92
|
-
|
93
|
-
# Retry on timeout-related problems. This shouldn't be lumped in with HTTP
|
94
|
-
# exceptions, but with RestClient it is.
|
95
|
-
RestClient::RequestTimeout,
|
96
|
-
].freeze
|
97
|
-
|
98
71
|
@api_base = 'https://api.stripe.com'
|
99
72
|
@connect_base = 'https://connect.stripe.com'
|
100
73
|
@uploads_base = 'https://uploads.stripe.com'
|
@@ -103,7 +76,7 @@ module Stripe
|
|
103
76
|
@max_network_retry_delay = 2
|
104
77
|
@initial_network_retry_delay = 0.5
|
105
78
|
|
106
|
-
@ca_bundle_path
|
79
|
+
@ca_bundle_path = DEFAULT_CA_BUNDLE_PATH
|
107
80
|
@ca_store = nil
|
108
81
|
@verify_ssl_certs = true
|
109
82
|
|
@@ -117,10 +90,6 @@ module Stripe
|
|
117
90
|
attr_reader :max_network_retry_delay, :initial_network_retry_delay
|
118
91
|
end
|
119
92
|
|
120
|
-
def self.api_url(url='', api_base_url=nil)
|
121
|
-
(api_base_url || @api_base) + url
|
122
|
-
end
|
123
|
-
|
124
93
|
# The location of a file containing a bundle of CA certificates. By default
|
125
94
|
# the library will use an included bundle that can successfully validate
|
126
95
|
# Stripe certificates.
|
@@ -152,62 +121,6 @@ module Stripe
|
|
152
121
|
end
|
153
122
|
end
|
154
123
|
|
155
|
-
def self.request(method, url, api_key, params={}, headers={}, api_base_url=nil)
|
156
|
-
api_base_url = api_base_url || @api_base
|
157
|
-
|
158
|
-
unless api_key ||= @api_key
|
159
|
-
raise AuthenticationError.new('No API key provided. ' \
|
160
|
-
'Set your API key using "Stripe.api_key = <API-KEY>". ' \
|
161
|
-
'You can generate API keys from the Stripe web interface. ' \
|
162
|
-
'See https://stripe.com/api for details, or email support@stripe.com ' \
|
163
|
-
'if you have any questions.')
|
164
|
-
end
|
165
|
-
|
166
|
-
if api_key =~ /\s/
|
167
|
-
raise AuthenticationError.new('Your API key is invalid, as it contains ' \
|
168
|
-
'whitespace. (HINT: You can double-check your API key from the ' \
|
169
|
-
'Stripe web interface. See https://stripe.com/api for details, or ' \
|
170
|
-
'email support@stripe.com if you have any questions.)')
|
171
|
-
end
|
172
|
-
|
173
|
-
if verify_ssl_certs
|
174
|
-
request_opts = {:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
175
|
-
:ssl_cert_store => ca_store}
|
176
|
-
else
|
177
|
-
request_opts = {:verify_ssl => false}
|
178
|
-
unless @verify_ssl_warned
|
179
|
-
@verify_ssl_warned = true
|
180
|
-
$stderr.puts("WARNING: Running without SSL cert verification. " \
|
181
|
-
"You should never do this in production. " \
|
182
|
-
"Execute 'Stripe.verify_ssl_certs = true' to enable verification.")
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
params = Util.objects_to_ids(params)
|
187
|
-
url = api_url(url, api_base_url)
|
188
|
-
|
189
|
-
case method.to_s.downcase.to_sym
|
190
|
-
when :get, :head, :delete
|
191
|
-
# Make params into GET parameters
|
192
|
-
url += "#{URI.parse(url).query ? '&' : '?'}#{Util.encode_parameters(params)}" if params && params.any?
|
193
|
-
payload = nil
|
194
|
-
else
|
195
|
-
if headers[:content_type] && headers[:content_type] == "multipart/form-data"
|
196
|
-
payload = params
|
197
|
-
else
|
198
|
-
payload = Util.encode_parameters(params)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
request_opts.update(:headers => request_headers(api_key, method).update(headers),
|
203
|
-
:method => method, :open_timeout => open_timeout,
|
204
|
-
:payload => payload, :url => url, :timeout => read_timeout)
|
205
|
-
|
206
|
-
response = execute_request_with_rescues(request_opts, api_base_url)
|
207
|
-
|
208
|
-
[parse(response), api_key]
|
209
|
-
end
|
210
|
-
|
211
124
|
def self.max_network_retries
|
212
125
|
@max_network_retries
|
213
126
|
end
|
@@ -218,242 +131,6 @@ module Stripe
|
|
218
131
|
|
219
132
|
private
|
220
133
|
|
221
|
-
def self.api_error(error, resp, error_obj)
|
222
|
-
APIError.new(error[:message], resp.code, resp.body, error_obj, resp.headers)
|
223
|
-
end
|
224
|
-
|
225
|
-
def self.authentication_error(error, resp, error_obj)
|
226
|
-
AuthenticationError.new(error[:message], resp.code, resp.body, error_obj,
|
227
|
-
resp.headers)
|
228
|
-
end
|
229
|
-
|
230
|
-
def self.card_error(error, resp, error_obj)
|
231
|
-
CardError.new(error[:message], error[:param], error[:code],
|
232
|
-
resp.code, resp.body, error_obj, resp.headers)
|
233
|
-
end
|
234
|
-
|
235
|
-
def self.execute_request(opts)
|
236
|
-
RestClient::Request.execute(opts)
|
237
|
-
end
|
238
|
-
|
239
|
-
def self.execute_request_with_rescues(request_opts, api_base_url, retry_count = 0)
|
240
|
-
begin
|
241
|
-
response = execute_request(request_opts)
|
242
|
-
|
243
|
-
# We rescue all exceptions from a request so that we have an easy spot to
|
244
|
-
# implement our retry logic across the board. We'll re-raise if it's a type
|
245
|
-
# of exception that we didn't expect to handle.
|
246
|
-
rescue => e
|
247
|
-
if should_retry?(e, retry_count)
|
248
|
-
retry_count = retry_count + 1
|
249
|
-
sleep sleep_time(retry_count)
|
250
|
-
retry
|
251
|
-
end
|
252
|
-
|
253
|
-
case e
|
254
|
-
when SocketError
|
255
|
-
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
256
|
-
|
257
|
-
when RestClient::ExceptionWithResponse
|
258
|
-
if e.response
|
259
|
-
handle_api_error(e.response)
|
260
|
-
else
|
261
|
-
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
262
|
-
end
|
263
|
-
|
264
|
-
when RestClient::Exception, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError
|
265
|
-
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
266
|
-
|
267
|
-
# Only handle errors when we know we can do so, and re-raise otherwise.
|
268
|
-
# This should be pretty infrequent.
|
269
|
-
else
|
270
|
-
raise
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
response
|
275
|
-
end
|
276
|
-
|
277
|
-
def self.general_api_error(rcode, rbody)
|
278
|
-
APIError.new("Invalid response object from API: #{rbody.inspect} " +
|
279
|
-
"(HTTP response code was #{rcode})", rcode, rbody)
|
280
|
-
end
|
281
|
-
|
282
|
-
def self.get_uname
|
283
|
-
if File.exist?('/proc/version')
|
284
|
-
File.read('/proc/version').strip
|
285
|
-
else
|
286
|
-
case RbConfig::CONFIG['host_os']
|
287
|
-
when /linux|darwin|bsd|sunos|solaris|cygwin/i
|
288
|
-
get_uname_from_system
|
289
|
-
when /mswin|mingw/i
|
290
|
-
get_uname_from_system_ver
|
291
|
-
else
|
292
|
-
"unknown platform"
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
def self.get_uname_from_system
|
298
|
-
(`uname -a 2>/dev/null` || '').strip
|
299
|
-
rescue Errno::ENOENT
|
300
|
-
"uname executable not found"
|
301
|
-
rescue Errno::ENOMEM # couldn't create subprocess
|
302
|
-
"uname lookup failed"
|
303
|
-
end
|
304
|
-
|
305
|
-
def self.get_uname_from_system_ver
|
306
|
-
(`ver` || '').strip
|
307
|
-
rescue Errno::ENOENT
|
308
|
-
"ver executable not found"
|
309
|
-
rescue Errno::ENOMEM # couldn't create subprocess
|
310
|
-
"uname lookup failed"
|
311
|
-
end
|
312
|
-
|
313
|
-
def self.handle_api_error(resp)
|
314
|
-
begin
|
315
|
-
error_obj = JSON.parse(resp.body)
|
316
|
-
error_obj = Util.symbolize_names(error_obj)
|
317
|
-
error = error_obj[:error]
|
318
|
-
raise StripeError.new unless error && error.is_a?(Hash)
|
319
|
-
|
320
|
-
rescue JSON::ParserError, StripeError
|
321
|
-
raise general_api_error(resp.code, resp.body)
|
322
|
-
end
|
323
|
-
|
324
|
-
case resp.code
|
325
|
-
when 400, 404
|
326
|
-
raise invalid_request_error(error, resp, error_obj)
|
327
|
-
when 401
|
328
|
-
raise authentication_error(error, resp, error_obj)
|
329
|
-
when 402
|
330
|
-
raise card_error(error, resp, error_obj)
|
331
|
-
when 403
|
332
|
-
raise permission_error(error, resp, error_obj)
|
333
|
-
when 429
|
334
|
-
raise rate_limit_error(error, resp, error_obj)
|
335
|
-
else
|
336
|
-
raise api_error(error, resp, error_obj)
|
337
|
-
end
|
338
|
-
|
339
|
-
end
|
340
|
-
|
341
|
-
def self.handle_restclient_error(e, request_opts, retry_count, api_base_url=nil)
|
342
|
-
|
343
|
-
api_base_url = @api_base unless api_base_url
|
344
|
-
connection_message = "Please check your internet connection and try again. " \
|
345
|
-
"If this problem persists, you should check Stripe's service status at " \
|
346
|
-
"https://twitter.com/stripestatus, or let us know at support@stripe.com."
|
347
|
-
|
348
|
-
case e
|
349
|
-
when RestClient::RequestTimeout
|
350
|
-
message = "Could not connect to Stripe (#{api_base_url}). #{connection_message}"
|
351
|
-
|
352
|
-
when RestClient::ServerBrokeConnection
|
353
|
-
message = "The connection to the server (#{api_base_url}) broke before the " \
|
354
|
-
"request completed. #{connection_message}"
|
355
|
-
|
356
|
-
when OpenSSL::SSL::SSLError
|
357
|
-
message = "Could not establish a secure connection to Stripe, you may " \
|
358
|
-
"need to upgrade your OpenSSL version. To check, try running " \
|
359
|
-
"'openssl s_client -connect api.stripe.com:443' from the " \
|
360
|
-
"command line."
|
361
|
-
|
362
|
-
when RestClient::SSLCertificateNotVerified
|
363
|
-
message = "Could not verify Stripe's SSL certificate. " \
|
364
|
-
"Please make sure that your network is not intercepting certificates. " \
|
365
|
-
"(Try going to https://api.stripe.com/v1 in your browser.) " \
|
366
|
-
"If this problem persists, let us know at support@stripe.com."
|
367
|
-
|
368
|
-
when SocketError
|
369
|
-
message = "Unexpected error communicating when trying to connect to Stripe. " \
|
370
|
-
"You may be seeing this message because your DNS is not working. " \
|
371
|
-
"To check, try running 'host stripe.com' from the command line."
|
372
|
-
|
373
|
-
else
|
374
|
-
message = "Unexpected error communicating with Stripe. " \
|
375
|
-
"If this problem persists, let us know at support@stripe.com."
|
376
|
-
|
377
|
-
end
|
378
|
-
|
379
|
-
if retry_count > 0
|
380
|
-
message += " Request was retried #{retry_count} times."
|
381
|
-
end
|
382
|
-
|
383
|
-
raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
|
384
|
-
end
|
385
|
-
|
386
|
-
def self.invalid_request_error(error, resp, error_obj)
|
387
|
-
InvalidRequestError.new(error[:message], error[:param], resp.code,
|
388
|
-
resp.body, error_obj, resp.headers)
|
389
|
-
end
|
390
|
-
|
391
|
-
def self.parse(response)
|
392
|
-
begin
|
393
|
-
# Would use :symbolize_names => true, but apparently there is
|
394
|
-
# some library out there that makes symbolize_names not work.
|
395
|
-
response = JSON.parse(response.body)
|
396
|
-
rescue JSON::ParserError
|
397
|
-
raise general_api_error(response.code, response.body)
|
398
|
-
end
|
399
|
-
|
400
|
-
Util.symbolize_names(response)
|
401
|
-
end
|
402
|
-
|
403
|
-
def self.permission_error(error, resp, error_obj)
|
404
|
-
PermissionError.new(error[:message], resp.code, resp.body, error_obj, resp.headers)
|
405
|
-
end
|
406
|
-
|
407
|
-
def self.rate_limit_error(error, resp, error_obj)
|
408
|
-
RateLimitError.new(error[:message], resp.code, resp.body, error_obj,
|
409
|
-
resp.headers)
|
410
|
-
end
|
411
|
-
|
412
|
-
def self.request_headers(api_key, method)
|
413
|
-
headers = {
|
414
|
-
'User-Agent' => "Stripe/v1 RubyBindings/#{Stripe::VERSION}",
|
415
|
-
'Authorization' => "Bearer #{api_key}",
|
416
|
-
'Content-Type' => 'application/x-www-form-urlencoded'
|
417
|
-
}
|
418
|
-
|
419
|
-
# It is only safe to retry network failures on post and delete
|
420
|
-
# requests if we add an Idempotency-Key header
|
421
|
-
if [:post, :delete].include?(method) && self.max_network_retries > 0
|
422
|
-
headers['Idempotency-Key'] ||= SecureRandom.uuid
|
423
|
-
end
|
424
|
-
|
425
|
-
headers['Stripe-Version'] = api_version if api_version
|
426
|
-
headers['Stripe-Account'] = stripe_account if stripe_account
|
427
|
-
|
428
|
-
begin
|
429
|
-
headers.update('X-Stripe-Client-User-Agent' => JSON.generate(user_agent))
|
430
|
-
rescue => e
|
431
|
-
headers.update('X-Stripe-Client-Raw-User-Agent' => user_agent.inspect,
|
432
|
-
:error => "#{e} (#{e.class})")
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
def self.should_retry?(e, retry_count)
|
437
|
-
retry_count < self.max_network_retries &&
|
438
|
-
RETRY_EXCEPTIONS.any? { |klass| e.is_a?(klass) }
|
439
|
-
end
|
440
|
-
|
441
|
-
def self.sleep_time(retry_count)
|
442
|
-
# Apply exponential backoff with initial_network_retry_delay on the number
|
443
|
-
# of attempts so far as inputs. Do not allow the number to exceed
|
444
|
-
# max_network_retry_delay.
|
445
|
-
sleep_seconds = [initial_network_retry_delay * (2 ** (retry_count - 1)), max_network_retry_delay].min
|
446
|
-
|
447
|
-
# Apply some jitter by randomizing the value in the range of (sleep_seconds
|
448
|
-
# / 2) to (sleep_seconds).
|
449
|
-
sleep_seconds = sleep_seconds * (0.5 * (1 + rand()))
|
450
|
-
|
451
|
-
# But never sleep less than the base sleep seconds.
|
452
|
-
sleep_seconds = [initial_network_retry_delay, sleep_seconds].max
|
453
|
-
|
454
|
-
sleep_seconds
|
455
|
-
end
|
456
|
-
|
457
134
|
# DEPRECATED. Use `Util#encode_parameters` instead.
|
458
135
|
def self.uri_encode(params)
|
459
136
|
Util.encode_parameters(params)
|
@@ -462,21 +139,4 @@ module Stripe
|
|
462
139
|
extend Gem::Deprecate
|
463
140
|
deprecate :uri_encode, "Stripe::Util#encode_parameters", 2016, 01
|
464
141
|
end
|
465
|
-
|
466
|
-
def self.user_agent
|
467
|
-
@uname ||= get_uname
|
468
|
-
lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
469
|
-
|
470
|
-
{
|
471
|
-
:bindings_version => Stripe::VERSION,
|
472
|
-
:lang => 'ruby',
|
473
|
-
:lang_version => lang_version,
|
474
|
-
:platform => RUBY_PLATFORM,
|
475
|
-
:engine => defined?(RUBY_ENGINE) ? RUBY_ENGINE : '',
|
476
|
-
:publisher => 'stripe',
|
477
|
-
:uname => @uname,
|
478
|
-
:hostname => Socket.gethostname,
|
479
|
-
}
|
480
|
-
|
481
|
-
end
|
482
142
|
end
|