stripe 3.3.1 → 5.38.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +962 -0
  3. data/CODE_OF_CONDUCT.md +77 -0
  4. data/Gemfile +24 -22
  5. data/History.txt +1 -689
  6. data/README.md +202 -55
  7. data/Rakefile +18 -12
  8. data/VERSION +1 -1
  9. data/bin/stripe-console +5 -3
  10. data/lib/stripe/api_operations/create.rb +4 -2
  11. data/lib/stripe/api_operations/delete.rb +31 -3
  12. data/lib/stripe/api_operations/list.rb +4 -13
  13. data/lib/stripe/api_operations/nested_resource.rb +73 -0
  14. data/lib/stripe/api_operations/request.rb +84 -17
  15. data/lib/stripe/api_operations/save.rb +25 -13
  16. data/lib/stripe/api_resource.rb +70 -11
  17. data/lib/stripe/connection_manager.rb +179 -0
  18. data/lib/stripe/error_object.rb +93 -0
  19. data/lib/stripe/errors.rb +47 -19
  20. data/lib/stripe/instrumentation.rb +84 -0
  21. data/lib/stripe/list_object.rb +54 -22
  22. data/lib/stripe/multipart_encoder.rb +131 -0
  23. data/lib/stripe/oauth.rb +29 -20
  24. data/lib/stripe/object_types.rb +107 -0
  25. data/lib/stripe/{account.rb → resources/account.rb} +70 -36
  26. data/lib/stripe/resources/account_link.rb +10 -0
  27. data/lib/stripe/resources/alipay_account.rb +34 -0
  28. data/lib/stripe/{apple_pay_domain.rb → resources/apple_pay_domain.rb} +5 -2
  29. data/lib/stripe/resources/application_fee.rb +14 -0
  30. data/lib/stripe/resources/application_fee_refund.rb +31 -0
  31. data/lib/stripe/resources/balance.rb +8 -0
  32. data/lib/stripe/resources/balance_transaction.rb +10 -0
  33. data/lib/stripe/resources/bank_account.rb +43 -0
  34. data/lib/stripe/resources/billing_portal/configuration.rb +14 -0
  35. data/lib/stripe/resources/billing_portal/session.rb +12 -0
  36. data/lib/stripe/{bitcoin_receiver.rb → resources/bitcoin_receiver.rb} +7 -5
  37. data/lib/stripe/resources/bitcoin_transaction.rb +16 -0
  38. data/lib/stripe/resources/capability.rb +34 -0
  39. data/lib/stripe/resources/card.rb +38 -0
  40. data/lib/stripe/resources/charge.rb +23 -0
  41. data/lib/stripe/resources/checkout/session.rb +16 -0
  42. data/lib/stripe/resources/country_spec.rb +10 -0
  43. data/lib/stripe/{coupon.rb → resources/coupon.rb} +5 -2
  44. data/lib/stripe/resources/credit_note.rb +33 -0
  45. data/lib/stripe/resources/credit_note_line_item.rb +8 -0
  46. data/lib/stripe/resources/customer.rb +41 -0
  47. data/lib/stripe/resources/customer_balance_transaction.rb +31 -0
  48. data/lib/stripe/resources/discount.rb +7 -0
  49. data/lib/stripe/resources/dispute.rb +22 -0
  50. data/lib/stripe/resources/ephemeral_key.rb +20 -0
  51. data/lib/stripe/resources/event.rb +10 -0
  52. data/lib/stripe/resources/exchange_rate.rb +10 -0
  53. data/lib/stripe/resources/file.rb +36 -0
  54. data/lib/stripe/resources/file_link.rb +12 -0
  55. data/lib/stripe/resources/identity/verification_report.rb +12 -0
  56. data/lib/stripe/resources/identity/verification_session.rb +35 -0
  57. data/lib/stripe/resources/invoice.rb +74 -0
  58. data/lib/stripe/{invoice_item.rb → resources/invoice_item.rb} +5 -2
  59. data/lib/stripe/resources/invoice_line_item.rb +8 -0
  60. data/lib/stripe/resources/issuing/authorization.rb +34 -0
  61. data/lib/stripe/resources/issuing/card.rb +25 -0
  62. data/lib/stripe/resources/issuing/card_details.rb +9 -0
  63. data/lib/stripe/resources/issuing/cardholder.rb +14 -0
  64. data/lib/stripe/resources/issuing/dispute.rb +25 -0
  65. data/lib/stripe/resources/issuing/transaction.rb +13 -0
  66. data/lib/stripe/resources/line_item.rb +8 -0
  67. data/lib/stripe/resources/login_link.rb +15 -0
  68. data/lib/stripe/resources/mandate.rb +8 -0
  69. data/lib/stripe/resources/order.rb +33 -0
  70. data/lib/stripe/resources/order_return.rb +10 -0
  71. data/lib/stripe/resources/payment_intent.rb +43 -0
  72. data/lib/stripe/resources/payment_method.rb +33 -0
  73. data/lib/stripe/resources/payout.rb +33 -0
  74. data/lib/stripe/resources/person.rb +32 -0
  75. data/lib/stripe/{plan.rb → resources/plan.rb} +4 -1
  76. data/lib/stripe/resources/price.rb +12 -0
  77. data/lib/stripe/{product.rb → resources/product.rb} +6 -3
  78. data/lib/stripe/resources/promotion_code.rb +12 -0
  79. data/lib/stripe/resources/quote.rb +105 -0
  80. data/lib/stripe/resources/radar/early_fraud_warning.rb +12 -0
  81. data/lib/stripe/resources/radar/value_list.rb +15 -0
  82. data/lib/stripe/resources/radar/value_list_item.rb +14 -0
  83. data/lib/stripe/resources/recipient.rb +14 -0
  84. data/lib/stripe/resources/recipient_transfer.rb +7 -0
  85. data/lib/stripe/{refund.rb → resources/refund.rb} +4 -1
  86. data/lib/stripe/resources/reporting/report_run.rb +13 -0
  87. data/lib/stripe/resources/reporting/report_type.rb +13 -0
  88. data/lib/stripe/resources/reversal.rb +30 -0
  89. data/lib/stripe/resources/review.rb +21 -0
  90. data/lib/stripe/resources/setup_attempt.rb +10 -0
  91. data/lib/stripe/resources/setup_intent.rb +33 -0
  92. data/lib/stripe/resources/sigma/scheduled_query_run.rb +16 -0
  93. data/lib/stripe/{sku.rb → resources/sku.rb} +6 -3
  94. data/lib/stripe/resources/source.rb +47 -0
  95. data/lib/stripe/resources/source_transaction.rb +7 -0
  96. data/lib/stripe/resources/subscription.rb +26 -0
  97. data/lib/stripe/resources/subscription_item.rb +26 -0
  98. data/lib/stripe/resources/subscription_schedule.rb +33 -0
  99. data/lib/stripe/resources/tax_code.rb +10 -0
  100. data/lib/stripe/resources/tax_id.rb +27 -0
  101. data/lib/stripe/resources/tax_rate.rb +12 -0
  102. data/lib/stripe/resources/terminal/connection_token.rb +12 -0
  103. data/lib/stripe/resources/terminal/location.rb +15 -0
  104. data/lib/stripe/resources/terminal/reader.rb +15 -0
  105. data/lib/stripe/{three_d_secure.rb → resources/three_d_secure.rb} +4 -1
  106. data/lib/stripe/resources/token.rb +10 -0
  107. data/lib/stripe/resources/topup.rb +23 -0
  108. data/lib/stripe/resources/transfer.rb +27 -0
  109. data/lib/stripe/resources/usage_record.rb +8 -0
  110. data/lib/stripe/resources/usage_record_summary.rb +8 -0
  111. data/lib/stripe/{recipient.rb → resources/webhook_endpoint.rb} +6 -7
  112. data/lib/stripe/resources.rb +90 -0
  113. data/lib/stripe/singleton_api_resource.rb +10 -4
  114. data/lib/stripe/stripe_client.rb +798 -346
  115. data/lib/stripe/stripe_configuration.rb +194 -0
  116. data/lib/stripe/stripe_object.rb +271 -126
  117. data/lib/stripe/stripe_response.rb +89 -27
  118. data/lib/stripe/util.rb +134 -194
  119. data/lib/stripe/version.rb +3 -1
  120. data/lib/stripe/webhook.rb +57 -18
  121. data/lib/stripe.rb +74 -186
  122. data/stripe.gemspec +35 -16
  123. metadata +110 -165
  124. data/.gitattributes +0 -4
  125. data/.github/ISSUE_TEMPLATE.md +0 -5
  126. data/.gitignore +0 -5
  127. data/.travis.yml +0 -38
  128. data/lib/stripe/alipay_account.rb +0 -22
  129. data/lib/stripe/application_fee.rb +0 -22
  130. data/lib/stripe/application_fee_refund.rb +0 -20
  131. data/lib/stripe/balance.rb +0 -5
  132. data/lib/stripe/balance_transaction.rb +0 -11
  133. data/lib/stripe/bank_account.rb +0 -30
  134. data/lib/stripe/bitcoin_transaction.rb +0 -11
  135. data/lib/stripe/card.rb +0 -27
  136. data/lib/stripe/charge.rb +0 -82
  137. data/lib/stripe/country_spec.rb +0 -11
  138. data/lib/stripe/customer.rb +0 -79
  139. data/lib/stripe/dispute.rb +0 -17
  140. data/lib/stripe/ephemeral_key.rb +0 -18
  141. data/lib/stripe/event.rb +0 -7
  142. data/lib/stripe/file_upload.rb +0 -33
  143. data/lib/stripe/invoice.rb +0 -29
  144. data/lib/stripe/invoice_line_item.rb +0 -5
  145. data/lib/stripe/login_link.rb +0 -9
  146. data/lib/stripe/order.rb +0 -29
  147. data/lib/stripe/order_return.rb +0 -11
  148. data/lib/stripe/payout.rb +0 -18
  149. data/lib/stripe/recipient_transfer.rb +0 -6
  150. data/lib/stripe/reversal.rb +0 -20
  151. data/lib/stripe/source.rb +0 -23
  152. data/lib/stripe/subscription.rb +0 -33
  153. data/lib/stripe/subscription_item.rb +0 -14
  154. data/lib/stripe/token.rb +0 -7
  155. data/lib/stripe/transfer.rb +0 -18
  156. data/test/api_stub_helpers.rb +0 -0
  157. data/test/stripe/account_test.rb +0 -202
  158. data/test/stripe/alipay_account_test.rb +0 -17
  159. data/test/stripe/api_operations_test.rb +0 -31
  160. data/test/stripe/api_resource_test.rb +0 -558
  161. data/test/stripe/apple_pay_domain_test.rb +0 -31
  162. data/test/stripe/application_fee_refund_test.rb +0 -35
  163. data/test/stripe/application_fee_test.rb +0 -12
  164. data/test/stripe/balance_test.rb +0 -11
  165. data/test/stripe/bank_account_test.rb +0 -36
  166. data/test/stripe/bitcoin_receiver_test.rb +0 -67
  167. data/test/stripe/bitcoin_transaction_test.rb +0 -19
  168. data/test/stripe/charge_test.rb +0 -57
  169. data/test/stripe/country_spec_test.rb +0 -18
  170. data/test/stripe/coupon_test.rb +0 -42
  171. data/test/stripe/customer_card_test.rb +0 -46
  172. data/test/stripe/customer_test.rb +0 -114
  173. data/test/stripe/dispute_test.rb +0 -40
  174. data/test/stripe/ephemeral_key_test.rb +0 -84
  175. data/test/stripe/errors_test.rb +0 -18
  176. data/test/stripe/file_upload_test.rb +0 -66
  177. data/test/stripe/invoice_item_test.rb +0 -53
  178. data/test/stripe/invoice_line_item_test.rb +0 -6
  179. data/test/stripe/invoice_test.rb +0 -110
  180. data/test/stripe/list_object_test.rb +0 -170
  181. data/test/stripe/login_link_test.rb +0 -35
  182. data/test/stripe/oauth_test.rb +0 -85
  183. data/test/stripe/order_return_test.rb +0 -19
  184. data/test/stripe/order_test.rb +0 -57
  185. data/test/stripe/payout_test.rb +0 -48
  186. data/test/stripe/plan_test.rb +0 -50
  187. data/test/stripe/product_test.rb +0 -45
  188. data/test/stripe/recipient_card_test.rb +0 -44
  189. data/test/stripe/recipient_test.rb +0 -48
  190. data/test/stripe/refund_test.rb +0 -37
  191. data/test/stripe/reversal_test.rb +0 -41
  192. data/test/stripe/sku_test.rb +0 -48
  193. data/test/stripe/source_test.rb +0 -68
  194. data/test/stripe/stripe_client_test.rb +0 -750
  195. data/test/stripe/stripe_object_test.rb +0 -398
  196. data/test/stripe/stripe_response_test.rb +0 -46
  197. data/test/stripe/subscription_item_test.rb +0 -52
  198. data/test/stripe/subscription_test.rb +0 -58
  199. data/test/stripe/three_d_secure_test.rb +0 -21
  200. data/test/stripe/transfer_test.rb +0 -41
  201. data/test/stripe/util_test.rb +0 -414
  202. data/test/stripe/webhook_test.rb +0 -92
  203. data/test/stripe_test.rb +0 -59
  204. data/test/test_data.rb +0 -59
  205. data/test/test_helper.rb +0 -56
@@ -1,750 +0,0 @@
1
- require File.expand_path('../../test_helper', __FILE__)
2
-
3
- module Stripe
4
- class StripeClientTest < Test::Unit::TestCase
5
- context ".active_client" do
6
- should "be .default_client outside of #request" do
7
- assert_equal StripeClient.default_client, StripeClient.active_client
8
- end
9
-
10
- should "be active client inside of #request" do
11
- client = StripeClient.new
12
- client.request do
13
- assert_equal client, StripeClient.active_client
14
- end
15
- end
16
- end
17
-
18
- context ".default_client" do
19
- should "be a StripeClient" do
20
- assert_kind_of StripeClient, StripeClient.default_client
21
- end
22
- end
23
-
24
- context ".default_conn" do
25
- should "be a Faraday::Connection" do
26
- assert_kind_of Faraday::Connection, StripeClient.default_conn
27
- end
28
-
29
- should "be a different connection on each thread" do
30
- other_thread_conn = nil
31
- thread = Thread.new do
32
- other_thread_conn = StripeClient.default_conn
33
- end
34
- thread.join
35
- refute_equal StripeClient.default_conn, other_thread_conn
36
- end
37
- end
38
-
39
- context ".should_retry?" do
40
- setup do
41
- Stripe.stubs(:max_network_retries).returns(2)
42
- end
43
-
44
- should 'retry on timeout' do
45
- assert StripeClient.should_retry?(Faraday::TimeoutError.new(""), 0)
46
- end
47
-
48
- should 'retry on a failed connection' do
49
- assert StripeClient.should_retry?(Faraday::ConnectionFailed.new(""), 0)
50
- end
51
-
52
- should 'retry on a conflict' do
53
- error = make_rate_limit_error
54
- e = Faraday::ClientError.new(error[:error][:message], { status: 409 })
55
- assert StripeClient.should_retry?(e, 0)
56
- end
57
-
58
- should 'not retry at maximum count' do
59
- refute StripeClient.should_retry?(RuntimeError.new, Stripe.max_network_retries)
60
- end
61
-
62
- should 'not retry on a certificate validation error' do
63
- refute StripeClient.should_retry?(Faraday::SSLError.new(""), 0)
64
- end
65
- end
66
-
67
- context ".sleep_time" do
68
- should "should grow exponentially" do
69
- StripeClient.stubs(:rand).returns(1)
70
- Stripe.stubs(:max_network_retry_delay).returns(999)
71
- assert_equal(Stripe.initial_network_retry_delay, StripeClient.sleep_time(1))
72
- assert_equal(Stripe.initial_network_retry_delay * 2, StripeClient.sleep_time(2))
73
- assert_equal(Stripe.initial_network_retry_delay * 4, StripeClient.sleep_time(3))
74
- assert_equal(Stripe.initial_network_retry_delay * 8, StripeClient.sleep_time(4))
75
- end
76
-
77
- should "enforce the max_network_retry_delay" do
78
- StripeClient.stubs(:rand).returns(1)
79
- Stripe.stubs(:initial_network_retry_delay).returns(1)
80
- Stripe.stubs(:max_network_retry_delay).returns(2)
81
- assert_equal(1, StripeClient.sleep_time(1))
82
- assert_equal(2, StripeClient.sleep_time(2))
83
- assert_equal(2, StripeClient.sleep_time(3))
84
- assert_equal(2, StripeClient.sleep_time(4))
85
- end
86
-
87
- should "add some randomness" do
88
- random_value = 0.8
89
- StripeClient.stubs(:rand).returns(random_value)
90
- Stripe.stubs(:initial_network_retry_delay).returns(1)
91
- Stripe.stubs(:max_network_retry_delay).returns(8)
92
-
93
- base_value = Stripe.initial_network_retry_delay * (0.5 * (1 + random_value))
94
-
95
- # the initial value cannot be smaller than the base,
96
- # so the randomness is ignored
97
- assert_equal(Stripe.initial_network_retry_delay, StripeClient.sleep_time(1))
98
-
99
- # after the first one, the randomness is applied
100
- assert_equal(base_value * 2, StripeClient.sleep_time(2))
101
- assert_equal(base_value * 4, StripeClient.sleep_time(3))
102
- assert_equal(base_value * 8, StripeClient.sleep_time(4))
103
- end
104
- end
105
-
106
- context "#initialize" do
107
- should "set Stripe.default_conn" do
108
- client = StripeClient.new
109
- assert_equal StripeClient.default_conn, client.conn
110
- end
111
-
112
- should "set a different connection if one was specified" do
113
- conn = Faraday.new
114
- client = StripeClient.new(conn)
115
- assert_equal conn, client.conn
116
- end
117
- end
118
-
119
- context "#execute_request" do
120
- context "headers" do
121
- should "support literal headers" do
122
- stub_request(:post, "#{Stripe.api_base}/v1/account").
123
- with(headers: { "Stripe-Account" => "bar" }).
124
- to_return(body: JSON.generate({ object: "account" }))
125
-
126
- client = StripeClient.new
127
- client.execute_request(:post, '/v1/account',
128
- headers: { "Stripe-Account" => "bar" }
129
- )
130
- end
131
-
132
- should "support RestClient-style header keys" do
133
- stub_request(:post, "#{Stripe.api_base}/v1/account").
134
- with(headers: { "Stripe-Account" => "bar" }).
135
- to_return(body: JSON.generate({ object: "account" }))
136
-
137
- client = StripeClient.new
138
- client.execute_request(:post, '/v1/account',
139
- headers: { :stripe_account => "bar" }
140
- )
141
- end
142
- end
143
-
144
- context "logging" do
145
- setup do
146
- # Freeze time for the purposes of the `elapsed` parameter that we
147
- # emit for responses. I didn't want to bring in a new dependency for
148
- # this, but Mocha's `anything` parameter can't match inside of a hash
149
- # and is therefore not useful for this purpose. If we switch over to
150
- # rspec-mocks at some point, we can probably remove Timecop from the
151
- # project.
152
- Timecop.freeze(Time.local(1990))
153
- end
154
-
155
- teardown do
156
- Timecop.return
157
- end
158
-
159
- should "produce appropriate logging" do
160
- body = JSON.generate({ object: "account" })
161
-
162
- Util.expects(:log_info).with("Request to Stripe API",
163
- account: "acct_123",
164
- api_version: '2010-11-12',
165
- idempotency_key: "abc",
166
- method: :post,
167
- num_retries: 0,
168
- path: "/v1/account"
169
- )
170
- Util.expects(:log_debug).with("Request details",
171
- body: '',
172
- idempotency_key: "abc"
173
- )
174
-
175
- Util.expects(:log_info).with("Response from Stripe API",
176
- account: "acct_123",
177
- api_version: '2010-11-12',
178
- elapsed: 0.0,
179
- idempotency_key: "abc",
180
- method: :post,
181
- path: "/v1/account",
182
- request_id: "req_123",
183
- status: 200
184
- )
185
- Util.expects(:log_debug).with("Response details",
186
- body: body,
187
- idempotency_key: "abc",
188
- request_id: "req_123"
189
- )
190
- Util.expects(:log_debug).with("Dashboard link for request",
191
- idempotency_key: "abc",
192
- request_id: "req_123",
193
- url: Util.request_id_dashboard_url("req_123", Stripe.api_key)
194
- )
195
-
196
- stub_request(:post, "#{Stripe.api_base}/v1/account").
197
- to_return(
198
- body: body,
199
- headers: {
200
- "Idempotency-Key" => "abc",
201
- "Request-Id" => "req_123",
202
- "Stripe-Account" => "acct_123",
203
- "Stripe-Version" => "2010-11-12"
204
- }
205
- )
206
-
207
- client = StripeClient.new
208
- client.execute_request(:post, '/v1/account',
209
- headers: {
210
- "Idempotency-Key" => "abc",
211
- "Stripe-Account" => "acct_123",
212
- "Stripe-Version" => "2010-11-12"
213
- }
214
- )
215
- end
216
-
217
- should "produce logging on API error" do
218
- Util.expects(:log_info).with("Request to Stripe API",
219
- account: nil,
220
- api_version: nil,
221
- idempotency_key: nil,
222
- method: :post,
223
- num_retries: 0,
224
- path: "/v1/account"
225
- )
226
- Util.expects(:log_info).with("Response from Stripe API",
227
- account: nil,
228
- api_version: nil,
229
- elapsed: 0.0,
230
- idempotency_key: nil,
231
- method: :post,
232
- path: "/v1/account",
233
- request_id: nil,
234
- status: 500
235
- )
236
-
237
- error = {
238
- code: 'code',
239
- message: 'message',
240
- param: 'param',
241
- type: 'type',
242
- }
243
- Util.expects(:log_error).with('Stripe API error',
244
- status: 500,
245
- error_code: error['code'],
246
- error_message: error['message'],
247
- error_param: error['param'],
248
- error_type: error['type'],
249
- idempotency_key: nil,
250
- request_id: nil
251
- )
252
-
253
- stub_request(:post, "#{Stripe.api_base}/v1/account").
254
- to_return(
255
- body: JSON.generate({ :error => error }),
256
- status: 500
257
- )
258
-
259
- client = StripeClient.new
260
- assert_raises Stripe::APIError do
261
- client.execute_request(:post, '/v1/account')
262
- end
263
- end
264
-
265
- should "produce logging on OAuth error" do
266
- Util.expects(:log_info).with("Request to Stripe API",
267
- account: nil,
268
- api_version: nil,
269
- idempotency_key: nil,
270
- method: :post,
271
- num_retries: 0,
272
- path: "/oauth/token"
273
- )
274
- Util.expects(:log_info).with("Response from Stripe API",
275
- account: nil,
276
- api_version: nil,
277
- elapsed: 0.0,
278
- idempotency_key: nil,
279
- method: :post,
280
- path: "/oauth/token",
281
- request_id: nil,
282
- status: 400
283
- )
284
-
285
- Util.expects(:log_error).with('Stripe OAuth error',
286
- status: 400,
287
- error_code: "invalid_request",
288
- error_description: "No grant type specified",
289
- idempotency_key: nil,
290
- request_id: nil
291
- )
292
-
293
- stub_request(:post, "#{Stripe.connect_base}/oauth/token").
294
- to_return(body: JSON.generate({
295
- error: "invalid_request",
296
- error_description: "No grant type specified",
297
- }), status: 400)
298
-
299
- client = StripeClient.new
300
- opts = {api_base: Stripe.connect_base}
301
- assert_raises Stripe::OAuth::InvalidRequestError do
302
- client.execute_request(:post, '/oauth/token', opts)
303
- end
304
- end
305
- end
306
-
307
- context "Stripe-Account header" do
308
- should "use a globally set header" do
309
- begin
310
- old = Stripe.stripe_account
311
- Stripe.stripe_account = 'acct_1234'
312
-
313
- stub_request(:post, "#{Stripe.api_base}/v1/account").
314
- with(headers: {"Stripe-Account" => Stripe.stripe_account}).
315
- to_return(body: JSON.generate({ object: "account" }))
316
-
317
- client = StripeClient.new
318
- client.execute_request(:post, '/v1/account')
319
- ensure
320
- Stripe.stripe_account = old
321
- end
322
- end
323
-
324
- should "use a locally set header" do
325
- stripe_account = "acct_0000"
326
- stub_request(:post, "#{Stripe.api_base}/v1/account").
327
- with(headers: {"Stripe-Account" => stripe_account}).
328
- to_return(body: JSON.generate({ object: "account" }))
329
-
330
- client = StripeClient.new
331
- client.execute_request(:post, '/v1/account',
332
- headers: { :stripe_account => stripe_account }
333
- )
334
- end
335
-
336
- should "not send it otherwise" do
337
- stub_request(:post, "#{Stripe.api_base}/v1/account").
338
- with { |req|
339
- req.headers["Stripe-Account"].nil?
340
- }.to_return(body: JSON.generate({ object: "account" }))
341
-
342
- client = StripeClient.new
343
- client.execute_request(:post, '/v1/account')
344
- end
345
- end
346
-
347
- context "app_info" do
348
- should "send app_info if set" do
349
- begin
350
- old = Stripe.app_info
351
- Stripe.set_app_info(
352
- "MyAwesomePlugin",
353
- url: "https://myawesomeplugin.info",
354
- version: "1.2.34"
355
- )
356
-
357
- stub_request(:post, "#{Stripe.api_base}/v1/account").
358
- with { |req|
359
- assert_equal \
360
- "Stripe/v1 RubyBindings/#{Stripe::VERSION} " \
361
- "MyAwesomePlugin/1.2.34 (https://myawesomeplugin.info)",
362
- req.headers["User-Agent"]
363
-
364
- data = JSON.parse(req.headers["X-Stripe-Client-User-Agent"],
365
- symbolize_names: true)
366
-
367
- assert_equal({
368
- name: "MyAwesomePlugin",
369
- url: "https://myawesomeplugin.info",
370
- version: "1.2.34"
371
- }, data[:application])
372
-
373
- true
374
- }.to_return(body: JSON.generate({ object: "account" }))
375
-
376
- client = StripeClient.new
377
- client.execute_request(:post, '/v1/account')
378
- ensure
379
- Stripe.app_info = old
380
- end
381
- end
382
- end
383
-
384
- context "error handling" do
385
- should "handle error response with empty body" do
386
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
387
- to_return(body: '', status: 500)
388
-
389
- client = StripeClient.new
390
- e = assert_raises Stripe::APIError do
391
- client.execute_request(:post, '/v1/charges')
392
- end
393
-
394
- assert_equal 'Invalid response object from API: "" (HTTP response code was 500)', e.message
395
- end
396
-
397
- should "handle success response with empty body" do
398
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
399
- to_return(body: '', status: 200)
400
-
401
- client = StripeClient.new
402
- e = assert_raises Stripe::APIError do
403
- client.execute_request(:post, '/v1/charges')
404
- end
405
-
406
- assert_equal 'Invalid response object from API: "" (HTTP response code was 200)', e.message
407
- end
408
-
409
- should "handle error response with unknown value" do
410
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
411
- to_return(body: JSON.generate({ bar: "foo" }), status: 500)
412
-
413
- client = StripeClient.new
414
- e = assert_raises Stripe::APIError do
415
- client.execute_request(:post, '/v1/charges')
416
- end
417
-
418
- assert_equal 'Invalid response object from API: "{\"bar\":\"foo\"}" (HTTP response code was 500)', e.message
419
- end
420
-
421
- should "raise InvalidRequestError on 400" do
422
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
423
- to_return(body: JSON.generate(make_missing_id_error), status: 400)
424
- client = StripeClient.new
425
- begin
426
- client.execute_request(:post, '/v1/charges')
427
- rescue Stripe::InvalidRequestError => e
428
- assert_equal(400, e.http_status)
429
- assert_equal(true, !!e.http_body)
430
- assert_equal(true, e.json_body.kind_of?(Hash))
431
- end
432
- end
433
-
434
- should "raise AuthenticationError on 401" do
435
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
436
- to_return(body: JSON.generate(make_missing_id_error), status: 401)
437
- client = StripeClient.new
438
- begin
439
- client.execute_request(:post, '/v1/charges')
440
- rescue Stripe::AuthenticationError => e
441
- assert_equal(401, e.http_status)
442
- assert_equal(true, !!e.http_body)
443
- assert_equal(true, e.json_body.kind_of?(Hash))
444
- end
445
- end
446
-
447
- should "raise CardError on 402" do
448
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
449
- to_return(body: JSON.generate(make_missing_id_error), status: 402)
450
- client = StripeClient.new
451
- begin
452
- client.execute_request(:post, '/v1/charges')
453
- rescue Stripe::CardError => e
454
- assert_equal(402, e.http_status)
455
- assert_equal(true, !!e.http_body)
456
- assert_equal(true, e.json_body.kind_of?(Hash))
457
- end
458
- end
459
-
460
- should "raise PermissionError on 403" do
461
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
462
- to_return(body: JSON.generate(make_missing_id_error), status: 403)
463
- client = StripeClient.new
464
- begin
465
- client.execute_request(:post, '/v1/charges')
466
- rescue Stripe::PermissionError => e
467
- assert_equal(403, e.http_status)
468
- assert_equal(true, !!e.http_body)
469
- assert_equal(true, e.json_body.kind_of?(Hash))
470
- end
471
- end
472
-
473
- should "raise InvalidRequestError on 404" do
474
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
475
- to_return(body: JSON.generate(make_missing_id_error), status: 404)
476
- client = StripeClient.new
477
- begin
478
- client.execute_request(:post, '/v1/charges')
479
- rescue Stripe::InvalidRequestError => e
480
- assert_equal(404, e.http_status)
481
- assert_equal(true, !!e.http_body)
482
- assert_equal(true, e.json_body.kind_of?(Hash))
483
- end
484
- end
485
-
486
- should "raise RateLimitError on 429" do
487
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
488
- to_return(body: JSON.generate(make_rate_limit_error), status: 429)
489
- client = StripeClient.new
490
- begin
491
- client.execute_request(:post, '/v1/charges')
492
- rescue Stripe::RateLimitError => e
493
- assert_equal(429, e.http_status)
494
- assert_equal(true, !!e.http_body)
495
- assert_equal(true, e.json_body.kind_of?(Hash))
496
- end
497
- end
498
-
499
- should "raise OAuth::InvalidRequestError when error is a string with value 'invalid_request'" do
500
- stub_request(:post, "#{Stripe.connect_base}/oauth/token").
501
- to_return(body: JSON.generate({
502
- error: "invalid_request",
503
- error_description: "No grant type specified",
504
- }), status: 400)
505
-
506
- client = StripeClient.new
507
- opts = {api_base: Stripe.connect_base}
508
- e = assert_raises Stripe::OAuth::InvalidRequestError do
509
- client.execute_request(:post, '/oauth/token', opts)
510
- end
511
-
512
- assert_equal(400, e.http_status)
513
- assert_equal(true, !!e.http_body)
514
- assert_equal('No grant type specified', e.message)
515
- end
516
-
517
- should "raise OAuth::InvalidGrantError when error is a string with value 'invalid_grant'" do
518
- stub_request(:post, "#{Stripe.connect_base}/oauth/token").
519
- to_return(body: JSON.generate({
520
- error: "invalid_grant",
521
- error_description: "This authorization code has already been used. All tokens issued with this code have been revoked.",
522
- }), status: 400)
523
-
524
- client = StripeClient.new
525
- opts = {api_base: Stripe.connect_base}
526
- e = assert_raises Stripe::OAuth::InvalidGrantError do
527
- client.execute_request(:post, '/oauth/token', opts)
528
- end
529
-
530
- assert_equal(400, e.http_status)
531
- assert_equal('invalid_grant', e.code)
532
- assert_equal('This authorization code has already been used. All tokens issued with this code have been revoked.', e.message)
533
- end
534
-
535
- should "raise OAuth::InvalidClientError when error is a string with value 'invalid_client'" do
536
- stub_request(:post, "#{Stripe.connect_base}/oauth/deauthorize").
537
- to_return(body: JSON.generate({
538
- error: "invalid_client",
539
- error_description: "This application is not connected to stripe account acct_19tLK7DSlTMT26Mk, or that account does not exist.",
540
- }), status: 401)
541
-
542
- client = StripeClient.new
543
- opts = {api_base: Stripe.connect_base}
544
- e = assert_raises Stripe::OAuth::InvalidClientError do
545
- client.execute_request(:post, '/oauth/deauthorize', opts)
546
- end
547
-
548
- assert_equal(401, e.http_status)
549
- assert_equal('invalid_client', e.code)
550
- assert_equal('This application is not connected to stripe account acct_19tLK7DSlTMT26Mk, or that account does not exist.', e.message)
551
- end
552
-
553
- should "raise Stripe::OAuthError on indeterminate OAuth error" do
554
- stub_request(:post, "#{Stripe.connect_base}/oauth/deauthorize").
555
- to_return(body: JSON.generate({
556
- error: "new_code_not_recognized",
557
- error_description: "Something.",
558
- }), status: 401)
559
-
560
- client = StripeClient.new
561
- opts = {api_base: Stripe.connect_base}
562
- e = assert_raises Stripe::OAuth::OAuthError do
563
- client.execute_request(:post, '/oauth/deauthorize', opts)
564
- end
565
-
566
- assert_equal(401, e.http_status)
567
- assert_equal("new_code_not_recognized", e.code)
568
- assert_equal("Something.", e.message)
569
- end
570
- end
571
-
572
- context "idempotency keys" do
573
- setup do
574
- Stripe.stubs(:max_network_retries).returns(2)
575
- end
576
-
577
- should 'not add an idempotency key to GET requests' do
578
- SecureRandom.expects(:uuid).times(0)
579
- stub_request(:get, "#{Stripe.api_base}/v1/charges/ch_123").
580
- with { |req|
581
- req.headers['Idempotency-Key'].nil?
582
- }.to_return(body: JSON.generate({ object: "charge" }))
583
- client = StripeClient.new
584
- client.execute_request(:get, "/v1/charges/ch_123")
585
- end
586
-
587
- should 'ensure there is always an idempotency_key on POST requests' do
588
- SecureRandom.expects(:uuid).at_least_once.returns("random_key")
589
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
590
- with(headers: {"Idempotency-Key" => "random_key"}).
591
- to_return(body: JSON.generate({ object: "charge" }))
592
- client = StripeClient.new
593
- client.execute_request(:post, "/v1/charges")
594
- end
595
-
596
- should 'ensure there is always an idempotency_key on DELETE requests' do
597
- SecureRandom.expects(:uuid).at_least_once.returns("random_key")
598
- stub_request(:delete, "#{Stripe.api_base}/v1/charges/ch_123").
599
- with(headers: {"Idempotency-Key" => "random_key"}).
600
- to_return(body: JSON.generate({ object: "charge" }))
601
- client = StripeClient.new
602
- client.execute_request(:delete, "/v1/charges/ch_123")
603
- end
604
-
605
- should 'not override a provided idempotency_key' do
606
- # Note that this expectation looks like `:idempotency_key` instead of
607
- # the header `Idempotency-Key` because it's user provided as seen
608
- # below. The ones injected by the library itself look like headers
609
- # (`Idempotency-Key`), but rest-client does allow this symbol
610
- # formatting and will properly override the system generated one as
611
- # expected.
612
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
613
- with(headers: {"Idempotency-Key" => "provided_key"}).
614
- to_return(body: JSON.generate({ object: "charge" }))
615
-
616
- client = StripeClient.new
617
- client.execute_request(:post, "/v1/charges",
618
- headers: {:idempotency_key => 'provided_key'})
619
- end
620
- end
621
-
622
- context "retry logic" do
623
- setup do
624
- Stripe.stubs(:max_network_retries).returns(2)
625
- end
626
-
627
- should 'retry failed requests and raise if error persists' do
628
- StripeClient.expects(:sleep_time).at_least_once.returns(0)
629
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
630
- to_raise(Errno::ECONNREFUSED.new)
631
-
632
- client = StripeClient.new
633
- err = assert_raises Stripe::APIConnectionError do
634
- client.execute_request(:post, '/v1/charges')
635
- end
636
- assert_match(/Request was retried 2 times/, err.message)
637
- end
638
-
639
- should 'retry failed requests and return successful response' do
640
- StripeClient.expects(:sleep_time).at_least_once.returns(0)
641
-
642
- i = 0
643
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
644
- to_return { |_|
645
- if i < 2
646
- i += 1
647
- raise Errno::ECONNREFUSED.new
648
- else
649
- { body: JSON.generate({"id" => "myid"}) }
650
- end
651
- }
652
-
653
- client = StripeClient.new
654
- client.execute_request(:post, '/v1/charges')
655
- end
656
- end
657
-
658
- context "params serialization" do
659
- should 'allows empty strings in params' do
660
- client = StripeClient.new
661
- client.execute_request(:get, '/v1/invoices/upcoming', params: {
662
- customer: 'cus_123',
663
- coupon: ''
664
- })
665
- assert_requested(
666
- :get,
667
- "#{Stripe.api_base}/v1/invoices/upcoming?",
668
- query: {
669
- customer: 'cus_123',
670
- coupon: ''
671
- }
672
- )
673
- end
674
-
675
- should 'filter nils in params' do
676
- client = StripeClient.new
677
- client.execute_request(:get, '/v1/invoices/upcoming', params: {
678
- customer: 'cus_123',
679
- coupon: nil
680
- })
681
- assert_requested(
682
- :get,
683
- "#{Stripe.api_base}/v1/invoices/upcoming?",
684
- query: {
685
- customer: 'cus_123'
686
- }
687
- )
688
- end
689
- end
690
- end
691
-
692
- context "#request" do
693
- should "return a result and response object" do
694
- stub_request(:post, "#{Stripe.api_base}/v1/charges").
695
- to_return(body: JSON.generate({ object: "charge" }))
696
-
697
- client = StripeClient.new
698
- charge, resp = client.request { Charge.create }
699
-
700
- assert charge.is_a?(Charge)
701
- assert resp.is_a?(StripeResponse)
702
- assert_equal 200, resp.http_status
703
- end
704
-
705
- should "return the value of given block" do
706
- client = StripeClient.new
707
- ret, _ = client.request { 7 }
708
- assert_equal 7, ret
709
- end
710
-
711
- should "reset local thread state after a call" do
712
- begin
713
- Thread.current[:stripe_client] = :stripe_client
714
-
715
- client = StripeClient.new
716
- client.request {}
717
-
718
- assert_equal :stripe_client, Thread.current[:stripe_client]
719
- ensure
720
- Thread.current[:stripe_client] = nil
721
- end
722
- end
723
- end
724
- end
725
-
726
- class SystemProfilerTest < Test::Unit::TestCase
727
- context "#get_uname" do
728
- should "run without failure" do
729
- # Don't actually check the result because we try a variety of different
730
- # strategies that will have different results depending on where this
731
- # test and running. We're mostly making sure that no exception is thrown.
732
- _ = StripeClient::SystemProfiler.get_uname
733
- end
734
- end
735
-
736
- context "#get_uname_from_system" do
737
- should "run without failure" do
738
- # as above, just verify that an exception is not thrown
739
- _ = StripeClient::SystemProfiler.get_uname_from_system
740
- end
741
- end
742
-
743
- context "#get_uname_from_system_ver" do
744
- should "run without failure" do
745
- # as above, just verify that an exception is not thrown
746
- _ = StripeClient::SystemProfiler.get_uname_from_system_ver
747
- end
748
- end
749
- end
750
- end