recurly 2.19.12 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +158 -110
  8. data/Rakefile +6 -0
  9. data/bin/bundle +105 -0
  10. data/bin/coderay +29 -0
  11. data/bin/console +14 -0
  12. data/bin/htmldiff +29 -0
  13. data/bin/ldiff +29 -0
  14. data/bin/pry +29 -0
  15. data/bin/rake +29 -0
  16. data/bin/rspec +29 -0
  17. data/bin/setup +8 -0
  18. data/bin/yard +29 -0
  19. data/bin/yardoc +29 -0
  20. data/bin/yri +29 -0
  21. data/lib/data/ca-certificates.crt +31 -0
  22. data/lib/recurly/client/operations.rb +935 -0
  23. data/lib/recurly/client.rb +198 -0
  24. data/lib/recurly/errors/api_errors.rb +35 -0
  25. data/lib/recurly/errors/network_errors.rb +8 -0
  26. data/lib/recurly/errors.rb +34 -0
  27. data/lib/recurly/pager.rb +119 -0
  28. data/lib/recurly/request.rb +30 -0
  29. data/lib/recurly/requests/account_acquisition_updatable.rb +22 -0
  30. data/lib/recurly/requests/account_create_only.rb +18 -0
  31. data/lib/recurly/requests/account_updatable.rb +50 -0
  32. data/lib/recurly/requests/add_on_create.rb +38 -0
  33. data/lib/recurly/requests/add_on_update.rb +38 -0
  34. data/lib/recurly/requests/address.rb +42 -0
  35. data/lib/recurly/requests/billing_info_create.rb +58 -0
  36. data/lib/recurly/requests/coupon_create_only.rb +66 -0
  37. data/lib/recurly/requests/coupon_updatable.rb +30 -0
  38. data/lib/recurly/requests/create_account.rb +62 -0
  39. data/lib/recurly/requests/create_coupon.rb +90 -0
  40. data/lib/recurly/requests/invoice_create.rb +42 -0
  41. data/lib/recurly/requests/invoice_refund.rb +30 -0
  42. data/lib/recurly/requests/line_item_create.rb +46 -0
  43. data/lib/recurly/requests/plan_create.rb +66 -0
  44. data/lib/recurly/requests/plan_update.rb +70 -0
  45. data/lib/recurly/requests/shipping_address_create.rb +58 -0
  46. data/lib/recurly/requests/shipping_address_update.rb +62 -0
  47. data/lib/recurly/requests/subscription_add_on_create.rb +22 -0
  48. data/lib/recurly/requests/subscription_change_create.rb +42 -0
  49. data/lib/recurly/requests/subscription_create.rb +86 -0
  50. data/lib/recurly/requests/subscription_update.rb +42 -0
  51. data/lib/recurly/requests/update_coupon.rb +30 -0
  52. data/lib/recurly/resource.rb +16 -1114
  53. data/lib/recurly/resources/account.rb +86 -0
  54. data/lib/recurly/resources/account_acquisition.rb +42 -0
  55. data/lib/recurly/resources/account_balance.rb +22 -0
  56. data/lib/recurly/resources/account_note.rb +30 -0
  57. data/lib/recurly/resources/add_on.rb +62 -0
  58. data/lib/recurly/resources/address.rb +42 -0
  59. data/lib/recurly/resources/billing_info.rb +62 -0
  60. data/lib/recurly/resources/coupon.rb +110 -0
  61. data/lib/recurly/resources/coupon_discount.rb +22 -0
  62. data/lib/recurly/resources/coupon_redemption.rb +46 -0
  63. data/lib/recurly/resources/credit_payment.rb +62 -0
  64. data/lib/recurly/resources/error.rb +18 -0
  65. data/lib/recurly/resources/error_may_have_transaction.rb +22 -0
  66. data/lib/recurly/resources/invoice.rb +138 -0
  67. data/lib/recurly/resources/invoice_collection.rb +18 -0
  68. data/lib/recurly/resources/line_item.rb +166 -0
  69. data/lib/recurly/resources/plan.rb +86 -0
  70. data/lib/recurly/resources/settings.rb +18 -0
  71. data/lib/recurly/resources/shipping_address.rb +74 -0
  72. data/lib/recurly/resources/site.rb +46 -0
  73. data/lib/recurly/resources/subscription.rb +134 -0
  74. data/lib/recurly/resources/subscription_add_on.rb +42 -0
  75. data/lib/recurly/resources/subscription_change.rb +54 -0
  76. data/lib/recurly/resources/tax_info.rb +18 -0
  77. data/lib/recurly/resources/transaction.rb +146 -0
  78. data/lib/recurly/resources/unique_coupon_code.rb +38 -0
  79. data/lib/recurly/resources/user.rb +38 -0
  80. data/lib/recurly/schema/json_deserializer.rb +53 -0
  81. data/lib/recurly/schema/json_parser.rb +71 -0
  82. data/lib/recurly/schema/request_caster.rb +66 -0
  83. data/lib/recurly/schema/schema_factory.rb +50 -0
  84. data/lib/recurly/schema/schema_validator.rb +125 -0
  85. data/lib/recurly/schema.rb +114 -0
  86. data/lib/recurly/version.rb +1 -10
  87. data/lib/recurly.rb +14 -167
  88. data/recurly.gemspec +32 -0
  89. data/scripts/build +4 -0
  90. data/scripts/clean +6 -0
  91. data/scripts/test +3 -0
  92. metadata +124 -273
  93. data/lib/recurly/account.rb +0 -230
  94. data/lib/recurly/account_acquisition.rb +0 -27
  95. data/lib/recurly/account_balance.rb +0 -23
  96. data/lib/recurly/add_on.rb +0 -52
  97. data/lib/recurly/address.rb +0 -25
  98. data/lib/recurly/adjustment.rb +0 -98
  99. data/lib/recurly/api/errors.rb +0 -208
  100. data/lib/recurly/api/net_http_adapter.rb +0 -111
  101. data/lib/recurly/api.rb +0 -110
  102. data/lib/recurly/billing_info.rb +0 -134
  103. data/lib/recurly/business_entity.rb +0 -33
  104. data/lib/recurly/coupon.rb +0 -136
  105. data/lib/recurly/credit_payment.rb +0 -32
  106. data/lib/recurly/currency_percentage_tier.rb +0 -17
  107. data/lib/recurly/custom_field.rb +0 -15
  108. data/lib/recurly/custom_field_definition.rb +0 -14
  109. data/lib/recurly/customer_permission.rb +0 -10
  110. data/lib/recurly/delivery.rb +0 -19
  111. data/lib/recurly/dunning_campaign.rb +0 -30
  112. data/lib/recurly/dunning_cycle.rb +0 -18
  113. data/lib/recurly/entitlement.rb +0 -19
  114. data/lib/recurly/error.rb +0 -13
  115. data/lib/recurly/external_account.rb +0 -17
  116. data/lib/recurly/external_charge.rb +0 -20
  117. data/lib/recurly/external_invoice.rb +0 -27
  118. data/lib/recurly/external_payment_phase.rb +0 -27
  119. data/lib/recurly/external_product.rb +0 -34
  120. data/lib/recurly/external_product_reference.rb +0 -18
  121. data/lib/recurly/external_subscription.rb +0 -51
  122. data/lib/recurly/gateway_attribute.rb +0 -10
  123. data/lib/recurly/general_ledger_account.rb +0 -16
  124. data/lib/recurly/gift_card.rb +0 -85
  125. data/lib/recurly/helper.rb +0 -51
  126. data/lib/recurly/invoice.rb +0 -322
  127. data/lib/recurly/invoice_collection.rb +0 -14
  128. data/lib/recurly/invoice_template.rb +0 -14
  129. data/lib/recurly/item.rb +0 -36
  130. data/lib/recurly/js.rb +0 -14
  131. data/lib/recurly/juris_detail.rb +0 -15
  132. data/lib/recurly/measured_unit.rb +0 -16
  133. data/lib/recurly/money.rb +0 -120
  134. data/lib/recurly/note.rb +0 -14
  135. data/lib/recurly/percentage_tier.rb +0 -17
  136. data/lib/recurly/performance_obligation.rb +0 -15
  137. data/lib/recurly/plan.rb +0 -58
  138. data/lib/recurly/plan_ramp_interval.rb +0 -10
  139. data/lib/recurly/purchase.rb +0 -238
  140. data/lib/recurly/redemption.rb +0 -46
  141. data/lib/recurly/resource/association.rb +0 -16
  142. data/lib/recurly/resource/errors.rb +0 -20
  143. data/lib/recurly/resource/pager.rb +0 -313
  144. data/lib/recurly/rev_rec.rb +0 -18
  145. data/lib/recurly/shipping_address.rb +0 -26
  146. data/lib/recurly/shipping_fee.rb +0 -17
  147. data/lib/recurly/shipping_method.rb +0 -13
  148. data/lib/recurly/sub_add_on_percentage_tier.rb +0 -17
  149. data/lib/recurly/subscription/add_ons.rb +0 -82
  150. data/lib/recurly/subscription.rb +0 -372
  151. data/lib/recurly/subscription_add_on.rb +0 -64
  152. data/lib/recurly/subscription_ramp_interval.rb +0 -12
  153. data/lib/recurly/tax_detail.rb +0 -18
  154. data/lib/recurly/tax_type.rb +0 -13
  155. data/lib/recurly/tier.rb +0 -18
  156. data/lib/recurly/transaction/errors.rb +0 -119
  157. data/lib/recurly/transaction.rb +0 -132
  158. data/lib/recurly/usage.rb +0 -29
  159. data/lib/recurly/verify.rb +0 -12
  160. data/lib/recurly/webhook/account_notification.rb +0 -13
  161. data/lib/recurly/webhook/billing_info_update_failed_notification.rb +0 -6
  162. data/lib/recurly/webhook/billing_info_updated_notification.rb +0 -6
  163. data/lib/recurly/webhook/canceled_account_notification.rb +0 -6
  164. data/lib/recurly/webhook/canceled_gift_card_notification.rb +0 -6
  165. data/lib/recurly/webhook/canceled_subscription_notification.rb +0 -6
  166. data/lib/recurly/webhook/closed_credit_invoice_notification.rb +0 -6
  167. data/lib/recurly/webhook/closed_invoice_notification.rb +0 -6
  168. data/lib/recurly/webhook/credit_payment_notification.rb +0 -12
  169. data/lib/recurly/webhook/deactivated_item_notification.rb +0 -6
  170. data/lib/recurly/webhook/deleted_shipping_address_notification.rb +0 -6
  171. data/lib/recurly/webhook/dunning_notification.rb +0 -14
  172. data/lib/recurly/webhook/expired_subscription_notification.rb +0 -6
  173. data/lib/recurly/webhook/failed_charge_invoice_notification.rb +0 -6
  174. data/lib/recurly/webhook/failed_payment_notification.rb +0 -6
  175. data/lib/recurly/webhook/fraud_info_updated_notification.rb +0 -6
  176. data/lib/recurly/webhook/gift_card_notification.rb +0 -8
  177. data/lib/recurly/webhook/invoice_notification.rb +0 -12
  178. data/lib/recurly/webhook/item_notification.rb +0 -7
  179. data/lib/recurly/webhook/low_balance_gift_card_notification.rb +0 -6
  180. data/lib/recurly/webhook/new_account_notification.rb +0 -6
  181. data/lib/recurly/webhook/new_charge_invoice_notification.rb +0 -6
  182. data/lib/recurly/webhook/new_credit_invoice_notification.rb +0 -6
  183. data/lib/recurly/webhook/new_credit_payment_notification.rb +0 -6
  184. data/lib/recurly/webhook/new_dunning_event_notification.rb +0 -6
  185. data/lib/recurly/webhook/new_invoice_notification.rb +0 -6
  186. data/lib/recurly/webhook/new_item_notification.rb +0 -6
  187. data/lib/recurly/webhook/new_shipping_address_notification.rb +0 -6
  188. data/lib/recurly/webhook/new_subscription_notification.rb +0 -6
  189. data/lib/recurly/webhook/new_usage_notification.rb +0 -8
  190. data/lib/recurly/webhook/notification.rb +0 -18
  191. data/lib/recurly/webhook/paid_charge_invoice_notification.rb +0 -6
  192. data/lib/recurly/webhook/past_due_charge_invoice_notification.rb +0 -6
  193. data/lib/recurly/webhook/past_due_invoice_notification.rb +0 -6
  194. data/lib/recurly/webhook/paused_subscription_renewal_notification.rb +0 -6
  195. data/lib/recurly/webhook/prerenewal_notification.rb +0 -6
  196. data/lib/recurly/webhook/processing_charge_invoice_notification.rb +0 -6
  197. data/lib/recurly/webhook/processing_credit_invoice_notification.rb +0 -6
  198. data/lib/recurly/webhook/processing_invoice_notification.rb +0 -6
  199. data/lib/recurly/webhook/processing_payment_notification.rb +0 -6
  200. data/lib/recurly/webhook/purchased_gift_card_notification.rb +0 -7
  201. data/lib/recurly/webhook/reactivated_account_notification.rb +0 -6
  202. data/lib/recurly/webhook/reactivated_item_notification.rb +0 -6
  203. data/lib/recurly/webhook/redeemed_gift_card_notification.rb +0 -7
  204. data/lib/recurly/webhook/regenerated_gift_card_notification.rb +0 -6
  205. data/lib/recurly/webhook/renewed_subscription_notification.rb +0 -6
  206. data/lib/recurly/webhook/reopened_charge_invoice_notification.rb +0 -6
  207. data/lib/recurly/webhook/reopened_credit_invoice_notification.rb +0 -6
  208. data/lib/recurly/webhook/scheduled_payment_notification.rb +0 -6
  209. data/lib/recurly/webhook/scheduled_subscription_pause_notification.rb +0 -6
  210. data/lib/recurly/webhook/scheduled_subscription_update_notification.rb +0 -6
  211. data/lib/recurly/webhook/subscription_notification.rb +0 -12
  212. data/lib/recurly/webhook/subscription_pause_canceled_notification.rb +0 -6
  213. data/lib/recurly/webhook/subscription_pause_modified_notification.rb +0 -6
  214. data/lib/recurly/webhook/subscription_paused_notification.rb +0 -6
  215. data/lib/recurly/webhook/subscription_resumed_notification.rb +0 -6
  216. data/lib/recurly/webhook/successful_payment_notification.rb +0 -6
  217. data/lib/recurly/webhook/successful_refund_notification.rb +0 -6
  218. data/lib/recurly/webhook/transaction_authorized_notification.rb +0 -6
  219. data/lib/recurly/webhook/transaction_notification.rb +0 -12
  220. data/lib/recurly/webhook/transaction_status_updated_notification.rb +0 -6
  221. data/lib/recurly/webhook/updated_account_notification.rb +0 -6
  222. data/lib/recurly/webhook/updated_balance_gift_card_notification.rb +0 -7
  223. data/lib/recurly/webhook/updated_gift_card_notification.rb +0 -6
  224. data/lib/recurly/webhook/updated_invoice_notification.rb +0 -6
  225. data/lib/recurly/webhook/updated_item_notification.rb +0 -6
  226. data/lib/recurly/webhook/updated_shipping_address_notification.rb +0 -6
  227. data/lib/recurly/webhook/updated_subscription_notification.rb +0 -6
  228. data/lib/recurly/webhook/void_payment_notification.rb +0 -6
  229. data/lib/recurly/webhook/voided_credit_invoice_notification.rb +0 -6
  230. data/lib/recurly/webhook/voided_credit_payment_notification.rb +0 -6
  231. data/lib/recurly/webhook.rb +0 -113
  232. data/lib/recurly/xml/nokogiri.rb +0 -60
  233. data/lib/recurly/xml/rexml.rb +0 -52
  234. data/lib/recurly/xml.rb +0 -122
@@ -0,0 +1,198 @@
1
+ require 'faraday'
2
+ require 'logger'
3
+ require_relative './schema/json_parser'
4
+
5
+ module Recurly
6
+ class Client
7
+ require_relative './client/operations'
8
+
9
+ BASE_URL = "https://partner-api.recurly.com/"
10
+
11
+ # The last result of the *X-RateLimit-Limit* header
12
+ # @return [Integer] The rate limit applied to this client.
13
+ attr_reader :rate_limit
14
+
15
+ # The last result of the *X-RateLimit-Remaining* header
16
+ # @return [Integer] The number of remaining requests, decrements per request.
17
+ attr_reader :rate_limit_remaining
18
+
19
+ # The last result of the *X-RateLimit-Reset* header
20
+ # @return [DateTime] The DateTime in which the request count will be reset.
21
+ attr_reader :rate_limit_reset
22
+
23
+ # Initialize a client. It requires an API key.
24
+ #
25
+ # @example
26
+ # API_KEY = '83749879bbde395b5fe0cc1a5abf8e5'
27
+ # SITE_ID = 'dqzlv9shi7wa'
28
+ # client = Recurly::Client.new(site_id: SITE_ID, api_key: API_KEY)
29
+ # # You can optionally use the subdomain instead of the site id
30
+ # client = Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY)
31
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
32
+ # @example
33
+ # # You can also pass the initializer a block. This will give you
34
+ # # a client scoped for just that block
35
+ # Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY) do |client|
36
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
37
+ # end
38
+ # @example
39
+ # # If you only plan on using the client for more than one site,
40
+ # # you should initialize a new client for each site.
41
+ #
42
+ # # Give a `site_id`
43
+ # client = Recurly::Client.new(api_key: API_KEY, site_id: SITE_ID)
44
+ # # Or use the subdomain
45
+ # client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-dev')
46
+ #
47
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
48
+ #
49
+ # # you should create a new client to connect to another site
50
+ # client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-prod')
51
+ # sub = client.get_subscription(subscription_id: 'abcd7890')
52
+ #
53
+ # @param api_key [String] The private API key
54
+ # @param site_id [String] The site you wish to be scoped to.
55
+ # @param subdomain [String] Optional subdomain for the site you wish to be scoped to. Providing this makes all the `site_id` parameters optional.
56
+ def initialize(api_key:, site_id: nil, subdomain: nil, **options)
57
+ if site_id
58
+ @site_id = site_id
59
+ elsif subdomain
60
+ @site_id = "subdomain-#{subdomain}"
61
+ else
62
+ raise ArgumentError, "You must pass a site_id or subdomain argument to initialize the Client"
63
+ end
64
+
65
+ @log_level = options[:log_level] || Logger::WARN
66
+ @logger = Logger.new(STDOUT)
67
+ @logger.level = @log_level
68
+
69
+ @conn = Faraday.new(url: BASE_URL) do |faraday|
70
+ if @log_level == Logger::INFO
71
+ faraday.response :logger
72
+ end
73
+ faraday.basic_auth(api_key, '')
74
+ faraday.adapter :net_http do |http| # yields Net::HTTP
75
+ # Let's not use the bundled cert in production yet
76
+ # but we will use these certs for any other staging or dev environment
77
+ unless BASE_URL.end_with?('.recurly.com')
78
+ http.ca_file = File.join(File.dirname(__FILE__), '../data/ca-certificates.crt')
79
+ end
80
+ http.use_ssl = true
81
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
82
+ http.open_timeout = 50
83
+ http.read_timeout = 60
84
+ http.keep_alive_timeout = 60
85
+ end
86
+ end
87
+
88
+ # TODO this is undocumented until we finalize it
89
+ @extra_headers = options[:headers] || {}
90
+
91
+ # execute block with this client if given
92
+ yield(self) if block_given?
93
+ end
94
+
95
+ def next_page(pager)
96
+ run_request(:get, pager.next, nil, headers)
97
+ end
98
+
99
+ protected
100
+
101
+ def pager(path, **options)
102
+ Pager.new(client: self, path: path, options: options)
103
+ end
104
+
105
+ def get(path, **options)
106
+ response = run_request(:get, path, options.compact, headers)
107
+ raise_api_error!(response) if response.status != 200
108
+ JSONParser.parse(self, response.body)
109
+ rescue Faraday::ClientError => ex
110
+ raise_network_error!(ex)
111
+ end
112
+
113
+ def post(path, request_data, request_class, **options)
114
+ request = request_class.new(request_data)
115
+ request.validate!
116
+ logger.info("POST BODY #{JSON.dump(request_data)}")
117
+ response = run_request(:post, path, JSON.dump(request.attributes), headers)
118
+ raise_api_error!(response) if response.status != 201
119
+ JSONParser.parse(self, response.body)
120
+ rescue Faraday::ClientError => ex
121
+ raise_network_error!(ex)
122
+ end
123
+
124
+ def put(path, request_data, request_class, **options)
125
+ request = request_class.new(request_data)
126
+ request.validate!
127
+ logger.info("PUT BODY #{JSON.dump(request_data)}")
128
+ response = run_request(:put, path, JSON.dump(request_data), headers)
129
+ raise_api_error!(response) if ![200, 201].include?(response.status)
130
+ JSONParser.parse(self, response.body)
131
+ rescue Faraday::ClientError => ex
132
+ raise_network_error!(ex)
133
+ end
134
+
135
+ def delete(path, **options)
136
+ response = run_request(:delete, path, options.compact, headers)
137
+ raise_api_error!(response) if ![200, 201].include?(response.status)
138
+ JSONParser.parse(self, response.body)
139
+ rescue Faraday::ClientError => ex
140
+ raise_network_error!(ex)
141
+ end
142
+
143
+ protected
144
+
145
+ # Used by the operations.rb file to interpolate paths
146
+ attr_reader :site_id
147
+
148
+ private
149
+
150
+ # @return [Logger]
151
+ attr_reader :logger
152
+
153
+ def run_request(method, url, body, headers)
154
+ read_headers @conn.run_request(method, url, body, headers)
155
+ end
156
+
157
+ def raise_network_error!(ex)
158
+ error_class = case ex
159
+ when Faraday::TimeoutError
160
+ Errors::TimeoutError
161
+ when Faraday::ConnectionFailed
162
+ Errors::ConnectionFailed
163
+ when Faraday::SSLError
164
+ Errors::SSLError
165
+ else
166
+ Errors::NetworkError
167
+ end
168
+
169
+ raise error_class, ex.message
170
+ end
171
+
172
+ def raise_api_error!(response)
173
+ error = JSONParser.parse(self, response.body)
174
+ error_class = Errors::APIError.error_class(error.type)
175
+ raise error_class.new(response, error)
176
+ end
177
+
178
+ def read_headers(response)
179
+ @rate_limit = response.headers['x-ratelimit-limit'].to_i
180
+ @rate_limit_remaining = response.headers['x-ratelimit-remaining'].to_i
181
+ @rate_limit_reset = Time.at(response.headers['x-ratelimit-reset'].to_i).to_datetime
182
+ response
183
+ end
184
+
185
+ def headers
186
+ {
187
+ 'Accept' => "application/vnd.recurly.#{api_version}", # got this method from operations.rb
188
+ 'Content-Type' => 'application/json',
189
+ 'User-Agent' => "Recurly/#{VERSION}; #{RUBY_DESCRIPTION}"
190
+ }.merge(@extra_headers)
191
+ end
192
+
193
+ def interpolate_path(path, **options)
194
+ path = path.gsub("{", "%{")
195
+ path % options
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,35 @@
1
+ module Recurly
2
+ module Errors
3
+ class BadRequestError < Errors::APIError; end
4
+
5
+ class InternalServerError < Errors::APIError; end
6
+
7
+ class ImmutableSubscriptionError < Errors::APIError; end
8
+
9
+ class InvalidApiKeyError < Errors::APIError; end
10
+
11
+ class InvalidApiVersionError < Errors::APIError; end
12
+
13
+ class InvalidContentTypeError < Errors::APIError; end
14
+
15
+ class InvalidPermissionsError < Errors::APIError; end
16
+
17
+ class InvalidTokenError < Errors::APIError; end
18
+
19
+ class NotFoundError < Errors::APIError; end
20
+
21
+ class SimultaneousRequestError < Errors::APIError; end
22
+
23
+ class TransactionError < Errors::APIError; end
24
+
25
+ class UnauthorizedError < Errors::APIError; end
26
+
27
+ class UnavailableInApiVersionError < Errors::APIError; end
28
+
29
+ class UnknownApiVersionError < Errors::APIError; end
30
+
31
+ class ValidationError < Errors::APIError; end
32
+
33
+ class MissingFeatureError < Errors::APIError; end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ module Recurly
2
+ module Errors
3
+ class NetworkError < StandardError; end
4
+ class TimeoutError < NetworkError; end
5
+ class ConnectionFailed < NetworkError; end
6
+ class SSLError < NetworkError; end
7
+ end
8
+ end
@@ -0,0 +1,34 @@
1
+ module Recurly
2
+ module Errors
3
+ class APIError < StandardError
4
+ # @!attribute recurly_error
5
+ # @return [Recurly::Resources::Error] The {Recurly::Resources::Error} object
6
+ attr_reader :recurly_error
7
+
8
+ # Looks up an Error class by name
9
+ # @example
10
+ # Errors.error_class('BadRequestError')
11
+ # #=> Errors::BadRequestError
12
+ # @param error_key [String]
13
+ # @return [Errors::APIError,Errors::NetworkError]
14
+ def self.error_class(error_key)
15
+ class_name = error_key.split('_').map(&:capitalize).join
16
+ class_name += "Error" unless class_name.end_with?("Error")
17
+ Errors.const_get(class_name)
18
+ end
19
+
20
+ def initialize(response, error)
21
+ super("#{self.class.name}: #{error.message}")
22
+ @response = response
23
+ @recurly_error = error
24
+ end
25
+
26
+ def status_code
27
+ @response.status
28
+ end
29
+ end
30
+ end
31
+
32
+ require_relative "./errors/api_errors"
33
+ require_relative "./errors/network_errors"
34
+ end
@@ -0,0 +1,119 @@
1
+ module Recurly
2
+ class Pager
3
+ attr_accessor :client
4
+ attr_reader :data, :next
5
+
6
+ def initialize(client:, path:, options: {})
7
+ @client = client
8
+ @path = path
9
+ @options = options
10
+ @next = build_path(@path, @options)
11
+ end
12
+
13
+ # Enumerates each "page" from the server.
14
+ # This method yields a given block with the array of items
15
+ # in the page `data` and the page number the pagination is on
16
+ # `page_num` which is 0-indexed.
17
+ #
18
+ # @example
19
+ # plans = client.list_plans()
20
+ # plans.each_page do |data|
21
+ # data.each do |plan|
22
+ # puts "Plan: #{plan.id}"
23
+ # end
24
+ # end
25
+ # @example
26
+ # plans = client.list_plans()
27
+ # plans.each_page.each_with_index do |data, page_num|
28
+ # puts "Page Number: #{page_num}"
29
+ # data.each do |plan|
30
+ # puts "Plan: #{plan.id}"
31
+ # end
32
+ # end
33
+ def each_page(&block)
34
+ if block_given?
35
+ page_enumerator.each(&block)
36
+ else
37
+ page_enumerator
38
+ end
39
+ end
40
+
41
+ # Enumerates each item on the server. Each item is yielded to the
42
+ # block presenting the effect of a continuous stream of items.
43
+ # In reality, the pager is fetching blocks of data (pages) under the hood.
44
+ # This method yields a given block with the next item to process.
45
+ #
46
+ # @example
47
+ # plans = client.list_plans()
48
+ # plans.each do |plan|
49
+ # puts "Plan: #{plan.id}"
50
+ # end
51
+ # @example
52
+ # plans = client.list_plans()
53
+ # plans.each.each_with_index do |plan, idx|
54
+ # puts "Plan #{idx}: #{plan.id}"
55
+ # end
56
+ def each(&block)
57
+ if block_given?
58
+ item_enumerator.each(&block)
59
+ else
60
+ item_enumerator
61
+ end
62
+ end
63
+
64
+ def has_more?
65
+ !!@has_more
66
+ end
67
+
68
+ def requires_client?
69
+ true
70
+ end
71
+
72
+ private
73
+
74
+ def from_json(data)
75
+ @data = data['data'].map do |resource_data|
76
+ JSONParser.from_json(resource_data)
77
+ end
78
+ @next = data['next']
79
+ @has_more = data['has_more']
80
+ end
81
+
82
+ def item_enumerator
83
+ Enumerator.new do |yielder|
84
+ page_enumerator.each do |data|
85
+ data.each do |item|
86
+ yielder << item
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def page_enumerator
93
+ Enumerator.new do |yielder|
94
+ loop do
95
+ fetch_next!
96
+ yielder << data
97
+ unless has_more?
98
+ rewind!
99
+ break
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def fetch_next!
106
+ response = @client.next_page(self)
107
+ from_json(JSON.parse(response.body))
108
+ end
109
+
110
+ def rewind!
111
+ @data = []
112
+ @next = build_path(@path, @options)
113
+ end
114
+
115
+ def build_path(path, options)
116
+ "#{path}?#{URI.encode_www_form(options)}"
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,30 @@
1
+ module Recurly
2
+ # This class represents a request to Recurly.
3
+ # It's used to validate requests data as well as
4
+ # cast and serialize the request data to JSON.
5
+ class Request
6
+ extend Schema::SchemaFactory
7
+ extend Schema::RequestCaster
8
+ include Schema::SchemaValidator
9
+
10
+ attr_reader :attributes
11
+
12
+ def ==(other_resource)
13
+ self.attributes == other_resource.attributes
14
+ end
15
+
16
+ protected
17
+
18
+ def initialize(attributes = {})
19
+ @attributes = self.class.cast(attributes.clone)
20
+ end
21
+
22
+ def to_s
23
+ self.inspect
24
+ end
25
+
26
+ def schema
27
+ self.class.schema
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ module Recurly
2
+ module Requests
3
+ class AccountAcquisitionUpdatable < Request
4
+
5
+ # @!attribute campaign
6
+ # @return [String] An arbitrary identifier for the marketing campaign that led to the acquisition of this account.
7
+ define_attribute :campaign, String
8
+
9
+ # @!attribute channel
10
+ # @return [String] The channel through which the account was acquired.
11
+ define_attribute :channel, String, {:enum => ["referral", "social_media", "email", "paid_search", "organic_search", "direct_traffic", "marketing_content", "blog", "events", "outbound_sales", "advertising", "public_relations", "other"]}
12
+
13
+ # @!attribute cost
14
+ # @return [Hash] Account balance
15
+ define_attribute :cost, Hash
16
+
17
+ # @!attribute subchannel
18
+ # @return [String] An arbitrary subchannel string representing a distinction/subcategory within a broader channel.
19
+ define_attribute :subchannel, String
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Recurly
2
+ module Requests
3
+ class AccountCreateOnly < Request
4
+
5
+ # @!attribute acquisition
6
+ # @return [AccountAcquisitionUpdatable]
7
+ define_attribute :acquisition, :AccountAcquisitionUpdatable
8
+
9
+ # @!attribute code
10
+ # @return [String] The unique identifier of the account. This cannot be changed once the account is created.
11
+ define_attribute :code, String
12
+
13
+ # @!attribute shipping_addresses
14
+ # @return [Array[ShippingAddressCreate]]
15
+ define_attribute :shipping_addresses, Array, {:item_type => :ShippingAddressCreate}
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ module Recurly
2
+ module Requests
3
+ class AccountUpdatable < Request
4
+
5
+ # @!attribute address
6
+ # @return [Address]
7
+ define_attribute :address, :Address
8
+
9
+ # @!attribute billing_info
10
+ # @return [BillingInfoCreate]
11
+ define_attribute :billing_info, :BillingInfoCreate
12
+
13
+ # @!attribute cc_emails
14
+ # @return [String] Additional email address that should receive account correspondence. These should be separated only by commas. These CC emails will receive all emails that the `email` field also receives.
15
+ define_attribute :cc_emails, String
16
+
17
+ # @!attribute company
18
+ # @return [String]
19
+ define_attribute :company, String
20
+
21
+ # @!attribute email
22
+ # @return [String] The email address used for communicating with this customer. The customer will also use this email address to log into your hosted account management pages. This value does not need to be unique.
23
+ define_attribute :email, String
24
+
25
+ # @!attribute first_name
26
+ # @return [String]
27
+ define_attribute :first_name, String
28
+
29
+ # @!attribute last_name
30
+ # @return [String]
31
+ define_attribute :last_name, String
32
+
33
+ # @!attribute preferred_locale
34
+ # @return [String] Used to determine the language and locale of emails sent on behalf of the merchant to the customer. The list of locales is restricted to those the merchant has enabled on the site.
35
+ define_attribute :preferred_locale, String, {:enum => ["da-DK", "de-CH", "de-DE", "en-AU", "en-CA", "en-GB", "en-NZ", "en-US", "es-ES", "es-MX", "es-US", "fr-CA", "fr-FR", "hi-IN", "ja-JP", "nl-BE", "nl-NL", "pt-BR", "pt-PT", "ru-RU", "tr-TR", "zh-CN"]}
36
+
37
+ # @!attribute tax_exempt
38
+ # @return [Boolean] The tax status of the account. `true` exempts tax on the account, `false` applies tax on the account.
39
+ define_attribute :tax_exempt, :Boolean
40
+
41
+ # @!attribute username
42
+ # @return [String] A secondary value for the account.
43
+ define_attribute :username, String
44
+
45
+ # @!attribute vat_number
46
+ # @return [String] The VAT number of the account (to avoid having the VAT applied). This is only used for manually collected invoices.
47
+ define_attribute :vat_number, String
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,38 @@
1
+ module Recurly
2
+ module Requests
3
+ class AddOnCreate < Request
4
+
5
+ # @!attribute accounting_code
6
+ # @return [String] Accounting code for invoice line items for this add-on. If no value is provided, it defaults to add-on's code.
7
+ define_attribute :accounting_code, String
8
+
9
+ # @!attribute code
10
+ # @return [String] The unique identifier for the add-on within its plan.
11
+ define_attribute :code, String
12
+
13
+ # @!attribute currencies
14
+ # @return [Array[String]] Add-on pricing
15
+ define_attribute :currencies, Array, {:item_type => String}
16
+
17
+ # @!attribute default_quantity
18
+ # @return [Integer] Default quantity for the hosted pages.
19
+ define_attribute :default_quantity, Integer
20
+
21
+ # @!attribute display_quantity
22
+ # @return [Boolean] Determines if the quantity field is displayed on the hosted pages for the add-on.
23
+ define_attribute :display_quantity, :Boolean
24
+
25
+ # @!attribute name
26
+ # @return [String] Describes your add-on and will appear in subscribers' invoices.
27
+ define_attribute :name, String
28
+
29
+ # @!attribute [r] plan_id
30
+ # @return [String] Plan ID
31
+ define_attribute :plan_id, String, {:read_only => true}
32
+
33
+ # @!attribute tax_code
34
+ # @return [String] Optional field for EU VAT merchants and Avalara AvaTax Pro merchants. If you are using Recurly's EU VAT feature, you can use values of 'unknown', 'physical', or 'digital'. If you have your own AvaTax account configured, you can use Avalara tax codes to assign custom tax rules.
35
+ define_attribute :tax_code, String
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module Recurly
2
+ module Requests
3
+ class AddOnUpdate < Request
4
+
5
+ # @!attribute accounting_code
6
+ # @return [String] Accounting code for invoice line items for this add-on. If no value is provided, it defaults to add-on's code.
7
+ define_attribute :accounting_code, String
8
+
9
+ # @!attribute code
10
+ # @return [String] The unique identifier for the add-on within its plan.
11
+ define_attribute :code, String
12
+
13
+ # @!attribute currencies
14
+ # @return [Array[String]] Add-on pricing
15
+ define_attribute :currencies, Array, {:item_type => String}
16
+
17
+ # @!attribute default_quantity
18
+ # @return [Integer] Default quantity for the hosted pages.
19
+ define_attribute :default_quantity, Integer
20
+
21
+ # @!attribute display_quantity
22
+ # @return [Boolean] Determines if the quantity field is displayed on the hosted pages for the add-on.
23
+ define_attribute :display_quantity, :Boolean
24
+
25
+ # @!attribute [r] id
26
+ # @return [String] Add-on ID
27
+ define_attribute :id, String, {:read_only => true}
28
+
29
+ # @!attribute name
30
+ # @return [String] Describes your add-on and will appear in subscribers' invoices.
31
+ define_attribute :name, String
32
+
33
+ # @!attribute tax_code
34
+ # @return [String] Optional field for EU VAT merchants and Avalara AvaTax Pro merchants. If you are using Recurly's EU VAT feature, you can use values of 'unknown', 'physical', or 'digital'. If you have your own AvaTax account configured, you can use Avalara tax codes to assign custom tax rules.
35
+ define_attribute :tax_code, String
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ module Recurly
2
+ module Requests
3
+ class Address < Request
4
+
5
+ # @!attribute city
6
+ # @return [String] City
7
+ define_attribute :city, String
8
+
9
+ # @!attribute country
10
+ # @return [String] Country, 2-letter ISO code.
11
+ define_attribute :country, String
12
+
13
+ # @!attribute first_name
14
+ # @return [String] First name
15
+ define_attribute :first_name, String
16
+
17
+ # @!attribute last_name
18
+ # @return [String] Last name
19
+ define_attribute :last_name, String
20
+
21
+ # @!attribute phone
22
+ # @return [String] Phone number
23
+ define_attribute :phone, String
24
+
25
+ # @!attribute postal_code
26
+ # @return [String] Zip or postal code.
27
+ define_attribute :postal_code, String
28
+
29
+ # @!attribute region
30
+ # @return [String] State or province.
31
+ define_attribute :region, String
32
+
33
+ # @!attribute street1
34
+ # @return [String] Street 1
35
+ define_attribute :street1, String
36
+
37
+ # @!attribute street2
38
+ # @return [String] Street 2
39
+ define_attribute :street2, String
40
+ end
41
+ end
42
+ end