stripe 4.21.2 → 5.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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -4
  3. data/.rubocop_todo.yml +10 -9
  4. data/.travis.yml +2 -6
  5. data/CHANGELOG.md +40 -1
  6. data/Gemfile +2 -12
  7. data/README.md +10 -10
  8. data/Rakefile +8 -7
  9. data/VERSION +1 -1
  10. data/lib/stripe/api_operations/list.rb +0 -6
  11. data/lib/stripe/api_resource.rb +16 -0
  12. data/lib/stripe/connection_manager.rb +131 -0
  13. data/lib/stripe/error_object.rb +94 -0
  14. data/lib/stripe/errors.rb +15 -2
  15. data/lib/stripe/list_object.rb +2 -1
  16. data/lib/stripe/multipart_encoder.rb +131 -0
  17. data/lib/stripe/object_types.rb +0 -4
  18. data/lib/stripe/resources/account.rb +7 -7
  19. data/lib/stripe/resources/account_link.rb +1 -1
  20. data/lib/stripe/resources/alipay_account.rb +1 -1
  21. data/lib/stripe/resources/apple_pay_domain.rb +1 -1
  22. data/lib/stripe/resources/application_fee.rb +1 -12
  23. data/lib/stripe/resources/application_fee_refund.rb +1 -1
  24. data/lib/stripe/resources/balance.rb +1 -1
  25. data/lib/stripe/resources/balance_transaction.rb +1 -5
  26. data/lib/stripe/resources/bank_account.rb +1 -1
  27. data/lib/stripe/resources/bitcoin_receiver.rb +1 -1
  28. data/lib/stripe/resources/bitcoin_transaction.rb +1 -1
  29. data/lib/stripe/resources/capability.rb +1 -1
  30. data/lib/stripe/resources/card.rb +1 -1
  31. data/lib/stripe/resources/charge.rb +7 -69
  32. data/lib/stripe/resources/checkout/session.rb +1 -1
  33. data/lib/stripe/resources/country_spec.rb +1 -1
  34. data/lib/stripe/resources/coupon.rb +1 -1
  35. data/lib/stripe/resources/credit_note.rb +7 -3
  36. data/lib/stripe/resources/customer.rb +3 -63
  37. data/lib/stripe/resources/customer_balance_transaction.rb +1 -1
  38. data/lib/stripe/resources/discount.rb +1 -1
  39. data/lib/stripe/resources/dispute.rb +7 -9
  40. data/lib/stripe/resources/ephemeral_key.rb +1 -1
  41. data/lib/stripe/resources/event.rb +1 -1
  42. data/lib/stripe/resources/exchange_rate.rb +1 -1
  43. data/lib/stripe/resources/file.rb +3 -13
  44. data/lib/stripe/resources/file_link.rb +1 -1
  45. data/lib/stripe/resources/invoice.rb +36 -11
  46. data/lib/stripe/resources/invoice_item.rb +1 -1
  47. data/lib/stripe/resources/invoice_line_item.rb +1 -1
  48. data/lib/stripe/resources/issuing/authorization.rb +13 -5
  49. data/lib/stripe/resources/issuing/card.rb +7 -3
  50. data/lib/stripe/resources/issuing/card_details.rb +1 -1
  51. data/lib/stripe/resources/issuing/cardholder.rb +1 -1
  52. data/lib/stripe/resources/issuing/dispute.rb +1 -1
  53. data/lib/stripe/resources/issuing/transaction.rb +1 -1
  54. data/lib/stripe/resources/login_link.rb +1 -1
  55. data/lib/stripe/resources/order.rb +13 -13
  56. data/lib/stripe/resources/order_return.rb +1 -1
  57. data/lib/stripe/resources/payment_intent.rb +19 -7
  58. data/lib/stripe/resources/payment_method.rb +13 -5
  59. data/lib/stripe/resources/payout.rb +7 -9
  60. data/lib/stripe/resources/person.rb +1 -1
  61. data/lib/stripe/resources/plan.rb +1 -1
  62. data/lib/stripe/resources/product.rb +1 -1
  63. data/lib/stripe/resources/radar/early_fraud_warning.rb +1 -1
  64. data/lib/stripe/resources/radar/value_list.rb +1 -1
  65. data/lib/stripe/resources/radar/value_list_item.rb +1 -1
  66. data/lib/stripe/resources/recipient.rb +1 -5
  67. data/lib/stripe/resources/recipient_transfer.rb +1 -1
  68. data/lib/stripe/resources/refund.rb +1 -1
  69. data/lib/stripe/resources/reporting/report_run.rb +1 -1
  70. data/lib/stripe/resources/reporting/report_type.rb +1 -1
  71. data/lib/stripe/resources/reversal.rb +1 -1
  72. data/lib/stripe/resources/review.rb +7 -3
  73. data/lib/stripe/resources/setup_intent.rb +13 -5
  74. data/lib/stripe/resources/sigma/scheduled_query_run.rb +1 -1
  75. data/lib/stripe/resources/sku.rb +1 -1
  76. data/lib/stripe/resources/source.rb +7 -9
  77. data/lib/stripe/resources/source_transaction.rb +1 -1
  78. data/lib/stripe/resources/subscription.rb +9 -9
  79. data/lib/stripe/resources/subscription_item.rb +4 -1
  80. data/lib/stripe/resources/subscription_schedule.rb +13 -13
  81. data/lib/stripe/resources/tax_id.rb +1 -1
  82. data/lib/stripe/resources/tax_rate.rb +1 -1
  83. data/lib/stripe/resources/terminal/connection_token.rb +1 -1
  84. data/lib/stripe/resources/terminal/location.rb +1 -1
  85. data/lib/stripe/resources/terminal/reader.rb +1 -1
  86. data/lib/stripe/resources/three_d_secure.rb +1 -1
  87. data/lib/stripe/resources/token.rb +1 -1
  88. data/lib/stripe/resources/topup.rb +7 -3
  89. data/lib/stripe/resources/transfer.rb +7 -8
  90. data/lib/stripe/resources/usage_record.rb +1 -17
  91. data/lib/stripe/resources/usage_record_summary.rb +1 -1
  92. data/lib/stripe/resources/webhook_endpoint.rb +1 -1
  93. data/lib/stripe/resources.rb +0 -2
  94. data/lib/stripe/stripe_client.rb +281 -183
  95. data/lib/stripe/stripe_object.rb +4 -23
  96. data/lib/stripe/stripe_response.rb +53 -21
  97. data/lib/stripe/util.rb +14 -11
  98. data/lib/stripe/version.rb +1 -1
  99. data/lib/stripe/webhook.rb +1 -1
  100. data/lib/stripe.rb +56 -15
  101. data/stripe.gemspec +6 -9
  102. data/test/stripe/account_test.rb +0 -16
  103. data/test/stripe/api_operations_test.rb +2 -2
  104. data/test/stripe/api_resource_test.rb +98 -8
  105. data/test/stripe/balance_transaction_test.rb +20 -0
  106. data/test/stripe/charge_test.rb +0 -16
  107. data/test/stripe/connection_manager_test.rb +138 -0
  108. data/test/stripe/customer_test.rb +1 -44
  109. data/test/stripe/errors_test.rb +29 -8
  110. data/test/stripe/file_test.rb +0 -10
  111. data/test/stripe/invoice_test.rb +17 -1
  112. data/test/stripe/list_object_test.rb +0 -16
  113. data/test/stripe/login_link_test.rb +1 -1
  114. data/test/stripe/multipart_encoder_test.rb +130 -0
  115. data/test/stripe/payment_intent_test.rb +1 -1
  116. data/test/stripe/setup_intent_test.rb +1 -1
  117. data/test/stripe/source_test.rb +0 -18
  118. data/test/stripe/stripe_client_test.rb +214 -29
  119. data/test/stripe/stripe_object_test.rb +7 -35
  120. data/test/stripe/stripe_response_test.rb +70 -24
  121. data/test/stripe/subscription_item_test.rb +12 -0
  122. data/test/stripe/subscription_schedule_test.rb +0 -34
  123. data/test/stripe/subscription_test.rb +2 -2
  124. data/test/stripe/webhook_test.rb +2 -2
  125. data/test/stripe_mock.rb +4 -3
  126. data/test/stripe_test.rb +0 -13
  127. data/test/test_helper.rb +10 -5
  128. metadata +13 -42
  129. data/lib/stripe/resources/issuer_fraud_record.rb +0 -9
  130. data/lib/stripe/resources/subscription_schedule_revision.rb +0 -34
  131. data/test/stripe/file_upload_test.rb +0 -79
  132. data/test/stripe/issuer_fraud_record_test.rb +0 -20
  133. data/test/stripe/subscription_schedule_revision_test.rb +0 -37
  134. data/test/stripe/usage_record_test.rb +0 -28
@@ -127,18 +127,6 @@ module Stripe
127
127
  JSON.pretty_generate(@values)
128
128
  end
129
129
 
130
- # Re-initializes the object based on a hash of values (usually one that's
131
- # come back from an API call). Adds or removes value accessors as necessary
132
- # and updates the state of internal data.
133
- #
134
- # Please don't use this method. If you're trying to do mass assignment, try
135
- # #initialize_from instead.
136
- def refresh_from(values, opts, partial = false)
137
- initialize_from(values, opts, partial)
138
- end
139
- extend Gem::Deprecate
140
- deprecate :refresh_from, "#update_attributes", 2016, 1
141
-
142
130
  # Mass assigns attributes on the model.
143
131
  #
144
132
  # This is a version of +update_attributes+ that takes some extra options
@@ -192,7 +180,9 @@ module Stripe
192
180
 
193
181
  def to_hash
194
182
  maybe_to_hash = lambda do |value|
195
- value && value.respond_to?(:to_hash) ? value.to_hash : value
183
+ return nil if value.nil?
184
+
185
+ value.respond_to?(:to_hash) ? value.to_hash : value
196
186
  end
197
187
 
198
188
  @values.each_with_object({}) do |(key, value), acc|
@@ -256,6 +246,7 @@ module Stripe
256
246
  #
257
247
  unsaved = @unsaved_values.include?(k)
258
248
  next unless options[:force] || unsaved || v.is_a?(StripeObject)
249
+
259
250
  update_hash[k.to_sym] = serialize_params_value(
260
251
  @values[k], @original_values[k], unsaved, options[:force], key: k
261
252
  )
@@ -268,16 +259,6 @@ module Stripe
268
259
  update_hash
269
260
  end
270
261
 
271
- class << self
272
- # This class method has been deprecated in favor of the instance method
273
- # of the same name.
274
- def serialize_params(obj, options = {})
275
- obj.serialize_params(options)
276
- end
277
- extend Gem::Deprecate
278
- deprecate :serialize_params, "#serialize_params", 2016, 9
279
- end
280
-
281
262
  # A protected field is one that doesn't get an accessor assigned to it
282
263
  # (i.e. `obj.public = ...`) and one which is not allowed to be updated via
283
264
  # the class level `Model.update(id, { ... })`.
@@ -4,6 +4,53 @@ module Stripe
4
4
  # StripeResponse encapsulates some vitals of a response that came back from
5
5
  # the Stripe API.
6
6
  class StripeResponse
7
+ # Headers provides an access wrapper to an API response's header data. It
8
+ # mainly exists so that we don't need to expose the entire
9
+ # `Net::HTTPResponse` object while still getting some of its benefits like
10
+ # case-insensitive access to header names and flattening of header values.
11
+ class Headers
12
+ # Initializes a Headers object from a Net::HTTP::HTTPResponse object.
13
+ def self.from_net_http(resp)
14
+ new(resp.to_hash)
15
+ end
16
+
17
+ # `hash` is expected to be a hash mapping header names to arrays of
18
+ # header values. This is the default format generated by calling
19
+ # `#to_hash` on a `Net::HTTPResponse` object because headers can be
20
+ # repeated multiple times. Using `#[]` will collapse values down to just
21
+ # the first.
22
+ def initialize(hash)
23
+ if !hash.is_a?(Hash) ||
24
+ !hash.keys.all? { |n| n.is_a?(String) } ||
25
+ !hash.values.all? { |a| a.is_a?(Array) } ||
26
+ !hash.values.all? { |a| a.all? { |v| v.is_a?(String) } }
27
+ raise ArgumentError,
28
+ "expect hash to be a map of string header names to arrays of " \
29
+ "header values"
30
+ end
31
+
32
+ @hash = {}
33
+
34
+ # This shouldn't be strictly necessary because `Net::HTTPResponse` will
35
+ # produce a hash with all headers downcased, but do it anyway just in
36
+ # case an object of this class was constructed manually.
37
+ #
38
+ # Also has the effect of duplicating the hash, which is desirable for a
39
+ # little extra object safety.
40
+ hash.each do |k, v|
41
+ @hash[k.downcase] = v
42
+ end
43
+ end
44
+
45
+ def [](name)
46
+ values = @hash[name.downcase]
47
+ if values && values.count > 1
48
+ warn("Duplicate header values for `#{name}`; returning only first")
49
+ end
50
+ values ? values.first : nil
51
+ end
52
+ end
53
+
7
54
  # The data contained by the HTTP body of the response deserialized from
8
55
  # JSON.
9
56
  attr_accessor :data
@@ -20,30 +67,15 @@ module Stripe
20
67
  # The Stripe request ID of the response.
21
68
  attr_accessor :request_id
22
69
 
23
- # Initializes a StripeResponse object from a Hash like the kind returned as
24
- # part of a Faraday exception.
25
- #
26
- # This may throw JSON::ParserError if the response body is not valid JSON.
27
- def self.from_faraday_hash(http_resp)
28
- resp = StripeResponse.new
29
- resp.data = JSON.parse(http_resp[:body], symbolize_names: true)
30
- resp.http_body = http_resp[:body]
31
- resp.http_headers = http_resp[:headers]
32
- resp.http_status = http_resp[:status]
33
- resp.request_id = http_resp[:headers]["Request-Id"]
34
- resp
35
- end
36
-
37
- # Initializes a StripeResponse object from a Faraday HTTP response object.
38
- #
39
- # This may throw JSON::ParserError if the response body is not valid JSON.
40
- def self.from_faraday_response(http_resp)
70
+ # Initializes a StripeResponse object from a Net::HTTP::HTTPResponse
71
+ # object.
72
+ def self.from_net_http(http_resp)
41
73
  resp = StripeResponse.new
42
74
  resp.data = JSON.parse(http_resp.body, symbolize_names: true)
43
75
  resp.http_body = http_resp.body
44
- resp.http_headers = http_resp.headers
45
- resp.http_status = http_resp.status
46
- resp.request_id = http_resp.headers["Request-Id"]
76
+ resp.http_headers = Headers.from_net_http(http_resp)
77
+ resp.http_status = http_resp.code.to_i
78
+ resp.request_id = http_resp["request-id"]
47
79
  resp
48
80
  end
49
81
  end
data/lib/stripe/util.rb CHANGED
@@ -43,6 +43,10 @@ module Stripe
43
43
  @object_classes ||= Stripe::ObjectTypes.object_names_to_classes
44
44
  end
45
45
 
46
+ def self.object_name_matches_class?(object_name, klass)
47
+ Util.object_classes[object_name] == klass
48
+ end
49
+
46
50
  # Converts a hash of fields or an array of hashes into a +StripeObject+ or
47
51
  # array of +StripeObject+s. These new objects will be created as a concrete
48
52
  # type as dictated by their `object` field (e.g. an `object` value of
@@ -194,11 +198,13 @@ module Stripe
194
198
 
195
199
  def self.check_string_argument!(key)
196
200
  raise TypeError, "argument must be a string" unless key.is_a?(String)
201
+
197
202
  key
198
203
  end
199
204
 
200
205
  def self.check_api_key!(key)
201
206
  raise TypeError, "api_key must be a string" unless key.is_a?(String)
207
+
202
208
  key
203
209
  end
204
210
 
@@ -241,14 +247,14 @@ module Stripe
241
247
  #
242
248
 
243
249
  COLOR_CODES = {
244
- black: 0, light_black: 60,
245
- red: 1, light_red: 61,
246
- green: 2, light_green: 62,
247
- yellow: 3, light_yellow: 63,
248
- blue: 4, light_blue: 64,
250
+ black: 0, light_black: 60,
251
+ red: 1, light_red: 61,
252
+ green: 2, light_green: 62,
253
+ yellow: 3, light_yellow: 63,
254
+ blue: 4, light_blue: 64,
249
255
  magenta: 5, light_magenta: 65,
250
- cyan: 6, light_cyan: 66,
251
- white: 7, light_white: 67,
256
+ cyan: 6, light_cyan: 66,
257
+ white: 7, light_white: 67,
252
258
  default: 9,
253
259
  }.freeze
254
260
  private_constant :COLOR_CODES
@@ -277,10 +283,7 @@ module Stripe
277
283
  end
278
284
  private_class_method :level_name
279
285
 
280
- # TODO: Make these named required arguments when we drop support for Ruby
281
- # 2.0.
282
- def self.log_internal(message, data = {}, color: nil, level: nil,
283
- logger: nil, out: nil)
286
+ def self.log_internal(message, data = {}, color:, level:, logger:, out:)
284
287
  data_str = data.reject { |_k, v| v.nil? }
285
288
  .map do |(k, v)|
286
289
  format("%<key>s=%<value>s",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stripe
4
- VERSION = "4.21.2".freeze
4
+ VERSION = "5.0.0"
5
5
  end
@@ -22,7 +22,7 @@ module Stripe
22
22
  end
23
23
 
24
24
  module Signature
25
- EXPECTED_SCHEME = "v1".freeze
25
+ EXPECTED_SCHEME = "v1"
26
26
 
27
27
  def self.compute_signature(payload, secret)
28
28
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, payload)
data/lib/stripe.rb CHANGED
@@ -3,9 +3,9 @@
3
3
  # Stripe Ruby bindings
4
4
  # API spec at https://stripe.com/docs/api
5
5
  require "cgi"
6
- require "faraday"
7
6
  require "json"
8
7
  require "logger"
8
+ require "net/http"
9
9
  require "openssl"
10
10
  require "rbconfig"
11
11
  require "securerandom"
@@ -28,10 +28,13 @@ require "stripe/api_operations/save"
28
28
  require "stripe/errors"
29
29
  require "stripe/object_types"
30
30
  require "stripe/util"
31
+ require "stripe/connection_manager"
32
+ require "stripe/multipart_encoder"
31
33
  require "stripe/stripe_client"
32
34
  require "stripe/stripe_object"
33
35
  require "stripe/stripe_response"
34
36
  require "stripe/list_object"
37
+ require "stripe/error_object"
35
38
  require "stripe/api_resource"
36
39
  require "stripe/singleton_api_resource"
37
40
  require "stripe/webhook"
@@ -70,9 +73,20 @@ module Stripe
70
73
  @enable_telemetry = true
71
74
 
72
75
  class << self
73
- attr_accessor :stripe_account, :api_key, :api_base, :verify_ssl_certs,
74
- :api_version, :client_id, :connect_base, :uploads_base,
75
- :open_timeout, :read_timeout, :proxy
76
+ attr_accessor :api_key
77
+ attr_accessor :api_version
78
+ attr_accessor :client_id
79
+ attr_accessor :stripe_account
80
+
81
+ # These all get manual attribute writers so that we can reset connections
82
+ # if they change.
83
+ attr_reader :api_base
84
+ attr_reader :connect_base
85
+ attr_reader :open_timeout
86
+ attr_reader :proxy
87
+ attr_reader :read_timeout
88
+ attr_reader :uploads_base
89
+ attr_reader :verify_ssl_certs
76
90
 
77
91
  attr_reader :max_network_retry_delay, :initial_network_retry_delay
78
92
  end
@@ -87,6 +101,11 @@ module Stripe
87
101
  @app_info = info
88
102
  end
89
103
 
104
+ def self.api_base=(api_base)
105
+ @api_base = api_base
106
+ StripeClient.clear_all_connection_managers
107
+ end
108
+
90
109
  # The location of a file containing a bundle of CA certificates. By default
91
110
  # the library will use an included bundle that can successfully validate
92
111
  # Stripe certificates.
@@ -99,6 +118,8 @@ module Stripe
99
118
 
100
119
  # empty this field so a new store is initialized
101
120
  @ca_store = nil
121
+
122
+ StripeClient.clear_all_connection_managers
102
123
  end
103
124
 
104
125
  # A certificate store initialized from the the bundle in #ca_bundle_path and
@@ -118,6 +139,19 @@ module Stripe
118
139
  end
119
140
  end
120
141
 
142
+ def self.connection_base=(connection_base)
143
+ @connection_base = connection_base
144
+ StripeClient.clear_all_connection_managers
145
+ end
146
+
147
+ def self.enable_telemetry?
148
+ @enable_telemetry
149
+ end
150
+
151
+ def self.enable_telemetry=(val)
152
+ @enable_telemetry = val
153
+ end
154
+
121
155
  # map to the same values as the standard library's logger
122
156
  LEVEL_DEBUG = Logger::DEBUG
123
157
  LEVEL_ERROR = Logger::ERROR
@@ -172,12 +206,19 @@ module Stripe
172
206
  @max_network_retries = val.to_i
173
207
  end
174
208
 
175
- def self.enable_telemetry?
176
- @enable_telemetry
209
+ def self.open_timeout=(open_timeout)
210
+ @open_timeout = open_timeout
211
+ StripeClient.clear_all_connection_managers
177
212
  end
178
213
 
179
- def self.enable_telemetry=(val)
180
- @enable_telemetry = val
214
+ def self.proxy=(proxy)
215
+ @proxy = proxy
216
+ StripeClient.clear_all_connection_managers
217
+ end
218
+
219
+ def self.read_timeout=(read_timeout)
220
+ @read_timeout = read_timeout
221
+ StripeClient.clear_all_connection_managers
181
222
  end
182
223
 
183
224
  # Sets some basic information about the running application that's sent along
@@ -194,14 +235,14 @@ module Stripe
194
235
  }
195
236
  end
196
237
 
197
- # DEPRECATED. Use `Util#encode_parameters` instead.
198
- def self.uri_encode(params)
199
- Util.encode_parameters(params)
238
+ def self.uploads_base=(uploads_base)
239
+ @uploads_base = uploads_base
240
+ StripeClient.clear_all_connection_managers
200
241
  end
201
- private_class_method :uri_encode
202
- class << self
203
- extend Gem::Deprecate
204
- deprecate :uri_encode, "Stripe::Util#encode_parameters", 2016, 1
242
+
243
+ def self.verify_ssl_certs=(verify_ssl_certs)
244
+ @verify_ssl_certs = verify_ssl_certs
245
+ StripeClient.clear_all_connection_managers
205
246
  end
206
247
  end
207
248
 
data/stripe.gemspec CHANGED
@@ -7,7 +7,7 @@ require "stripe/version"
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "stripe"
9
9
  s.version = Stripe::VERSION
10
- s.required_ruby_version = ">= 2.1.0"
10
+ s.required_ruby_version = ">= 2.3.0"
11
11
  s.summary = "Ruby bindings for the Stripe API"
12
12
  s.description = "Stripe is the easiest way to accept payments online. " \
13
13
  "See https://stripe.com for details."
@@ -17,18 +17,15 @@ Gem::Specification.new do |s|
17
17
  s.license = "MIT"
18
18
 
19
19
  s.metadata = {
20
- "bug_tracker_uri" => "https://github.com/stripe/stripe-ruby/issues",
21
- "changelog_uri" =>
20
+ "bug_tracker_uri" => "https://github.com/stripe/stripe-ruby/issues",
21
+ "changelog_uri" =>
22
22
  "https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md",
23
23
  "documentation_uri" => "https://stripe.com/docs/api/ruby",
24
- "github_repo" => "ssh://github.com/stripe/stripe-ruby",
25
- "homepage_uri" => "https://stripe.com/docs/api/ruby",
26
- "source_code_uri" => "https://github.com/stripe/stripe-ruby",
24
+ "github_repo" => "ssh://github.com/stripe/stripe-ruby",
25
+ "homepage_uri" => "https://stripe.com/docs/api/ruby",
26
+ "source_code_uri" => "https://github.com/stripe/stripe-ruby",
27
27
  }
28
28
 
29
- s.add_dependency("faraday", "~> 0.13")
30
- s.add_dependency("net-http-persistent", "~> 3.0")
31
-
32
29
  s.files = `git ls-files`.split("\n")
33
30
  s.test_files = `git ls-files -- test/*`.split("\n")
34
31
  s.executables = `git ls-files -- bin/*`.split("\n")
@@ -82,22 +82,6 @@ module Stripe
82
82
  assert persons.data[0].is_a?(Stripe::Person)
83
83
  end
84
84
 
85
- context "#bank_account=" do
86
- should "warn that #bank_account= is deprecated" do
87
- old_stderr = $stderr
88
- $stderr = StringIO.new
89
- begin
90
- account = Stripe::Account.retrieve("acct_123")
91
- account.bank_account = "tok_123"
92
- message = "NOTE: Stripe::Account#bank_account= is " \
93
- "deprecated; use #external_account= instead"
94
- assert_match Regexp.new(message), $stderr.string
95
- ensure
96
- $stderr = old_stderr
97
- end
98
- end
99
- end
100
-
101
85
  context "#deauthorize" do
102
86
  should "deauthorize an account" do
103
87
  account = Stripe::Account.retrieve("acct_123")
@@ -7,7 +7,7 @@ module Stripe
7
7
  class UpdateableResource < APIResource
8
8
  include Stripe::APIOperations::Save
9
9
 
10
- OBJECT_NAME = "updateableresource".freeze
10
+ OBJECT_NAME = "updateableresource"
11
11
 
12
12
  def self.protected_fields
13
13
  [:protected]
@@ -34,7 +34,7 @@ module Stripe
34
34
  context ".nested_resource_class_methods" do
35
35
  class MainResource < APIResource
36
36
  extend Stripe::APIOperations::NestedResource
37
- OBJECT_NAME = "mainresource".freeze
37
+ OBJECT_NAME = "mainresource"
38
38
  nested_resource_class_methods :nested,
39
39
  operations: %i[create retrieve update delete list]
40
40
  end
@@ -4,10 +4,31 @@ require ::File.expand_path("../test_helper", __dir__)
4
4
 
5
5
  module Stripe
6
6
  class ApiResourceTest < Test::Unit::TestCase
7
+ class CustomMethodAPIResource < APIResource
8
+ OBJECT_NAME = "custom_method"
9
+ custom_method :my_method, http_verb: :post
10
+ end
11
+
7
12
  class NestedTestAPIResource < APIResource
8
13
  save_nested_resource :external_account
9
14
  end
10
15
 
16
+ context ".custom_method" do
17
+ should "call to an RPC-style method" do
18
+ stub_request(:post, "#{Stripe.api_base}/v1/custom_methods/ch_123/my_method")
19
+ .to_return(body: JSON.generate({}))
20
+ CustomMethodAPIResource.my_method("ch_123")
21
+ end
22
+
23
+ should "raise an error if a non-ID is passed" do
24
+ e = assert_raises ArgumentError do
25
+ CustomMethodAPIResource.my_method(id: "ch_123")
26
+ end
27
+ assert_equal "id should be a string representing the ID of an API resource",
28
+ e.message
29
+ end
30
+ end
31
+
11
32
  context ".save_nested_resource" do
12
33
  should "can have a scalar set" do
13
34
  r = NestedTestAPIResource.new("test_resource")
@@ -250,14 +271,6 @@ module Stripe
250
271
  assert_equal c.created, 12_345
251
272
  end
252
273
 
253
- should "accessing a property other than id or parent on an unfetched object should fetch it" do
254
- stub_request(:get, "#{Stripe.api_base}/v1/charges")
255
- .with(query: { customer: "cus_123" })
256
- .to_return(body: JSON.generate(customer_fixture))
257
- c = Stripe::Customer.new("cus_123")
258
- c.charges
259
- end
260
-
261
274
  should "updating an object should issue a POST request with only the changed properties" do
262
275
  stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123")
263
276
  .with(body: { "description" => "another_mn" })
@@ -490,6 +503,83 @@ module Stripe
490
503
  end
491
504
  end
492
505
 
506
+ context "#request_stripe_object" do
507
+ class HelloTestAPIResource < APIResource
508
+ OBJECT_NAME = "hello"
509
+ def say_hello(params = {}, opts = {})
510
+ request_stripe_object(
511
+ method: :post,
512
+ path: resource_url + "/say",
513
+ params: params,
514
+ opts: opts
515
+ )
516
+ end
517
+ end
518
+
519
+ setup do
520
+ Util.instance_variable_set(
521
+ :@object_classes,
522
+ Stripe::ObjectTypes.object_names_to_classes.merge(
523
+ "hello" => HelloTestAPIResource
524
+ )
525
+ )
526
+ end
527
+ teardown do
528
+ Util.class.instance_variable_set(:@object_classes, Stripe::ObjectTypes.object_names_to_classes)
529
+ end
530
+
531
+ should "make requests appropriately" do
532
+ stub_request(:post, "#{Stripe.api_base}/v1/hellos/hi_123/say")
533
+ .with(body: { foo: "bar" }, headers: { "Stripe-Account" => "acct_hi" })
534
+ .to_return(body: JSON.generate("object" => "hello"))
535
+
536
+ hello = HelloTestAPIResource.new(id: "hi_123")
537
+ hello.say_hello({ foo: "bar" }, stripe_account: "acct_hi")
538
+ end
539
+
540
+ should "update attributes in-place when it returns the same thing" do
541
+ stub_request(:post, "#{Stripe.api_base}/v1/hellos/hi_123/say")
542
+ .to_return(body: JSON.generate("object" => "hello", "additional" => "attribute"))
543
+
544
+ hello = HelloTestAPIResource.new(id: "hi_123")
545
+ hello.unsaved = "a value"
546
+ new_hello = hello.say_hello
547
+
548
+ # Doesn't matter if you use the return variable or the instance.
549
+ assert_equal(hello, new_hello)
550
+
551
+ # It updates new attributes in-place.
552
+ assert_equal("attribute", hello.additional)
553
+
554
+ # It removes unsaved attributes, but at least lets you know about them.
555
+ e = assert_raises(NoMethodError) { hello.unsaved }
556
+ assert_match("The 'unsaved' attribute was set in the past", e.message)
557
+ end
558
+
559
+ should "instantiate a new object of the appropriate class when it is different than the host class" do
560
+ stub_request(:post, "#{Stripe.api_base}/v1/hellos/hi_123/say")
561
+ .to_return(body: JSON.generate("object" => "goodbye", "additional" => "attribute"))
562
+
563
+ hello = HelloTestAPIResource.new(id: "hi_123")
564
+ hello.unsaved = "a value"
565
+ new_goodbye = hello.say_hello
566
+
567
+ # The returned value and the instance are different objects.
568
+ refute_equal(new_goodbye, hello)
569
+
570
+ # The returned value has stuff from the server.
571
+ assert_equal("attribute", new_goodbye.additional)
572
+ assert_equal("goodbye", new_goodbye.object)
573
+
574
+ # You instance doesn't have stuff from the server.
575
+ e = assert_raises(NoMethodError) { hello.additional }
576
+ refute_match(/was set in the past/, e.message)
577
+
578
+ # The instance preserves unset attributes on the original instance (not sure this is good behavior?)
579
+ assert_equal("a value", hello.unsaved)
580
+ end
581
+ end
582
+
493
583
  @@fixtures = {} # rubocop:disable Style/ClassVars
494
584
  setup do
495
585
  if @@fixtures.empty?
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require ::File.expand_path("../test_helper", __dir__)
4
+
5
+ module Stripe
6
+ class BalanceTransactionTest < Test::Unit::TestCase
7
+ should "be listable" do
8
+ balance_transactions = Stripe::BalanceTransaction.list
9
+ assert_requested :get, "#{Stripe.api_base}/v1/balance_transactions"
10
+ assert balance_transactions.data.is_a?(Array)
11
+ assert balance_transactions.first.is_a?(Stripe::BalanceTransaction)
12
+ end
13
+
14
+ should "be retrievable" do
15
+ balance_transaction = Stripe::BalanceTransaction.retrieve("txn_123")
16
+ assert_requested :get, "#{Stripe.api_base}/v1/balance_transactions/txn_123"
17
+ assert balance_transaction.is_a?(Stripe::BalanceTransaction)
18
+ end
19
+ end
20
+ end
@@ -60,21 +60,5 @@ module Stripe
60
60
  assert charge.is_a?(Stripe::Charge)
61
61
  end
62
62
  end
63
-
64
- context "#mark_as_fraudulent" do
65
- should "charges should be able to be marked as fraudulent" do
66
- charge = Stripe::Charge.retrieve("ch_123")
67
- charge = charge.mark_as_fraudulent
68
- assert charge.is_a?(Stripe::Charge)
69
- end
70
- end
71
-
72
- context "#mark_as_safe" do
73
- should "charges should be able to be marked as safe" do
74
- charge = Stripe::Charge.retrieve("ch_123")
75
- charge = charge.mark_as_safe
76
- assert charge.is_a?(Stripe::Charge)
77
- end
78
- end
79
63
  end
80
64
  end