stripe 1.18.0 → 1.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +11 -1
  4. data/History.txt +98 -0
  5. data/README.rdoc +19 -10
  6. data/VERSION +1 -1
  7. data/lib/stripe/account.rb +46 -4
  8. data/lib/stripe/api_operations/create.rb +3 -10
  9. data/lib/stripe/api_operations/delete.rb +4 -4
  10. data/lib/stripe/api_operations/list.rb +17 -9
  11. data/lib/stripe/api_operations/request.rb +41 -0
  12. data/lib/stripe/api_operations/update.rb +41 -40
  13. data/lib/stripe/api_resource.rb +7 -4
  14. data/lib/stripe/application_fee.rb +3 -4
  15. data/lib/stripe/application_fee_refund.rb +1 -1
  16. data/lib/stripe/balance_transaction.rb +1 -1
  17. data/lib/stripe/bank_account.rb +19 -0
  18. data/lib/stripe/bitcoin_receiver.rb +12 -2
  19. data/lib/stripe/bitcoin_transaction.rb +5 -0
  20. data/lib/stripe/card.rb +6 -4
  21. data/lib/stripe/charge.rb +14 -22
  22. data/lib/stripe/coupon.rb +2 -2
  23. data/lib/stripe/customer.rb +24 -26
  24. data/lib/stripe/dispute.rb +16 -0
  25. data/lib/stripe/errors/card_error.rb +3 -2
  26. data/lib/stripe/errors/invalid_request_error.rb +3 -2
  27. data/lib/stripe/errors/rate_limit_error.rb +4 -0
  28. data/lib/stripe/errors/stripe_error.rb +8 -2
  29. data/lib/stripe/event.rb +1 -1
  30. data/lib/stripe/file_upload.rb +12 -22
  31. data/lib/stripe/invoice.rb +8 -8
  32. data/lib/stripe/invoice_item.rb +2 -2
  33. data/lib/stripe/list_object.rb +77 -13
  34. data/lib/stripe/order.rb +19 -0
  35. data/lib/stripe/plan.rb +2 -2
  36. data/lib/stripe/product.rb +16 -0
  37. data/lib/stripe/recipient.rb +2 -2
  38. data/lib/stripe/refund.rb +2 -9
  39. data/lib/stripe/reversal.rb +14 -0
  40. data/lib/stripe/singleton_api_resource.rb +2 -2
  41. data/lib/stripe/sku.rb +8 -0
  42. data/lib/stripe/stripe_object.rb +232 -46
  43. data/lib/stripe/subscription.rb +3 -3
  44. data/lib/stripe/token.rb +1 -1
  45. data/lib/stripe/transfer.rb +3 -3
  46. data/lib/stripe/util.rb +64 -21
  47. data/lib/stripe/version.rb +1 -1
  48. data/lib/stripe.rb +102 -67
  49. data/stripe.gemspec +0 -2
  50. data/test/stripe/account_test.rb +135 -6
  51. data/test/stripe/api_resource_test.rb +326 -42
  52. data/test/stripe/application_fee_refund_test.rb +6 -6
  53. data/test/stripe/application_fee_test.rb +3 -3
  54. data/test/stripe/balance_test.rb +11 -0
  55. data/test/stripe/bitcoin_receiver_test.rb +30 -7
  56. data/test/stripe/bitcoin_transaction_test.rb +29 -0
  57. data/test/stripe/charge_refund_test.rb +55 -0
  58. data/test/stripe/charge_test.rb +32 -13
  59. data/test/stripe/coupon_test.rb +3 -3
  60. data/test/stripe/customer_card_test.rb +20 -14
  61. data/test/stripe/customer_test.rb +15 -15
  62. data/test/stripe/dispute_test.rb +45 -0
  63. data/test/stripe/file_upload_test.rb +17 -6
  64. data/test/stripe/invoice_test.rb +18 -4
  65. data/test/stripe/list_object_test.rb +126 -2
  66. data/test/stripe/metadata_test.rb +28 -13
  67. data/test/stripe/order_test.rb +52 -0
  68. data/test/stripe/product_test.rb +41 -0
  69. data/test/stripe/recipient_card_test.rb +9 -9
  70. data/test/stripe/refund_test.rb +23 -15
  71. data/test/stripe/reversal_test.rb +47 -0
  72. data/test/stripe/sku_test.rb +24 -0
  73. data/test/stripe/stripe_object_test.rb +67 -6
  74. data/test/stripe/subscription_test.rb +13 -13
  75. data/test/stripe/transfer_test.rb +4 -4
  76. data/test/stripe/util_test.rb +45 -29
  77. data/test/stripe_test.rb +16 -0
  78. data/test/test_data.rb +273 -66
  79. metadata +47 -76
  80. data/lib/stripe/certificate_blacklist.rb +0 -55
  81. data/test/stripe/certificate_blacklist_test.rb +0 -18
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 061c68a3e8fbf7b2adfa0a93489b1b124b08cb37
4
+ data.tar.gz: 4fda58089700ad1f39ab8a084b09982679b4e9a1
5
+ SHA512:
6
+ metadata.gz: b2f3f7dff2c30038b9608f825f542061eccb6461bb1c0a9bebfb754ac5d7031c00e4df16e0a753edf92c5934435dcd1bfe191dfd2bdd5744c67ffdc268f3e16c
7
+ data.tar.gz: b68dfc54c11b18e6081a5794c89d717812607f334c60744f7b0cf0ba2a65a337f8f0465c4e092471cb3709e30df8fc62267550b73d255857914b40c1d9f32c47
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  /Gemfile.lock
3
3
  .rvmrc
4
4
  Gemfile.lock
5
+ tags
data/.travis.yml CHANGED
@@ -6,11 +6,21 @@ rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
8
  - 2.1
9
- - 2.2
9
+ - 2.2
10
+ - jruby-19mode
10
11
 
11
12
  gemfile:
12
13
  - gemfiles/default-with-activesupport.gemfile
13
14
  - gemfiles/json.gemfile
14
15
  - gemfiles/yajl.gemfile
15
16
 
17
+ matrix:
18
+ exclude:
19
+ - rvm: jruby-19mode
20
+ gemfile: gemfiles/yajl.gemfile
21
+
22
+ notifications:
23
+ email:
24
+ on_success: never
25
+
16
26
  sudo: false
data/History.txt CHANGED
@@ -1,3 +1,101 @@
1
+ === 1.30.0 2015-10-09
2
+
3
+ * Add `StripeObject#deleted?` for a reliable way to check whether an object is alive
4
+ * Deprecate `StripeObject#refresh_from`
5
+ * New parameter encoding scheme that doesn't use `URI.escape`
6
+
7
+ === 1.29.1 2015-10-06
8
+
9
+ * Fix bug where ampersands were not being properly encoded
10
+
11
+ === 1.29.0 2015-10-05
12
+
13
+ * Add pagination helpers `#auto_paging_each`, `#previous_page`, and `#next_page`
14
+
15
+ === 1.28.1 2015-10-05
16
+
17
+ * Fix URI being referenced by file upload resources
18
+
19
+ === 1.28.0 2015-10-05
20
+
21
+ * Make StripeObject's #save "upsert"-like; creates an object if new
22
+ * Add #update_attributes to StripeObject for safe mass assignment
23
+ * Properly mass assign attributes on calls to #save
24
+ * Add question mark helpers for boolean fields (e.g. #paid? as well as old #paid)
25
+ * Fix a bug that broke the API for StripeObject initialization
26
+ * Remove use of deprecated URI.escape
27
+
28
+ === 1.27.2 2015-09-25
29
+
30
+ * Correct the URLs used to fetch Bitcoin transactions.
31
+
32
+ === 1.27.1 2015-09-20
33
+
34
+ * Use hash rockets for backwards compatibility.
35
+
36
+ === 1.27.0 2015-09-14
37
+
38
+ * Add Orders, Products, and SKUs for Relay.
39
+
40
+ === 1.26.0 2015-09-11
41
+
42
+ * Add support for 429 Rate Limited response
43
+
44
+ === 1.25.0 2015-08-17
45
+
46
+ * Added support for refund listing and retrieval without an associated charge
47
+
48
+ === 1.24.0 2015-08-03
49
+
50
+ * Added support for deleting managed accounts
51
+ * Added support for dispute listing and retrieval
52
+ * Bugfix: token objects now are the correct class
53
+
54
+ === 1.23.0 2015-07-06
55
+
56
+ * Added request IDs and HTTP headers to errors.
57
+
58
+ === 1.22.0 2015-06-10
59
+
60
+ * Added support for bank accounts and debit cards in managed accounts (via the `external_accounts` param)
61
+
62
+ === 1.21.0 2015-04-14
63
+
64
+ * Remove TLS cert revocation check. (All pre-heartbleed certs have expired.)
65
+ * Bugfix: don't unset keys when they don't exist on StripeObject.
66
+
67
+ === 1.20.4 2015-03-26
68
+
69
+ * Raise an error when explicitly passing nil as the API key on resource methods
70
+ * Fix error when passing an API key to Balance.retrieve (github issue #232)
71
+
72
+ === 1.20.3 2015-03-13
73
+
74
+ * Fixed error when updating certain resources (github issue #224)
75
+
76
+ === 1.20.2 2015-03-10
77
+
78
+ * Added support for updating nested hashes besides `metadata` (which was already supported)
79
+ * Fixed bug in balance retrieval
80
+
81
+ === 1.20.1 2015-02-26
82
+
83
+ * Updated Card to point to customer sources endpoint when customer property is set
84
+
85
+ === 1.20.0 2015-02-19
86
+
87
+ * Added Update & Delete operations to Bitcoin Receivers
88
+
89
+ === 1.19.1 2015-02-18
90
+
91
+ * Fixed fetching upcoming invoice/paying invoice methods
92
+
93
+ === 1.19.0 2015-02-15
94
+
95
+ * Support for new Transfers /reversals endpoint
96
+ * Account retrieval now optionally accepts an account ID
97
+ * Better support for passing custom headers, like Stripe-Account, through requests
98
+
1
99
  === 1.18.0 2015-01-21
2
100
 
3
101
  * 1 major enhancement:
data/README.rdoc CHANGED
@@ -1,11 +1,15 @@
1
- = Stripe Ruby bindings {<img src="https://travis-ci.org/stripe/stripe-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/stripe/stripe-ruby] {<img src="https://gemnasium.com/stripe/stripe-ruby.png" alt="Dependency Status" />}[https://gemnasium.com/stripe/stripe-ruby]
1
+ = Stripe Ruby bindings {<img src="https://travis-ci.org/stripe/stripe-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/stripe/stripe-ruby]
2
+
3
+ == Documentation
4
+
5
+ {Ruby API Docs}[https://stripe.com/docs/api/ruby#intro]
2
6
 
3
7
  == Installation
4
8
 
5
9
  You don't need this source code unless you want to modify the gem. If
6
10
  you just want to use the Stripe Ruby bindings, you should run:
7
11
 
8
- gem install --source https://code.stripe.com stripe
12
+ gem install stripe
9
13
 
10
14
  If you want to build the gem from source:
11
15
 
@@ -23,17 +27,12 @@ If you want to build the gem from source:
23
27
 
24
28
  * rest-client, json
25
29
 
26
- == Mirrors
30
+ == Bundler
27
31
 
28
- The stripe gem is mirrored on Rubygems, so you should be able to
29
- install it via <tt>gem install stripe</tt> if desired. We recommend using
30
- the https://code.stripe.com mirror so all code is fetched over SSL.
31
-
32
- Note that if you are installing via bundler, you should be sure to use the https
32
+ If you are installing via bundler, you should be sure to use the https
33
33
  rubygems source in your Gemfile, as any gems fetched over http could potentially be
34
34
  compromised in transit and alter the code of gems fetched securely over https:
35
35
 
36
- source 'https://code.stripe.com'
37
36
  source 'https://rubygems.org'
38
37
 
39
38
  gem 'rails'
@@ -41,4 +40,14 @@ compromised in transit and alter the code of gems fetched securely over https:
41
40
 
42
41
  == Development
43
42
 
44
- Test cases can be run with: `bundle exec rake test`
43
+ Run all tests:
44
+
45
+ bundle exec rake
46
+
47
+ Run a single test suite:
48
+
49
+ bundle exec ruby -Ilib/ test/stripe/util_test.rb
50
+
51
+ Run a single test:
52
+
53
+ bundle exec ruby -Ilib/ test/stripe/util_test.rb -n /should.convert.names.to.symbols/
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.18.0
1
+ 1.30.0
@@ -1,9 +1,51 @@
1
1
  module Stripe
2
- class Account < SingletonAPIResource
2
+ class Account < APIResource
3
+ extend Stripe::APIOperations::Create
4
+ include Stripe::APIOperations::Delete
5
+ extend Stripe::APIOperations::List
6
+ include Stripe::APIOperations::Update
7
+
8
+ def url
9
+ if self['id']
10
+ super
11
+ else
12
+ "/v1/account"
13
+ end
14
+ end
15
+
16
+ # @override To make id optional
17
+ def self.retrieve(id=ARGUMENT_NOT_PROVIDED, opts={})
18
+ id = id.equal?(ARGUMENT_NOT_PROVIDED) ? nil : Util.check_string_argument!(id)
19
+ # Account used to be a singleton, where this method's signature was `(opts={})`.
20
+ # For the sake of not breaking folks who pass in an OAuth key in opts, let's lurkily
21
+ # string match for it.
22
+ if opts == {} && id.is_a?(String) && id.start_with?('sk_')
23
+ # `super` properly assumes a String opts is the apiKey and normalizes as expected.
24
+ opts = id
25
+ id = nil
26
+ end
27
+ super(id, opts)
28
+ end
29
+
30
+ def protected_fields
31
+ [:legal_entity]
32
+ end
33
+
34
+ def legal_entity
35
+ self['legal_entity']
36
+ end
37
+
38
+ def legal_entity=(_)
39
+ raise NoMethodError.new('Overridding legal_entity can cause serious issues. Instead, set the individual fields of legal_entity like blah.legal_entity.first_name = \'Blah\'')
40
+ end
41
+
3
42
  def deauthorize(client_id, opts={})
4
- api_key, headers = Util.parse_opts(opts)
5
- response, api_key = Stripe.request(:post, '/oauth/deauthorize', api_key, { 'client_id' => client_id, 'stripe_user_id' => self.id }, headers, Stripe.connect_base)
6
- Util.convert_to_stripe_object(response, api_key)
43
+ opts = {:api_base => Stripe.connect_base}.merge(Util.normalize_opts(opts))
44
+ response, opts = request(:post, '/oauth/deauthorize', { 'client_id' => client_id, 'stripe_user_id' => self.id }, opts)
45
+ opts.delete(:api_base) # the api_base here is a one-off, don't persist it
46
+ Util.convert_to_stripe_object(response, opts)
7
47
  end
48
+
49
+ ARGUMENT_NOT_PROVIDED = Object.new
8
50
  end
9
51
  end
@@ -1,16 +1,9 @@
1
1
  module Stripe
2
2
  module APIOperations
3
3
  module Create
4
- module ClassMethods
5
- def create(params={}, opts={})
6
- api_key, headers = Util.parse_opts(opts)
7
- response, api_key = Stripe.request(:post, self.url, api_key, params, headers)
8
- Util.convert_to_stripe_object(response, api_key)
9
- end
10
- end
11
-
12
- def self.included(base)
13
- base.extend(ClassMethods)
4
+ def create(params={}, opts={})
5
+ response, opts = request(:post, url, params, opts)
6
+ Util.convert_to_stripe_object(response, opts)
14
7
  end
15
8
  end
16
9
  end
@@ -1,10 +1,10 @@
1
1
  module Stripe
2
2
  module APIOperations
3
3
  module Delete
4
- def delete(params = {}, opts={})
5
- api_key, headers = Util.parse_opts(opts)
6
- response, api_key = Stripe.request(:delete, url, api_key || @api_key, params, headers)
7
- refresh_from(response, api_key)
4
+ def delete(params={}, opts={})
5
+ opts = Util.normalize_opts(opts)
6
+ response, opts = request(:delete, url, params, opts)
7
+ initialize_from(response, opts)
8
8
  end
9
9
  end
10
10
  end
@@ -1,17 +1,25 @@
1
1
  module Stripe
2
2
  module APIOperations
3
3
  module List
4
- module ClassMethods
5
- def all(filters={}, opts={})
6
- api_key, headers = Util.parse_opts(opts)
7
- response, api_key = Stripe.request(:get, url, api_key, filters, headers)
8
- Util.convert_to_stripe_object(response, api_key)
9
- end
10
- end
4
+ def list(filters={}, opts={})
5
+ opts = Util.normalize_opts(opts)
6
+ opts = @opts.merge(opts) if @opts
7
+
8
+ response, opts = request(:get, url, filters, opts)
9
+ obj = ListObject.construct_from(response, opts)
11
10
 
12
- def self.included(base)
13
- base.extend(ClassMethods)
11
+ # set a limit so that we can fetch the same number when accessing the
12
+ # next and previous pages
13
+ obj.limit = filters[:limit]
14
+
15
+ obj
14
16
  end
17
+
18
+ # The original version of #list was given the somewhat unfortunate name of
19
+ # #all, and this alias allows us to maintain backward compatibility (the
20
+ # choice was somewhat misleading in the way that it only returned a single
21
+ # page rather than all objects).
22
+ alias :all :list
15
23
  end
16
24
  end
17
25
  end
@@ -0,0 +1,41 @@
1
+ module Stripe
2
+ module APIOperations
3
+ module Request
4
+ module ClassMethods
5
+ OPTS_KEYS_TO_PERSIST = Set[:api_key, :api_base, :stripe_account, :stripe_version]
6
+
7
+ def request(method, url, params={}, opts={})
8
+ opts = Util.normalize_opts(opts)
9
+
10
+ headers = opts.clone
11
+ api_key = headers.delete(:api_key)
12
+ api_base = headers.delete(:api_base)
13
+ # Assume all remaining opts must be headers
14
+
15
+ response, opts[:api_key] = Stripe.request(method, url, api_key, params, headers, api_base)
16
+
17
+ # Hash#select returns an array before 1.9
18
+ opts_to_persist = {}
19
+ opts.each do |k, v|
20
+ if OPTS_KEYS_TO_PERSIST.include?(k)
21
+ opts_to_persist[k] = v
22
+ end
23
+ end
24
+
25
+ [response, opts_to_persist]
26
+ end
27
+ end
28
+
29
+ def self.included(base)
30
+ base.extend(ClassMethods)
31
+ end
32
+
33
+ protected
34
+
35
+ def request(method, url, params={}, opts={})
36
+ opts = @opts.merge(Util.normalize_opts(opts))
37
+ self.class.request(method, url, params, opts)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,55 +1,56 @@
1
1
  module Stripe
2
2
  module APIOperations
3
3
  module Update
4
- def save(opts={})
5
- values = serialize_params(self).merge(opts)
6
-
7
- if @values[:metadata]
8
- values[:metadata] = serialize_metadata
9
- end
4
+ # Creates or updates an API resource.
5
+ #
6
+ # If the resource doesn't yet have an assigned ID and the resource is one
7
+ # that can be created, then the method attempts to create the resource.
8
+ # The resource is updated otherwise.
9
+ #
10
+ # ==== Attributes
11
+ #
12
+ # * +params+ - Overrides any parameters in the resource's serialized data
13
+ # and includes them in the create or update. If +:req_url:+ is included
14
+ # in the list, it overrides the update URL used for the create or
15
+ # update.
16
+ def save(params={})
17
+ # Let the caller override the URL but avoid serializing it.
18
+ req_url = params.delete(:req_url) || save_url
19
+
20
+ # We started unintentionally (sort of) allowing attributes send to
21
+ # +save+ to override values used during the update. So as not to break
22
+ # the API, this makes that official here.
23
+ update_attributes(params)
24
+
25
+ # Now remove any parameters that look like object attributes.
26
+ params = params.reject { |k, _| respond_to?(k) }
27
+
28
+ values = self.class.serialize_params(self).merge(params)
10
29
 
11
30
  if values.length > 0
31
+ # note that id gets removed here our call to #url above has already
32
+ # generated a uri for this object with an identifier baked in
12
33
  values.delete(:id)
13
34
 
14
- response, api_key = Stripe.request(:post, url, @api_key, values)
15
- refresh_from(response, api_key)
35
+ response, opts = request(:post, req_url, values)
36
+ initialize_from(response, opts)
16
37
  end
17
38
  self
18
39
  end
19
40
 
20
- def serialize_metadata
21
- if @unsaved_values.include?(:metadata)
22
- # the metadata object has been reassigned
23
- # i.e. as object.metadata = {key => val}
24
- metadata_update = @values[:metadata] # new hash
25
- new_keys = metadata_update.keys.map(&:to_sym)
26
- # remove keys at the server, but not known locally
27
- keys_to_unset = @previous_metadata.keys - new_keys
28
- keys_to_unset.each {|key| metadata_update[key] = ''}
29
-
30
- metadata_update
31
- else
32
- # metadata is a StripeObject, and can be serialized normally
33
- serialize_params(@values[:metadata])
34
- end
35
- end
36
-
37
- def serialize_params(obj)
38
- case obj
39
- when nil
40
- ''
41
- when StripeObject
42
- unsaved_keys = obj.instance_variable_get(:@unsaved_values)
43
- obj_values = obj.instance_variable_get(:@values)
44
- update_hash = {}
45
-
46
- unsaved_keys.each do |k|
47
- update_hash[k] = serialize_params(obj_values[k])
48
- end
49
-
50
- update_hash
41
+ private
42
+
43
+ def save_url
44
+ # This switch essentially allows us "upsert"-like functionality. If the
45
+ # API resource doesn't have an ID set (suggesting that it's new) and
46
+ # its class responds to .create (which comes from
47
+ # Stripe::APIOperations::Create), then use the URL to create a new
48
+ # resource. Otherwise, generate a URL based on the object's identifier
49
+ # for a normal update.
50
+ if self[:id] == nil && self.class.respond_to?(:create)
51
+ self.class.url
51
52
  else
52
- obj
53
+ url
53
54
  end
54
55
  end
55
56
  end
@@ -1,5 +1,7 @@
1
1
  module Stripe
2
2
  class APIResource < StripeObject
3
+ include Stripe::APIOperations::Request
4
+
3
5
  def self.class_name
4
6
  self.name.split('::')[-1]
5
7
  end
@@ -19,12 +21,13 @@ module Stripe
19
21
  end
20
22
 
21
23
  def refresh
22
- response, api_key = Stripe.request(:get, url, @api_key, @retrieve_options)
23
- refresh_from(response, api_key)
24
+ response, opts = request(:get, url, @retrieve_params)
25
+ initialize_from(response, opts)
24
26
  end
25
27
 
26
- def self.retrieve(id, api_key=nil)
27
- instance = self.new(id, api_key)
28
+ def self.retrieve(id, opts={})
29
+ opts = Util.normalize_opts(opts)
30
+ instance = self.new(id, opts)
28
31
  instance.refresh
29
32
  instance
30
33
  end
@@ -1,15 +1,14 @@
1
1
  module Stripe
2
2
  class ApplicationFee < APIResource
3
- include Stripe::APIOperations::List
3
+ extend Stripe::APIOperations::List
4
4
 
5
5
  def self.url
6
6
  '/v1/application_fees'
7
7
  end
8
8
 
9
9
  def refund(params={}, opts={})
10
- api_key, headers = Util.parse_opts(opts)
11
- response, api_key = Stripe.request(:post, refund_url, api_key || @api_key, params, headers)
12
- refresh_from(response, api_key)
10
+ response, opts = request(:post, refund_url, params, opts)
11
+ initialize_from(response, opts)
13
12
  end
14
13
 
15
14
  private
@@ -1,7 +1,7 @@
1
1
  module Stripe
2
2
  class ApplicationFeeRefund < APIResource
3
3
  include Stripe::APIOperations::Update
4
- include Stripe::APIOperations::List
4
+ extend Stripe::APIOperations::List
5
5
 
6
6
  def url
7
7
  "#{ApplicationFee.url}/#{CGI.escape(fee)}/refunds/#{CGI.escape(id)}"
@@ -1,6 +1,6 @@
1
1
  module Stripe
2
2
  class BalanceTransaction < APIResource
3
- include Stripe::APIOperations::List
3
+ extend Stripe::APIOperations::List
4
4
 
5
5
  def self.url
6
6
  '/v1/balance/history'
@@ -0,0 +1,19 @@
1
+ module Stripe
2
+ class BankAccount < APIResource
3
+ include Stripe::APIOperations::Update
4
+ include Stripe::APIOperations::Delete
5
+ extend Stripe::APIOperations::List
6
+
7
+ def url
8
+ if respond_to?(:customer)
9
+ "#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
10
+ elsif respond_to?(:account)
11
+ "#{Account.url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
12
+ end
13
+ end
14
+
15
+ def self.retrieve(id, opts=nil)
16
+ raise NotImplementedError.new("Bank accounts cannot be retrieved without an account ID. Retrieve a bank account using account.external_accounts.retrieve('card_id')")
17
+ end
18
+ end
19
+ end
@@ -1,10 +1,20 @@
1
1
  module Stripe
2
2
  class BitcoinReceiver < APIResource
3
- include Stripe::APIOperations::Create
4
- include Stripe::APIOperations::List
3
+ extend Stripe::APIOperations::Create
4
+ include Stripe::APIOperations::Update
5
+ include Stripe::APIOperations::Delete
6
+ extend Stripe::APIOperations::List
5
7
 
6
8
  def self.url
7
9
  "/v1/bitcoin/receivers"
8
10
  end
11
+
12
+ def url
13
+ if respond_to?(:customer)
14
+ "#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
15
+ else
16
+ "#{self.class.url}/#{CGI.escape(id)}"
17
+ end
18
+ end
9
19
  end
10
20
  end
@@ -1,4 +1,9 @@
1
1
  module Stripe
2
2
  class BitcoinTransaction < APIResource
3
+ extend Stripe::APIOperations::List
4
+
5
+ def self.url
6
+ "/v1/bitcoin/transactions"
7
+ end
3
8
  end
4
9
  end
data/lib/stripe/card.rb CHANGED
@@ -2,18 +2,20 @@ module Stripe
2
2
  class Card < APIResource
3
3
  include Stripe::APIOperations::Update
4
4
  include Stripe::APIOperations::Delete
5
- include Stripe::APIOperations::List
5
+ extend Stripe::APIOperations::List
6
6
 
7
7
  def url
8
8
  if respond_to?(:recipient)
9
9
  "#{Recipient.url}/#{CGI.escape(recipient)}/cards/#{CGI.escape(id)}"
10
10
  elsif respond_to?(:customer)
11
- "#{Customer.url}/#{CGI.escape(customer)}/cards/#{CGI.escape(id)}"
11
+ "#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
12
+ elsif respond_to?(:account)
13
+ "#{Account.url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
12
14
  end
13
15
  end
14
16
 
15
- def self.retrieve(id, api_key=nil)
16
- raise NotImplementedError.new("Cards cannot be retrieved without a customer ID. Retrieve a card using customer.cards.retrieve('card_id')")
17
+ def self.retrieve(id, opts=nil)
18
+ raise NotImplementedError.new("Cards cannot be retrieved without a customer ID. Retrieve a card using customer.sources.retrieve('card_id')")
17
19
  end
18
20
  end
19
21
  end