recurly 2.18.22 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +158 -110
- data/Rakefile +6 -0
- data/bin/bundle +105 -0
- data/bin/coderay +29 -0
- data/bin/console +14 -0
- data/bin/htmldiff +29 -0
- data/bin/ldiff +29 -0
- data/bin/pry +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/setup +8 -0
- data/bin/yard +29 -0
- data/bin/yardoc +29 -0
- data/bin/yri +29 -0
- data/lib/data/ca-certificates.crt +31 -0
- data/lib/recurly/client/operations.rb +935 -0
- data/lib/recurly/client.rb +198 -0
- data/lib/recurly/errors/api_errors.rb +35 -0
- data/lib/recurly/errors/network_errors.rb +8 -0
- data/lib/recurly/errors.rb +34 -0
- data/lib/recurly/pager.rb +119 -0
- data/lib/recurly/request.rb +30 -0
- data/lib/recurly/requests/account_acquisition_updatable.rb +22 -0
- data/lib/recurly/requests/account_create_only.rb +18 -0
- data/lib/recurly/requests/account_updatable.rb +50 -0
- data/lib/recurly/requests/add_on_create.rb +38 -0
- data/lib/recurly/requests/add_on_update.rb +38 -0
- data/lib/recurly/requests/address.rb +42 -0
- data/lib/recurly/requests/billing_info_create.rb +58 -0
- data/lib/recurly/requests/coupon_create_only.rb +66 -0
- data/lib/recurly/requests/coupon_updatable.rb +30 -0
- data/lib/recurly/requests/create_account.rb +62 -0
- data/lib/recurly/requests/create_coupon.rb +90 -0
- data/lib/recurly/requests/invoice_create.rb +42 -0
- data/lib/recurly/requests/invoice_refund.rb +30 -0
- data/lib/recurly/requests/line_item_create.rb +46 -0
- data/lib/recurly/requests/plan_create.rb +66 -0
- data/lib/recurly/requests/plan_update.rb +70 -0
- data/lib/recurly/requests/shipping_address_create.rb +58 -0
- data/lib/recurly/requests/shipping_address_update.rb +62 -0
- data/lib/recurly/requests/subscription_add_on_create.rb +22 -0
- data/lib/recurly/requests/subscription_change_create.rb +42 -0
- data/lib/recurly/requests/subscription_create.rb +86 -0
- data/lib/recurly/requests/subscription_update.rb +42 -0
- data/lib/recurly/requests/update_coupon.rb +30 -0
- data/lib/recurly/resource.rb +16 -1103
- data/lib/recurly/resources/account.rb +86 -0
- data/lib/recurly/resources/account_acquisition.rb +42 -0
- data/lib/recurly/resources/account_balance.rb +22 -0
- data/lib/recurly/resources/account_note.rb +30 -0
- data/lib/recurly/resources/add_on.rb +62 -0
- data/lib/recurly/resources/address.rb +42 -0
- data/lib/recurly/resources/billing_info.rb +62 -0
- data/lib/recurly/resources/coupon.rb +110 -0
- data/lib/recurly/resources/coupon_discount.rb +22 -0
- data/lib/recurly/resources/coupon_redemption.rb +46 -0
- data/lib/recurly/resources/credit_payment.rb +62 -0
- data/lib/recurly/resources/error.rb +18 -0
- data/lib/recurly/resources/error_may_have_transaction.rb +22 -0
- data/lib/recurly/resources/invoice.rb +138 -0
- data/lib/recurly/resources/invoice_collection.rb +18 -0
- data/lib/recurly/resources/line_item.rb +166 -0
- data/lib/recurly/resources/plan.rb +86 -0
- data/lib/recurly/resources/settings.rb +18 -0
- data/lib/recurly/resources/shipping_address.rb +74 -0
- data/lib/recurly/resources/site.rb +46 -0
- data/lib/recurly/resources/subscription.rb +134 -0
- data/lib/recurly/resources/subscription_add_on.rb +42 -0
- data/lib/recurly/resources/subscription_change.rb +54 -0
- data/lib/recurly/resources/tax_info.rb +18 -0
- data/lib/recurly/resources/transaction.rb +146 -0
- data/lib/recurly/resources/unique_coupon_code.rb +38 -0
- data/lib/recurly/resources/user.rb +38 -0
- data/lib/recurly/schema/json_deserializer.rb +53 -0
- data/lib/recurly/schema/json_parser.rb +71 -0
- data/lib/recurly/schema/request_caster.rb +66 -0
- data/lib/recurly/schema/schema_factory.rb +50 -0
- data/lib/recurly/schema/schema_validator.rb +125 -0
- data/lib/recurly/schema.rb +114 -0
- data/lib/recurly/version.rb +1 -10
- data/lib/recurly.rb +14 -147
- data/recurly.gemspec +32 -0
- data/scripts/build +4 -0
- data/scripts/clean +6 -0
- data/scripts/test +3 -0
- metadata +129 -175
- data/lib/recurly/account.rb +0 -210
- data/lib/recurly/account_acquisition.rb +0 -27
- data/lib/recurly/account_balance.rb +0 -21
- data/lib/recurly/add_on.rb +0 -46
- data/lib/recurly/address.rb +0 -25
- data/lib/recurly/adjustment.rb +0 -83
- data/lib/recurly/api/errors.rb +0 -208
- data/lib/recurly/api/net_http_adapter.rb +0 -111
- data/lib/recurly/api.rb +0 -110
- data/lib/recurly/billing_info.rb +0 -113
- data/lib/recurly/coupon.rb +0 -136
- data/lib/recurly/credit_payment.rb +0 -32
- data/lib/recurly/custom_field.rb +0 -15
- data/lib/recurly/delivery.rb +0 -19
- data/lib/recurly/dunning_campaign.rb +0 -30
- data/lib/recurly/dunning_cycle.rb +0 -18
- data/lib/recurly/error.rb +0 -13
- data/lib/recurly/gift_card.rb +0 -85
- data/lib/recurly/helper.rb +0 -51
- data/lib/recurly/invoice.rb +0 -305
- data/lib/recurly/invoice_collection.rb +0 -14
- data/lib/recurly/item.rb +0 -36
- data/lib/recurly/js.rb +0 -14
- data/lib/recurly/juris_detail.rb +0 -15
- data/lib/recurly/measured_unit.rb +0 -16
- data/lib/recurly/money.rb +0 -120
- data/lib/recurly/note.rb +0 -14
- data/lib/recurly/plan.rb +0 -44
- data/lib/recurly/purchase.rb +0 -238
- data/lib/recurly/redemption.rb +0 -46
- data/lib/recurly/resource/association.rb +0 -16
- data/lib/recurly/resource/errors.rb +0 -20
- data/lib/recurly/resource/pager.rb +0 -313
- data/lib/recurly/shipping_address.rb +0 -26
- data/lib/recurly/shipping_fee.rb +0 -17
- data/lib/recurly/shipping_method.rb +0 -13
- data/lib/recurly/subscription/add_ons.rb +0 -82
- data/lib/recurly/subscription.rb +0 -366
- data/lib/recurly/subscription_add_on.rb +0 -58
- data/lib/recurly/tax_detail.rb +0 -18
- data/lib/recurly/tax_type.rb +0 -13
- data/lib/recurly/tier.rb +0 -18
- data/lib/recurly/transaction/errors.rb +0 -115
- data/lib/recurly/transaction.rb +0 -131
- data/lib/recurly/usage.rb +0 -28
- data/lib/recurly/verify.rb +0 -12
- data/lib/recurly/webhook/account_notification.rb +0 -13
- data/lib/recurly/webhook/billing_info_update_failed_notification.rb +0 -6
- data/lib/recurly/webhook/billing_info_updated_notification.rb +0 -6
- data/lib/recurly/webhook/canceled_account_notification.rb +0 -6
- data/lib/recurly/webhook/canceled_gift_card_notification.rb +0 -6
- data/lib/recurly/webhook/canceled_subscription_notification.rb +0 -6
- data/lib/recurly/webhook/closed_credit_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/closed_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/credit_payment_notification.rb +0 -12
- data/lib/recurly/webhook/deactivated_item_notification.rb +0 -6
- data/lib/recurly/webhook/deleted_shipping_address_notification.rb +0 -6
- data/lib/recurly/webhook/dunning_notification.rb +0 -14
- data/lib/recurly/webhook/expired_subscription_notification.rb +0 -6
- data/lib/recurly/webhook/failed_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/failed_payment_notification.rb +0 -6
- data/lib/recurly/webhook/fraud_info_updated_notification.rb +0 -6
- data/lib/recurly/webhook/gift_card_notification.rb +0 -8
- data/lib/recurly/webhook/invoice_notification.rb +0 -12
- data/lib/recurly/webhook/item_notification.rb +0 -7
- data/lib/recurly/webhook/low_balance_gift_card_notification.rb +0 -6
- data/lib/recurly/webhook/new_account_notification.rb +0 -6
- data/lib/recurly/webhook/new_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/new_credit_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/new_credit_payment_notification.rb +0 -6
- data/lib/recurly/webhook/new_dunning_event_notification.rb +0 -6
- data/lib/recurly/webhook/new_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/new_item_notification.rb +0 -6
- data/lib/recurly/webhook/new_shipping_address_notification.rb +0 -6
- data/lib/recurly/webhook/new_subscription_notification.rb +0 -6
- data/lib/recurly/webhook/new_usage_notification.rb +0 -8
- data/lib/recurly/webhook/notification.rb +0 -18
- data/lib/recurly/webhook/paid_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/past_due_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/past_due_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/paused_subscription_renewal_notification.rb +0 -6
- data/lib/recurly/webhook/prerenewal_notification.rb +0 -6
- data/lib/recurly/webhook/processing_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/processing_credit_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/processing_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/processing_payment_notification.rb +0 -6
- data/lib/recurly/webhook/purchased_gift_card_notification.rb +0 -7
- data/lib/recurly/webhook/reactivated_account_notification.rb +0 -6
- data/lib/recurly/webhook/reactivated_item_notification.rb +0 -6
- data/lib/recurly/webhook/redeemed_gift_card_notification.rb +0 -7
- data/lib/recurly/webhook/regenerated_gift_card_notification.rb +0 -6
- data/lib/recurly/webhook/renewed_subscription_notification.rb +0 -6
- data/lib/recurly/webhook/reopened_charge_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/reopened_credit_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/scheduled_payment_notification.rb +0 -6
- data/lib/recurly/webhook/scheduled_subscription_pause_notification.rb +0 -6
- data/lib/recurly/webhook/scheduled_subscription_update_notification.rb +0 -6
- data/lib/recurly/webhook/subscription_notification.rb +0 -12
- data/lib/recurly/webhook/subscription_pause_canceled_notification.rb +0 -6
- data/lib/recurly/webhook/subscription_pause_modified_notification.rb +0 -6
- data/lib/recurly/webhook/subscription_paused_notification.rb +0 -6
- data/lib/recurly/webhook/subscription_resumed_notification.rb +0 -6
- data/lib/recurly/webhook/successful_payment_notification.rb +0 -6
- data/lib/recurly/webhook/successful_refund_notification.rb +0 -6
- data/lib/recurly/webhook/transaction_authorized_notification.rb +0 -6
- data/lib/recurly/webhook/transaction_notification.rb +0 -12
- data/lib/recurly/webhook/transaction_status_updated_notification.rb +0 -6
- data/lib/recurly/webhook/updated_account_notification.rb +0 -6
- data/lib/recurly/webhook/updated_balance_gift_card_notification.rb +0 -7
- data/lib/recurly/webhook/updated_gift_card_notification.rb +0 -6
- data/lib/recurly/webhook/updated_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/updated_item_notification.rb +0 -6
- data/lib/recurly/webhook/updated_shipping_address_notification.rb +0 -6
- data/lib/recurly/webhook/updated_subscription_notification.rb +0 -6
- data/lib/recurly/webhook/void_payment_notification.rb +0 -6
- data/lib/recurly/webhook/voided_credit_invoice_notification.rb +0 -6
- data/lib/recurly/webhook/voided_credit_payment_notification.rb +0 -6
- data/lib/recurly/webhook.rb +0 -113
- data/lib/recurly/xml/nokogiri.rb +0 -60
- data/lib/recurly/xml/rexml.rb +0 -52
- 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,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
|