stripe 5.4.0 → 5.7.1
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/.rubocop.yml +6 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +0 -1
- data/VERSION +1 -1
- data/lib/stripe.rb +2 -2
- data/lib/stripe/api_operations/list.rb +0 -5
- data/lib/stripe/api_operations/request.rb +17 -1
- data/lib/stripe/list_object.rb +30 -2
- data/lib/stripe/stripe_client.rb +18 -14
- data/lib/stripe/util.rb +2 -3
- data/lib/stripe/version.rb +1 -1
- data/test/stripe/api_resource_test.rb +17 -0
- data/test/stripe/list_object_test.rb +69 -7
- data/test/stripe/stripe_client_test.rb +25 -5
- data/test/test_helper.rb +0 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc4c445567a38782dc843a338247615185c7f7f37a41e7fc7112ae09a9b80863
|
4
|
+
data.tar.gz: 3feccf9203d4c39fcb2abb6ceee3cae6e501d2194a91117d6802fb2ecf151f2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb4acdf7e1d6c198f93b383fa6963a1222fcfc40fc3893ce005978e350a48995a2cd8c2507ac957284406a36eaeaa018db5b29d53092269b5dba1302dddfcc7f
|
7
|
+
data.tar.gz: 56f2cb939da176b60462370323bd5aff987b6d7ab2d12965833843d3fd8ad81bf9f1cd9f4ae65ebda1340a6c9eeba1a634d77ccaeff41e437abf3660c081dcb5
|
data/.rubocop.yml
CHANGED
@@ -4,6 +4,12 @@ AllCops:
|
|
4
4
|
DisplayCopNames: true
|
5
5
|
TargetRubyVersion: 2.3
|
6
6
|
|
7
|
+
Exclude:
|
8
|
+
# brandur: Exclude ephmeral script-like files that I use to try and
|
9
|
+
# reproduce problems with the library. If you know of a better way of doing
|
10
|
+
# this (e.g. exclude files not tracked by Git), feel free to change it.
|
11
|
+
- "example_*"
|
12
|
+
|
7
13
|
Layout/CaseIndentation:
|
8
14
|
EnforcedStyle: end
|
9
15
|
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 5.7.1 - 2019-10-15
|
4
|
+
* [#869](https://github.com/stripe/stripe-ruby/pull/869) Fixes the misnamed `connection_base=` setter to be named `connect_base=`
|
5
|
+
|
6
|
+
## 5.7.0 - 2019-10-10
|
7
|
+
* [#865](https://github.com/stripe/stripe-ruby/pull/865) Support backwards pagination with list's `#auto_paging_each`
|
8
|
+
|
9
|
+
## 5.6.0 - 2019-10-04
|
10
|
+
* [#861](https://github.com/stripe/stripe-ruby/pull/861) Nicer error when specifying non-nil non-string opt value
|
11
|
+
|
12
|
+
## 5.5.0 - 2019-10-03
|
13
|
+
* [#859](https://github.com/stripe/stripe-ruby/pull/859) User-friendly messages and retries for `EOFError`, `Errno::ECONNRESET`, `Errno::ETIMEDOUT`, and `Errno::EHOSTUNREACH` network errors
|
14
|
+
|
15
|
+
## 5.4.1 - 2019-10-01
|
16
|
+
* [#858](https://github.com/stripe/stripe-ruby/pull/858) Drop Timecop dependency
|
17
|
+
|
3
18
|
## 5.4.0 - 2019-10-01
|
4
19
|
* [#857](https://github.com/stripe/stripe-ruby/pull/857) Move to monotonic time for duration calculations
|
5
20
|
|
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.7.1
|
data/lib/stripe.rb
CHANGED
@@ -139,8 +139,8 @@ module Stripe
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
-
def self.
|
143
|
-
@
|
142
|
+
def self.connect_base=(connect_base)
|
143
|
+
@connect_base = connect_base
|
144
144
|
StripeClient.clear_all_connection_managers
|
145
145
|
end
|
146
146
|
|
@@ -11,12 +11,7 @@ module Stripe
|
|
11
11
|
|
12
12
|
# set filters so that we can fetch the same limit, expansions, and
|
13
13
|
# predicates when accessing the next and previous pages
|
14
|
-
#
|
15
|
-
# just for general cleanliness, remove any paging options
|
16
14
|
obj.filters = filters.dup
|
17
|
-
obj.filters.delete(:ending_before)
|
18
|
-
obj.filters.delete(:starting_after)
|
19
|
-
|
20
15
|
obj
|
21
16
|
end
|
22
17
|
end
|
@@ -8,6 +8,8 @@ module Stripe
|
|
8
8
|
warn_on_opts_in_params(params)
|
9
9
|
|
10
10
|
opts = Util.normalize_opts(opts)
|
11
|
+
error_on_non_string_user_opts(opts)
|
12
|
+
|
11
13
|
opts[:client] ||= StripeClient.active_client
|
12
14
|
|
13
15
|
headers = opts.clone
|
@@ -31,10 +33,24 @@ module Stripe
|
|
31
33
|
[resp, opts_to_persist]
|
32
34
|
end
|
33
35
|
|
36
|
+
private def error_on_non_string_user_opts(opts)
|
37
|
+
Util::OPTS_USER_SPECIFIED.each do |opt|
|
38
|
+
next unless opts.key?(opt)
|
39
|
+
|
40
|
+
val = opts[opt]
|
41
|
+
next if val.nil?
|
42
|
+
next if val.is_a?(String)
|
43
|
+
|
44
|
+
raise ArgumentError,
|
45
|
+
"request option '#{opt}' should be a string value " \
|
46
|
+
"(was a #{val.class})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
34
50
|
private def warn_on_opts_in_params(params)
|
35
51
|
Util::OPTS_USER_SPECIFIED.each do |opt|
|
36
52
|
if params.key?(opt)
|
37
|
-
warn("WARNING: #{opt} should be in opts instead of params.")
|
53
|
+
warn("WARNING: '#{opt}' should be in opts instead of params.")
|
38
54
|
end
|
39
55
|
end
|
40
56
|
end
|
data/lib/stripe/list_object.rb
CHANGED
@@ -51,6 +51,16 @@ module Stripe
|
|
51
51
|
# Iterates through each resource in all pages, making additional fetches to
|
52
52
|
# the API as necessary.
|
53
53
|
#
|
54
|
+
# The default iteration direction is forwards according to Stripe's API
|
55
|
+
# "natural" ordering direction -- newer objects first, and moving towards
|
56
|
+
# older objects.
|
57
|
+
#
|
58
|
+
# However, if the initial list object was fetched using an `ending_before`
|
59
|
+
# cursor (and only `ending_before`, `starting_after` cannot also be
|
60
|
+
# included), the method assumes that the user is trying to iterate
|
61
|
+
# backwards compared to natural ordering and returns results that way --
|
62
|
+
# older objects first, and moving towards newer objects.
|
63
|
+
#
|
54
64
|
# Note that this method will make as many API calls as necessary to fetch
|
55
65
|
# all resources. For more granular control, please see +each+ and
|
56
66
|
# +next_page+.
|
@@ -59,8 +69,18 @@ module Stripe
|
|
59
69
|
|
60
70
|
page = self
|
61
71
|
loop do
|
62
|
-
|
63
|
-
|
72
|
+
# Backward iterating activates if we have an `ending_before` constraint
|
73
|
+
# and _just_ an `ending_before` constraint. If `starting_after` was
|
74
|
+
# also used, we iterate forwards normally.
|
75
|
+
if filters.include?(:ending_before) &&
|
76
|
+
!filters.include?(:starting_after)
|
77
|
+
page.reverse_each(&blk)
|
78
|
+
page = page.previous_page
|
79
|
+
else
|
80
|
+
page.each(&blk)
|
81
|
+
page = page.next_page
|
82
|
+
end
|
83
|
+
|
64
84
|
break if page.empty?
|
65
85
|
end
|
66
86
|
end
|
@@ -96,6 +116,8 @@ module Stripe
|
|
96
116
|
# This method will try to respect the limit of the current page. If none
|
97
117
|
# was given, the default limit will be fetched again.
|
98
118
|
def previous_page(params = {}, opts = {})
|
119
|
+
return self.class.empty_list(opts) unless has_more
|
120
|
+
|
99
121
|
first_id = data.first.id
|
100
122
|
|
101
123
|
params = filters.merge(ending_before: first_id).merge(params)
|
@@ -107,5 +129,11 @@ module Stripe
|
|
107
129
|
url ||
|
108
130
|
raise(ArgumentError, "List object does not contain a 'url' field.")
|
109
131
|
end
|
132
|
+
|
133
|
+
# Iterates through each resource in the page represented by the current
|
134
|
+
# `ListObject` in reverse.
|
135
|
+
def reverse_each(&blk)
|
136
|
+
data.reverse_each(&blk)
|
137
|
+
end
|
110
138
|
end
|
111
139
|
end
|
data/lib/stripe/stripe_client.rb
CHANGED
@@ -81,17 +81,17 @@ module Stripe
|
|
81
81
|
def self.should_retry?(error, method:, num_retries:)
|
82
82
|
return false if num_retries >= Stripe.max_network_retries
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
84
|
+
case error
|
85
|
+
when Net::OpenTimeout, Net::ReadTimeout
|
86
|
+
# Retry on timeout-related problems (either on open or read).
|
87
|
+
true
|
88
|
+
when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET,
|
89
|
+
Errno::EHOSTUNREACH, Errno::ETIMEDOUT, SocketError
|
90
|
+
# Destination refused the connection, the connection was reset, or a
|
91
|
+
# variety of other connection failures. This could occur from a single
|
92
|
+
# saturated server, so retry in case it's intermittent.
|
93
|
+
true
|
94
|
+
when Stripe::StripeError
|
95
95
|
# The API may ask us not to retry (e.g. if doing so would be a no-op),
|
96
96
|
# or advise us to retry (e.g. in cases of lock timeouts). Defer to
|
97
97
|
# those instructions if given.
|
@@ -119,10 +119,10 @@ module Stripe
|
|
119
119
|
return true if error.http_status == 500 && method != :post
|
120
120
|
|
121
121
|
# 503 Service Unavailable
|
122
|
-
|
122
|
+
error.http_status == 503
|
123
|
+
else
|
124
|
+
false
|
123
125
|
end
|
124
|
-
|
125
|
-
false
|
126
126
|
end
|
127
127
|
|
128
128
|
def self.sleep_time(num_retries)
|
@@ -296,7 +296,11 @@ module Stripe
|
|
296
296
|
# The original error message is also appended onto the final exception for
|
297
297
|
# full transparency.
|
298
298
|
NETWORK_ERROR_MESSAGES_MAP = {
|
299
|
+
EOFError => ERROR_MESSAGE_CONNECTION,
|
299
300
|
Errno::ECONNREFUSED => ERROR_MESSAGE_CONNECTION,
|
301
|
+
Errno::ECONNRESET => ERROR_MESSAGE_CONNECTION,
|
302
|
+
Errno::EHOSTUNREACH => ERROR_MESSAGE_CONNECTION,
|
303
|
+
Errno::ETIMEDOUT => ERROR_MESSAGE_TIMEOUT_CONNECT,
|
300
304
|
SocketError => ERROR_MESSAGE_CONNECTION,
|
301
305
|
|
302
306
|
Net::OpenTimeout => ERROR_MESSAGE_TIMEOUT_CONNECT,
|
data/lib/stripe/util.rb
CHANGED
@@ -178,9 +178,8 @@ module Stripe
|
|
178
178
|
# to calculate an elapsed duration.
|
179
179
|
#
|
180
180
|
# Shortcut for getting monotonic time, mostly for purposes of line length
|
181
|
-
# and stubbing
|
182
|
-
#
|
183
|
-
# platform (e.g. system boot time).
|
181
|
+
# and test stubbing. Returns time in seconds since the event used for
|
182
|
+
# monotonic reference purposes by the platform (e.g. system boot time).
|
184
183
|
def self.monotonic_time
|
185
184
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
186
185
|
end
|
data/lib/stripe/version.rb
CHANGED
@@ -227,6 +227,23 @@ module Stripe
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
|
+
should "error if a user-specified opt is given a non-nil non-string value" do
|
231
|
+
stub_request(:post, "#{Stripe.api_base}/v1/charges")
|
232
|
+
.to_return(body: JSON.generate(charge_fixture))
|
233
|
+
|
234
|
+
# Works fine if not included or a string.
|
235
|
+
Stripe::Charge.create({ amount: 100, currency: "usd" }, {})
|
236
|
+
Stripe::Charge.create({ amount: 100, currency: "usd" }, idempotency_key: "12345")
|
237
|
+
|
238
|
+
# Errors on a non-string.
|
239
|
+
e = assert_raises(ArgumentError) do
|
240
|
+
Stripe::Charge.create({ amount: 100, currency: "usd" }, idempotency_key: :foo)
|
241
|
+
end
|
242
|
+
assert_equal "request option 'idempotency_key' should be a string value " \
|
243
|
+
"(was a Symbol)",
|
244
|
+
e.message
|
245
|
+
end
|
246
|
+
|
230
247
|
should "requesting with a unicode ID should result in a request" do
|
231
248
|
stub_request(:get, "#{Stripe.api_base}/v1/customers/%E2%98%83")
|
232
249
|
.to_return(body: JSON.generate(make_missing_id_error), status: 404)
|
@@ -25,20 +25,80 @@ module Stripe
|
|
25
25
|
assert_equal expected, list.each.to_a
|
26
26
|
end
|
27
27
|
|
28
|
-
should "provide #
|
28
|
+
should "provide #reverse_each" do
|
29
29
|
arr = [
|
30
30
|
{ id: 1 },
|
31
31
|
{ id: 2 },
|
32
32
|
{ id: 3 },
|
33
33
|
]
|
34
|
+
expected = Util.convert_to_stripe_object(arr.reverse, {})
|
35
|
+
list = Stripe::ListObject.construct_from(data: arr)
|
36
|
+
assert_equal expected, list.reverse_each.to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
should "provide #auto_paging_each that supports forward pagination" do
|
40
|
+
arr = [
|
41
|
+
{ id: 1 },
|
42
|
+
{ id: 2 },
|
43
|
+
{ id: 3 },
|
44
|
+
{ id: 4 },
|
45
|
+
{ id: 5 },
|
46
|
+
{ id: 6 },
|
47
|
+
]
|
34
48
|
expected = Util.convert_to_stripe_object(arr, {})
|
35
49
|
|
50
|
+
# Initial list object to page on. Notably, its last data element will be
|
51
|
+
# used as a cursor to fetch the next page.
|
36
52
|
list = TestListObject.construct_from(data: [{ id: 1 }],
|
37
53
|
has_more: true,
|
38
54
|
url: "/things")
|
55
|
+
list.filters = { limit: 3 }
|
56
|
+
|
57
|
+
# The test will start with the synthetic list object above, and use it as
|
58
|
+
# a starting point to fetch two more pages. The second page indicates
|
59
|
+
# that there are no more elements by setting `has_more` to `false`, and
|
60
|
+
# iteration stops.
|
39
61
|
stub_request(:get, "#{Stripe.api_base}/things")
|
40
|
-
.with(query: { starting_after: "1" })
|
41
|
-
.to_return(body: JSON.generate(data: [{ id: 2 }, { id: 3 }], has_more:
|
62
|
+
.with(query: { starting_after: "1", limit: "3" })
|
63
|
+
.to_return(body: JSON.generate(data: [{ id: 2 }, { id: 3 }, { id: 4 }], has_more: true, url: "/things"))
|
64
|
+
stub_request(:get, "#{Stripe.api_base}/things")
|
65
|
+
.with(query: { starting_after: "4", limit: "3" })
|
66
|
+
.to_return(body: JSON.generate(data: [{ id: 5 }, { id: 6 }], has_more: false, url: "/things"))
|
67
|
+
|
68
|
+
assert_equal expected, list.auto_paging_each.to_a
|
69
|
+
end
|
70
|
+
|
71
|
+
should "provide #auto_paging_each that supports backward pagination with `ending_before`" do
|
72
|
+
arr = [
|
73
|
+
{ id: 6 },
|
74
|
+
{ id: 5 },
|
75
|
+
{ id: 4 },
|
76
|
+
{ id: 3 },
|
77
|
+
{ id: 2 },
|
78
|
+
{ id: 1 },
|
79
|
+
]
|
80
|
+
expected = Util.convert_to_stripe_object(arr, {})
|
81
|
+
|
82
|
+
# Initial list object to page on. Notably, its first data element will be
|
83
|
+
# used as a cursor to fetch the next page.
|
84
|
+
list = TestListObject.construct_from(data: [{ id: 6 }],
|
85
|
+
has_more: true,
|
86
|
+
url: "/things")
|
87
|
+
|
88
|
+
# We also add an `ending_before` filter on the list to simulate backwards
|
89
|
+
# pagination.
|
90
|
+
list.filters = { ending_before: 7, limit: 3 }
|
91
|
+
|
92
|
+
# The test will start with the synthetic list object above, and use it as
|
93
|
+
# a starting point to fetch two more pages. The second page indicates
|
94
|
+
# that there are no more elements by setting `has_more` to `false`, and
|
95
|
+
# iteration stops.
|
96
|
+
stub_request(:get, "#{Stripe.api_base}/things")
|
97
|
+
.with(query: { ending_before: "6", limit: "3" })
|
98
|
+
.to_return(body: JSON.generate(data: [{ id: 3 }, { id: 4 }, { id: 5 }], has_more: true, url: "/things"))
|
99
|
+
stub_request(:get, "#{Stripe.api_base}/things")
|
100
|
+
.with(query: { ending_before: "3", limit: "3" })
|
101
|
+
.to_return(body: JSON.generate(data: [{ id: 1 }, { id: 2 }], has_more: false, url: "/things"))
|
42
102
|
|
43
103
|
assert_equal expected, list.auto_paging_each.to_a
|
44
104
|
end
|
@@ -97,7 +157,7 @@ module Stripe
|
|
97
157
|
.with(query: { "expand[]" => "data.source", "limit" => "3", "starting_after" => "1" })
|
98
158
|
.to_return(body: JSON.generate(data: [{ id: 2 }], has_more: false))
|
99
159
|
next_list = list.next_page
|
100
|
-
assert_equal({ expand: ["data.source"], limit: 3 }, next_list.filters)
|
160
|
+
assert_equal({ expand: ["data.source"], limit: 3, starting_after: 1 }, next_list.filters)
|
101
161
|
end
|
102
162
|
|
103
163
|
should "fetch an empty page through #next_page" do
|
@@ -114,23 +174,25 @@ module Stripe
|
|
114
174
|
|
115
175
|
should "fetch a next page through #previous_page" do
|
116
176
|
list = TestListObject.construct_from(data: [{ id: 2 }],
|
177
|
+
has_more: true,
|
117
178
|
url: "/things")
|
118
179
|
stub_request(:get, "#{Stripe.api_base}/things")
|
119
180
|
.with(query: { ending_before: "2" })
|
120
|
-
.to_return(body: JSON.generate(data: [{ id: 1 }]))
|
181
|
+
.to_return(body: JSON.generate(data: [{ id: 1 }], has_more: false))
|
121
182
|
next_list = list.previous_page
|
122
183
|
refute next_list.empty?
|
123
184
|
end
|
124
185
|
|
125
186
|
should "fetch a next page through #previous_page and respect limit" do
|
126
187
|
list = TestListObject.construct_from(data: [{ id: 2 }],
|
188
|
+
has_more: true,
|
127
189
|
url: "/things")
|
128
190
|
list.filters = { expand: ["data.source"], limit: 3 }
|
129
191
|
stub_request(:get, "#{Stripe.api_base}/things")
|
130
192
|
.with(query: { "expand[]" => "data.source", "limit" => "3", "ending_before" => "2" })
|
131
|
-
.to_return(body: JSON.generate(data: [{ id: 1 }]))
|
193
|
+
.to_return(body: JSON.generate(data: [{ id: 1 }], has_more: false))
|
132
194
|
next_list = list.previous_page
|
133
|
-
assert_equal({ expand: ["data.source"], limit: 3 }, next_list.filters)
|
195
|
+
assert_equal({ ending_before: 2, expand: ["data.source"], limit: 3 }, next_list.filters)
|
134
196
|
end
|
135
197
|
end
|
136
198
|
end
|
@@ -172,6 +172,26 @@ module Stripe
|
|
172
172
|
method: :post, num_retries: 0)
|
173
173
|
end
|
174
174
|
|
175
|
+
should "retry on EOFError" do
|
176
|
+
assert StripeClient.should_retry?(EOFError.new,
|
177
|
+
method: :post, num_retries: 0)
|
178
|
+
end
|
179
|
+
|
180
|
+
should "retry on Errno::ECONNRESET" do
|
181
|
+
assert StripeClient.should_retry?(Errno::ECONNRESET.new,
|
182
|
+
method: :post, num_retries: 0)
|
183
|
+
end
|
184
|
+
|
185
|
+
should "retry on Errno::ETIMEDOUT" do
|
186
|
+
assert StripeClient.should_retry?(Errno::ETIMEDOUT.new,
|
187
|
+
method: :post, num_retries: 0)
|
188
|
+
end
|
189
|
+
|
190
|
+
should "retry on Errno::EHOSTUNREACH" do
|
191
|
+
assert StripeClient.should_retry?(Errno::EHOSTUNREACH.new,
|
192
|
+
method: :post, num_retries: 0)
|
193
|
+
end
|
194
|
+
|
175
195
|
should "retry on Net::OpenTimeout" do
|
176
196
|
assert StripeClient.should_retry?(Net::OpenTimeout.new,
|
177
197
|
method: :post, num_retries: 0)
|
@@ -316,11 +336,11 @@ module Stripe
|
|
316
336
|
|
317
337
|
context "logging" do
|
318
338
|
setup do
|
319
|
-
# Freeze time for the purposes of the `elapsed` parameter that we
|
320
|
-
# for responses. Mocha's `anything` parameter can't match inside
|
321
|
-
# hash and is therefore not useful for this purpose
|
322
|
-
#
|
323
|
-
#
|
339
|
+
# Freeze time for the purposes of the `elapsed` parameter that we
|
340
|
+
# emit for responses. Mocha's `anything` parameter can't match inside
|
341
|
+
# of a hash and is therefore not useful for this purpose. If we
|
342
|
+
# switch over to rspec-mocks at some point, we can probably remove
|
343
|
+
# this.
|
324
344
|
Util.stubs(:monotonic_time).returns(0.0)
|
325
345
|
end
|
326
346
|
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stripe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stripe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Stripe is the easiest way to accept payments online. See https://stripe.com
|
14
14
|
for details.
|
@@ -246,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
246
246
|
- !ruby/object:Gem::Version
|
247
247
|
version: '0'
|
248
248
|
requirements: []
|
249
|
-
rubygems_version: 3.0.
|
249
|
+
rubygems_version: 3.0.6
|
250
250
|
signing_key:
|
251
251
|
specification_version: 4
|
252
252
|
summary: Ruby bindings for the Stripe API
|