recurly 0.4.16 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of recurly might be problematic. Click here for more details.

Files changed (78) hide show
  1. data/README.markdown +118 -0
  2. data/bin/recurly +78 -0
  3. data/lib/rails/generators/recurly/config_generator.rb +16 -0
  4. data/lib/rails/recurly.rb +13 -0
  5. data/lib/recurly.rb +64 -139
  6. data/lib/recurly/account.rb +52 -111
  7. data/lib/recurly/add_on.rb +20 -0
  8. data/lib/recurly/adjustment.rb +51 -0
  9. data/lib/recurly/api.rb +73 -0
  10. data/lib/recurly/api/errors.rb +205 -0
  11. data/lib/recurly/api/net_http.rb +77 -0
  12. data/lib/recurly/billing_info.rb +45 -42
  13. data/lib/recurly/coupon.rb +63 -8
  14. data/lib/recurly/helper.rb +39 -0
  15. data/lib/recurly/invoice.rb +38 -16
  16. data/lib/recurly/js.rb +113 -0
  17. data/lib/recurly/money.rb +105 -0
  18. data/lib/recurly/plan.rb +26 -15
  19. data/lib/recurly/redemption.rb +34 -0
  20. data/lib/recurly/resource.rb +925 -0
  21. data/lib/recurly/resource/pager.rb +210 -0
  22. data/lib/recurly/subscription.rb +90 -67
  23. data/lib/recurly/subscription/add_ons.rb +73 -0
  24. data/lib/recurly/transaction.rb +65 -53
  25. data/lib/recurly/transaction/errors.rb +98 -0
  26. data/lib/recurly/version.rb +16 -2
  27. data/lib/recurly/xml.rb +85 -0
  28. data/lib/recurly/xml/nokogiri.rb +49 -0
  29. data/lib/recurly/xml/rexml.rb +50 -0
  30. metadata +76 -165
  31. data/LICENSE +0 -21
  32. data/README.md +0 -104
  33. data/init.rb +0 -1
  34. data/lib/patches/rails2/active_resource/base.rb +0 -35
  35. data/lib/patches/rails2/active_resource/connection.rb +0 -10
  36. data/lib/patches/rails3/active_model/serializers/xml.rb +0 -28
  37. data/lib/patches/rails3/active_resource/connection.rb +0 -10
  38. data/lib/recurly/account_base.rb +0 -35
  39. data/lib/recurly/base.rb +0 -195
  40. data/lib/recurly/charge.rb +0 -39
  41. data/lib/recurly/config_parser.rb +0 -31
  42. data/lib/recurly/credit.rb +0 -28
  43. data/lib/recurly/exceptions.rb +0 -32
  44. data/lib/recurly/formats/xml_with_errors.rb +0 -132
  45. data/lib/recurly/formats/xml_with_pagination.rb +0 -47
  46. data/lib/recurly/rails2/compatibility.rb +0 -8
  47. data/lib/recurly/rails3/railtie.rb +0 -21
  48. data/lib/recurly/rails3/recurly.rake +0 -28
  49. data/lib/recurly/transparent.rb +0 -148
  50. data/lib/recurly/verification.rb +0 -83
  51. data/spec/config/recurly.yml +0 -6
  52. data/spec/config/test1.yml +0 -4
  53. data/spec/config/test2.yml +0 -7
  54. data/spec/integration/account_spec.rb +0 -286
  55. data/spec/integration/add_on_spec.rb +0 -84
  56. data/spec/integration/billing_info_spec.rb +0 -148
  57. data/spec/integration/charge_spec.rb +0 -176
  58. data/spec/integration/coupon_spec.rb +0 -49
  59. data/spec/integration/credit_spec.rb +0 -106
  60. data/spec/integration/invoice_spec.rb +0 -86
  61. data/spec/integration/plan_spec.rb +0 -87
  62. data/spec/integration/subscription_spec.rb +0 -221
  63. data/spec/integration/transaction_spec.rb +0 -154
  64. data/spec/integration/transparent_spec.rb +0 -99
  65. data/spec/spec_helper.rb +0 -34
  66. data/spec/support/factory.rb +0 -211
  67. data/spec/support/vcr.rb +0 -11
  68. data/spec/unit/account_spec.rb +0 -19
  69. data/spec/unit/billing_info_spec.rb +0 -39
  70. data/spec/unit/charge_spec.rb +0 -20
  71. data/spec/unit/config_spec.rb +0 -42
  72. data/spec/unit/coupon_spec.rb +0 -13
  73. data/spec/unit/credit_spec.rb +0 -20
  74. data/spec/unit/plan_spec.rb +0 -18
  75. data/spec/unit/subscription_spec.rb +0 -25
  76. data/spec/unit/transaction_spec.rb +0 -32
  77. data/spec/unit/transparent_spec.rb +0 -152
  78. data/spec/unit/verification_spec.rb +0 -82
data/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License
2
-
3
- Copyright (c) 2011 Recurly, Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
data/README.md DELETED
@@ -1,104 +0,0 @@
1
- Recurly Ruby Client
2
- ===================
3
-
4
- The Recurly Ruby Client library is an open source library to interact with Recurly's subscription management from your Ruby on Rails website. The library interacts with Recurly's [REST API](http://support.recurly.com/api/basics).
5
-
6
-
7
- Usage
8
- -----
9
-
10
- Please see the [documentation](http://support.recurly.com/faqs/api/ruby-client) and
11
- [support forums](http://support.recurly.com/discussions) for more information. The [API Documentation](http://docs.recurly.com/api/basics) has numerous examples demonstrating how to use the Recurly Ruby client library.
12
-
13
-
14
- Installation
15
- ------------
16
-
17
- gem 'recurly', '~> 0.4'
18
-
19
-
20
- Configuration
21
- -------------
22
-
23
- The Recurly Ruby Client requires an API user to connect. Please see the [Authentication](http://docs.recurly.com/api/authentication/) documentation for more information.
24
-
25
- In a YAML file at 'config/recurly.yml':
26
-
27
- production:
28
- api_key: your_api_key
29
- private_key: your_private_key
30
- subdomain: your_recurly_subdomain
31
-
32
- development:
33
- api_key: your_api_key
34
- private_key: your_private_key
35
- subdomain: your_recurly_subdomain
36
-
37
- The environment is optional. If you're using the same account with development and production, it can be simplified to:
38
-
39
- api_key: your_api_key
40
- private_key: your_private_key
41
- subdomain: your_recurly_subdomain
42
-
43
- Or, you may configure the Recurly gem using a `configure` block in 'config/initializers/recurly.rb':
44
-
45
- Recurly.configure do |c|
46
- c.api_key = 'your_api_key'
47
- c.private_key = 'your_private_key'
48
- c.subdomain = 'your-recurly-subdomain'
49
- end
50
-
51
- **Please Note:** the setup parameters changed in version 0.4.0. Additional configuration options were also added for the [Transparent Post API](http://docs.recurly.com/transparent-post/basics).
52
-
53
-
54
- Manual Setup via YAML or JSON
55
- --------------
56
- You can also configure Recurly via a YAML file by using:
57
-
58
- Recurly.configure_from_yaml("./config/recurly.yml")
59
-
60
- The Recurly Configuration YAML is in the format of:
61
-
62
- api_key: your_api_key
63
- private_key: your_private_key
64
- subdomain: your_recurly_subdomain
65
-
66
-
67
- The same format could be applied in JSON instead of YAML using: Recurly.configure_from_json('path/to/file.json')
68
-
69
-
70
- Rails Demo Application
71
- ----------------
72
-
73
- [Recurly Ruby Demo App](http://github.com/recurly/recurly-client-ruby-demo)
74
-
75
-
76
- Examples
77
- --------
78
-
79
- The [API Documentation](http://docs.recurly.com/api/basics) has numerous examples demonstrating how to use the Ruby client library.
80
-
81
- All the functionality is also demonstrated by the tests in the __spec__ directory.
82
-
83
-
84
- Running the Specs
85
- ------------------
86
-
87
- Recurly gem uses RSpec2 for testing. It also uses VCR / Webmock to handle fast and repeatable full integration tests with the API.
88
-
89
- The way this works is when each spec is first run, it will save each HTTP request generated within the spec/vcr folder. Subsequent http requests will be mocked using the data contained in these YML files.
90
-
91
- The specs require API credentials in '/spec/config/recurly.yml' and the following setup in your Recurly account:
92
-
93
- * A plan with no trial, use plan_code "paid".
94
- * Add-ons with the codes "special" and "special2" on the "paid" plan.
95
- * A plan with a trial period, use plan_code "trial"
96
- * A coupon with the coupon_code "coupon" which can be applied to all plans.
97
-
98
- To re-run specs, you will need to clear the test data from your Recurly account.
99
-
100
-
101
- API Documentation
102
- -----------------
103
-
104
- Please see the [Recurly API](http://docs.recurly.com/api/basics) for more information and examples.
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'recurly'
@@ -1,35 +0,0 @@
1
- module ActiveResource
2
- class Base
3
-
4
- # Patch for Rails 3.0 and below (fixed in 3.1) to properly
5
- # resolve resources inside nested modules, allowing for
6
- # ActiveRecord models and other classes with the same names
7
- # as Recurly's nested resources (CreditCard, etc)
8
- #
9
- # This issue was unintentially fixed in Rails 3.1 by this commit:
10
- # https://github.com/rails/rails/commit/a962bfe47232200c20dce02047201247d24d77f7
11
- def find_or_create_resource_for(name)
12
- resource_name = name.to_s.camelize
13
-
14
- const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false]
15
- if self.class.const_defined?(*const_args)
16
- self.class.const_get(*const_args)
17
- else
18
- ancestors = self.class.name.split("::")
19
- if ancestors.size > 1
20
- find_resource_in_modules(resource_name, ancestors)
21
- elsif Object.const_defined?(*const_args)
22
- Object.const_get(*const_args)
23
- else
24
- raise NameError
25
- end
26
- end
27
- rescue NameError
28
- resource = self.class.const_set(resource_name, Class.new(ActiveResource::Base))
29
- resource.prefix = self.class.prefix
30
- resource.site = self.class.site
31
- resource
32
- end
33
-
34
- end
35
- end
@@ -1,10 +0,0 @@
1
- module ActiveResource
2
- class Connection
3
-
4
- # Get the results without decoding
5
- def get_raw(path, headers = {})
6
- request(:get, path, build_request_headers(headers, :get))
7
- end
8
-
9
- end
10
- end
@@ -1,28 +0,0 @@
1
- module ActiveModel
2
- module Serializers
3
- module Xml
4
-
5
- # Patch for Rails 3.0 to properly serialize nil values (without type="yaml")
6
- #
7
- # This issue was fixed in Rails 3.0.20 by this pull request:
8
- # https://github.com/rails/rails/pull/8853
9
-
10
- class Serializer
11
- class Attribute
12
-
13
- protected
14
-
15
- def compute_type
16
- return if value.nil?
17
- type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name]
18
- type ||= :string if value.respond_to?(:to_str)
19
- type ||= :yaml
20
- type
21
- end
22
-
23
- end
24
- end
25
-
26
- end
27
- end
28
- end
@@ -1,10 +0,0 @@
1
- module ActiveResource
2
- class Connection
3
-
4
- # Get the results without decoding
5
- def get_raw(path, headers = {})
6
- with_auth { request(:get, path, build_request_headers(headers, :get, self.site.merge(path))) }
7
- end
8
-
9
- end
10
- end
@@ -1,35 +0,0 @@
1
-
2
- module Recurly
3
- # ActiveRecord treats resources as plural by default. Some resources are singular.
4
- class AccountBase < Base
5
- self.prefix = "/accounts/:account_code/"
6
-
7
- # Override element_path because this is a singular resource
8
- def self.element_path(id, prefix_options = {}, query_options = nil)
9
- prefix_options, query_options = split_options(prefix_options) if query_options.nil?
10
- prefix_options.merge!(:account_code => id) if id
11
- # original: "#{prefix(prefix_options)}#{collection_name}/#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
12
- "#{prefix(prefix_options)}#{element_name}.#{format.extension}#{query_string(query_options)}"
13
- end
14
-
15
- # element path
16
- def element_path(options = nil)
17
- self.class.element_path(to_param, options || prefix_options)
18
- end
19
-
20
- def to_param
21
- attributes[:account_code]
22
- end
23
-
24
- # Override collection_path because this is a singular resource
25
- def self.collection_path(prefix_options = {}, query_options = nil)
26
- prefix_options, query_options = split_options(prefix_options) if query_options.nil?
27
- # original: "#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
28
- "#{prefix(prefix_options)}#{element_name}.#{format.extension}#{query_string(query_options)}"
29
- end
30
-
31
- end
32
-
33
- # backwards compatibility
34
- RecurlyAccountBase = AccountBase
35
- end
@@ -1,195 +0,0 @@
1
- require 'active_support/memoizable'
2
-
3
- module Recurly
4
-
5
- class Base < ActiveResource::Base
6
- extend ActiveSupport::Memoizable
7
-
8
- self.format = Recurly::Formats::XmlWithErrorsFormat.new
9
-
10
- def update_only
11
- false
12
- end
13
-
14
- def valid?
15
- self.errors.blank?
16
- end
17
-
18
- # Define #initialize with persisted for our Rails 2.3 and 3.0 friends
19
- def initialize(attributes = {}, persisted = false)
20
- @attributes = {}.with_indifferent_access
21
- @prefix_options = {}
22
- @persisted = persisted
23
- load(attributes)
24
- end
25
-
26
- # See http://github.com/rails/rails/commit/1488c6cc9e6237ce794e3c4a6201627b9fd4ca09
27
- # Errors in Rails 2.3.4 are not parsed correctly.
28
- def save
29
- if update_only
30
- update
31
- else
32
- save_without_validation
33
- end
34
- true
35
- rescue ActiveResource::ResourceInvalid => e
36
- load_errors e.response.body
37
- #raise Recurly::ResourceInvalid.new(e.response, self.errors.full_messages.join(', '))
38
- false
39
- end
40
-
41
- # patch persisted? so it looks to see if it actually is persisted
42
- def persisted?
43
- @persisted ||= false
44
- @persisted
45
- end
46
-
47
- # patch new? to be the opposite of persisted
48
- def new?
49
- !persisted?
50
- end
51
-
52
- # patched to read Errors array
53
- def load(attributes, remove_root = false)
54
- raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
55
- @prefix_options, attributes = split_options(attributes)
56
- attributes.each do |key, value|
57
- if key.to_s == 'errors' && value.is_a?(Array)
58
- load_errors_from_array(value)
59
- next
60
- end
61
- @attributes[key.to_s] =
62
- case value
63
- when Array
64
- resource = nil
65
- value.map do |attrs|
66
- if attrs.is_a?(Hash)
67
- resource ||= find_or_create_resource_for_collection(key)
68
- resource.new(attrs)
69
- else
70
- attrs.duplicable? ? attrs.dup : attrs
71
- end
72
- end
73
- when Hash
74
- resource = find_or_create_resource_for(key)
75
- resource.new(value)
76
- else
77
- value.dup rescue value
78
- end
79
- end
80
- self
81
- end
82
-
83
- # builds the object from the transparent results
84
- def from_transparent_results(response)
85
- self.load_attributes_from_response(response)
86
- self
87
- end
88
-
89
- protected
90
- # patch load_attributes_from_response so it marks result records as persisted
91
- def load_attributes_from_response(response)
92
- if (response['Content-Length'].blank? || response['Content-Length'] != "0") && !response.body.nil? && response.body.strip.size > 0
93
- load(self.class.format.decode(response.body), true)
94
- @persisted = true
95
- end
96
- end
97
-
98
- def load_errors xml
99
- load_errors_from_array(
100
- Recurly::Formats::XmlWithErrorsFormat.new.decode(xml)
101
- )
102
- rescue => e
103
- # Fallback to default errors parsing
104
- errors.from_xml xml
105
- raise
106
- end
107
-
108
- # Patched to read errors with field information
109
- def load_errors_from_array(new_errors, save_cache = false)
110
- errors.clear unless save_cache
111
- return if new_errors.nil? or new_errors.empty?
112
- humanized_attributes = Hash[self.class.known_attributes.map { |attr_name| [attr_name.humanize, attr_name] }] unless self.class.known_attributes.nil?
113
- humanized_attributes ||= Hash[@attributes.keys.map { |attr_name| [attr_name.humanize, attr_name] }]
114
- new_errors.each do |error|
115
- if error.is_a?(Hash)
116
- field = error['field']
117
- message = error['message']
118
-
119
- if field.blank?
120
- errors.add :base, message
121
- next
122
- end
123
-
124
- humanized_name = field.to_s.humanize.downcase
125
- message = message[(humanized_name.size + 1)..-1] if message[0, humanized_name.size + 1].downcase == "#{humanized_name} "
126
-
127
- # HACK: Special case nested billing errors
128
- if self.respond_to?(:credit_card) && self.credit_card && self.is_a?(Recurly::BillingInfo) && Recurly::BillingInfo::CreditCard.known_attributes.include?(field)
129
- self.credit_card.errors.add field.to_sym, message
130
- next
131
- end
132
-
133
- errors.add field.to_sym, message
134
- elsif error.is_a?(String)
135
- message = error
136
- attr_message = humanized_attributes.keys.detect do |attr_name|
137
- if message[0, attr_name.size + 1] == "#{attr_name} "
138
- errors.add humanized_attributes[attr_name], message[(attr_name.size + 1)..-1]
139
- next
140
- end
141
- end
142
-
143
- errors.add :base, message
144
- end
145
- end
146
- end
147
-
148
- private
149
- # Fix @persisted for Rails 2.3, 3.0
150
- def self.instantiate_record(record, prefix_options = {})
151
- new(record, true).tap do |resource|
152
- resource.prefix_options = prefix_options
153
- end
154
- end
155
-
156
- def handle_response(response)
157
- case response.code.to_i
158
- when 401
159
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
160
- raise(UnauthorizedAccess.new(response, message))
161
- when 403
162
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
163
- raise(ForbiddenAccess.new(response, message))
164
- when 404
165
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
166
- raise ResourceNotFound.new(response, message)
167
- when 422
168
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
169
- raise Recurly::ResourceInvalid.new(response, message)
170
- when 412
171
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
172
- raise ClientError.new(response, message)
173
- when 500
174
- message = Hash.from_xml(response.body)['errors']['error'] rescue nil
175
- raise(ServerError.new(response, message))
176
- else
177
- super
178
- end
179
- end
180
- end
181
-
182
- # backwards compatibility
183
- RecurlyBase = Base
184
- end
185
-
186
- module ActiveResource
187
- class Connection
188
- private
189
- def default_header
190
- @default_header ||= {}
191
- @default_header['User-Agent'] = "Recurly Ruby Client v#{Recurly::VERSION}"
192
- @default_header
193
- end
194
- end
195
- end