recurly 3.0.0.beta.5 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.bumpversion.cfg +12 -0
- data/.travis.yml +2 -2
- data/.yardopts +3 -0
- data/CONTRIBUTING.md +102 -0
- data/GETTING_STARTED.md +266 -0
- data/README.md +12 -194
- data/benchmark.rb +16 -0
- data/lib/recurly.rb +4 -7
- data/lib/recurly/client.rb +60 -60
- data/lib/recurly/client/operations.rb +498 -340
- data/lib/recurly/errors.rb +4 -0
- data/lib/recurly/http.rb +43 -0
- data/lib/recurly/pager.rb +4 -10
- data/lib/recurly/request.rb +6 -6
- data/lib/recurly/requests.rb +8 -0
- data/lib/recurly/requests/account_acquisition_updatable.rb +2 -2
- data/lib/recurly/requests/billing_info_create.rb +4 -0
- data/lib/recurly/requests/custom_field.rb +18 -0
- data/lib/recurly/requests/invoice_create.rb +0 -4
- data/lib/recurly/requests/invoice_refund.rb +2 -2
- data/lib/recurly/requests/line_item_create.rb +4 -0
- data/lib/recurly/requests/purchase_create.rb +3 -7
- data/lib/recurly/requests/shipping_fee_create.rb +22 -0
- data/lib/recurly/requests/shipping_purchase.rb +22 -0
- data/lib/recurly/requests/subscription_add_on_create.rb +2 -6
- data/lib/recurly/requests/subscription_add_on_update.rb +26 -0
- data/lib/recurly/requests/subscription_change_create.rb +7 -3
- data/lib/recurly/requests/subscription_change_shipping_create.rb +22 -0
- data/lib/recurly/requests/subscription_create.rb +4 -8
- data/lib/recurly/requests/subscription_shipping_create.rb +30 -0
- data/lib/recurly/requests/subscription_shipping_update.rb +22 -0
- data/lib/recurly/requests/subscription_update.rb +3 -7
- data/lib/recurly/resource.rb +14 -1
- data/lib/recurly/resources.rb +17 -0
- data/lib/recurly/resources/account_acquisition.rb +2 -2
- data/lib/recurly/resources/add_on.rb +1 -1
- data/lib/recurly/resources/billing_info.rb +6 -6
- data/lib/recurly/resources/coupon.rb +1 -1
- data/lib/recurly/resources/coupon_discount.rb +2 -2
- data/lib/recurly/resources/coupon_redemption.rb +2 -2
- data/lib/recurly/resources/coupon_redemption_mini.rb +2 -2
- data/lib/recurly/resources/error_may_have_transaction.rb +2 -2
- data/lib/recurly/resources/invoice.rb +4 -0
- data/lib/recurly/resources/line_item.rb +1 -1
- data/lib/recurly/resources/{billing_info_payment_method.rb → payment_method.rb} +18 -2
- data/lib/recurly/resources/plan.rb +1 -1
- data/lib/recurly/resources/shipping_method.rb +42 -0
- data/lib/recurly/resources/shipping_method_mini.rb +26 -0
- data/lib/recurly/resources/subscription.rb +3 -3
- data/lib/recurly/resources/subscription_change.rb +4 -0
- data/lib/recurly/resources/subscription_shipping.rb +26 -0
- data/lib/recurly/resources/transaction.rb +4 -4
- data/lib/recurly/resources/transaction_error.rb +30 -0
- data/lib/recurly/schema.rb +85 -49
- data/lib/recurly/schema/json_parser.rb +16 -8
- data/lib/recurly/schema/request_caster.rb +10 -16
- data/lib/recurly/schema/resource_caster.rb +48 -0
- data/lib/recurly/schema/schema_factory.rb +0 -2
- data/lib/recurly/schema/schema_validator.rb +11 -14
- data/lib/recurly/version.rb +1 -1
- data/recurly.gemspec +6 -6
- data/scripts/build +1 -0
- data/scripts/bump +4 -0
- data/scripts/format +2 -0
- data/scripts/release +11 -0
- data/scripts/test +1 -0
- metadata +38 -20
- data/.ruby-version +0 -1
- data/lib/recurly/resources/transaction_payment_method.rb +0 -34
- data/lib/recurly/schema/json_deserializer.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 22a128d84f15a6887446e5f7791f3d6b91d67cec94641198ff3a4317c73a17a5
|
4
|
+
data.tar.gz: 71ac80f190a092f50cc8e9b2f7d8ab9eb5a91aa0528cacccbce642e488ef9616
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba861fa4d8f40dcc52e3cd4f2b7484aeaf90d5364deaccdf4e9e5894ee15cfdf98c3f05042d7916dd492278244a986fdfb547837214354eab3fc6c1678eb168b
|
7
|
+
data.tar.gz: bf1733bd81f4250afa91841f1e352bb884378c4edfb47bab62857c18d0ba40c74d7e1fdebbdacfc2a4289c31a895c675427d181688840e71a7da5e14a1997b01
|
data/.bumpversion.cfg
ADDED
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Contributing Guide
|
2
|
+
|
3
|
+
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
4
|
+
|
5
|
+
Filing an Issue or a Pull Request is often the best way to address a problem with this library;
|
6
|
+
however, we may not get to these right away. Although we try to be quick, our primary, daily focus is
|
7
|
+
writing code. If you want a timely response (especially if you have an emergency), we recommend
|
8
|
+
you contact our [official support team](https://support.recurly.com/).
|
9
|
+
|
10
|
+
#### Table Of Contents
|
11
|
+
|
12
|
+
* [I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
|
13
|
+
* [I think something is wrong with this library](#i-think-something-is-wrong-with-this-library)
|
14
|
+
* [I know what's wrong and I want to submit a code change](#i-know-whats-wrong-and-i-want-to-submit-a-code-change)
|
15
|
+
* [Development Dependencies](#development-dependencies)
|
16
|
+
* [Building and Testing](#building-and-testing)
|
17
|
+
* [Formatting Code](#formatting-code)
|
18
|
+
* [Generated Code](#generated-code)
|
19
|
+
|
20
|
+
|
21
|
+
## I don't want to read this whole thing I just have a question!!!
|
22
|
+
|
23
|
+
The best way to get a question answered is through our [official support channel](https://support.recurly.com/). If you
|
24
|
+
have a specific question related to this library and cannot find an answer, feel free to post an issue with the question.
|
25
|
+
|
26
|
+
## I think something is wrong with this library
|
27
|
+
|
28
|
+
Are you getting an exception or seeing some unexpected behavior from the library? An issue is the way to go.
|
29
|
+
Submit an issue and make sure you provide as much detail as possible. Some things you'll want to include:
|
30
|
+
|
31
|
+
* Your dependency versions (client version, language version, OS, etc)
|
32
|
+
* A stack trace if available
|
33
|
+
* A [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)
|
34
|
+
|
35
|
+
The more information you give us, the quicker and easier the response will be. Keep in mind that issues should be scoped
|
36
|
+
to a problem in this library and we may often redirect you to our official support for problems originating from
|
37
|
+
upstream systems.
|
38
|
+
|
39
|
+
## I know what's wrong and I want to submit a code change
|
40
|
+
|
41
|
+
So, you are sure you want to submit a change to the code? We appreciate the help!
|
42
|
+
Before you do, consider opening a discussion in the form of an issue. This accomplish a few things:
|
43
|
+
|
44
|
+
1. We can give you advice to implement the change
|
45
|
+
2. We can give you an idea of our openness to the change
|
46
|
+
|
47
|
+
**Note**: Sending code without a discussion is *always* fine. Discussion on the PR is often easier anyway. Just understand that we may
|
48
|
+
not accept the code if we don't think it's best for everyone using the library.
|
49
|
+
|
50
|
+
The rest of this section describes what you'll need to know.
|
51
|
+
|
52
|
+
### Development Dependencies
|
53
|
+
|
54
|
+
You're going to first need a supported version of the language toolchain. The best way to find which versions are supported are by checking
|
55
|
+
the [Travis File](.travis.yml) which is used to run our tests. We try to test against every supported version of the language. The [README](README.md)
|
56
|
+
may also have something to say about supported dependencies.
|
57
|
+
|
58
|
+
### Building and Testing
|
59
|
+
|
60
|
+
All of our client libraries contain a `scripts` folder which houses a set of bash scripts for doing common
|
61
|
+
development tasks. These scripts follow the same naming conventions so this can act as a kind of "Bash API"
|
62
|
+
for manipulating the libraries.
|
63
|
+
|
64
|
+
**Note**: If you are on a system without bash (such as some Windows systems), you should find the scripts only consist of a
|
65
|
+
few commands which can easily be run in your terminal or editor directly.
|
66
|
+
|
67
|
+
Start by running the `build` script to setup deps, compile (if applicable), build docs, etc:
|
68
|
+
|
69
|
+
```bash
|
70
|
+
./scripts/build
|
71
|
+
```
|
72
|
+
|
73
|
+
Use the `test` script to run the tests:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
./scripts/test
|
77
|
+
```
|
78
|
+
|
79
|
+
Make sure the tests pass locally before submitting your change.
|
80
|
+
|
81
|
+
### Formatting Code
|
82
|
+
|
83
|
+
The PR (and often the tests) will fail if you have not properly formatted the code. Instead of having a style-guide, we've provided
|
84
|
+
an auto-formatter. To use it, run the `format` script:
|
85
|
+
|
86
|
+
```bash
|
87
|
+
./scripts/format
|
88
|
+
```
|
89
|
+
|
90
|
+
### Generated Code
|
91
|
+
|
92
|
+
Some files in this codebase are generated by a non-public, proprietary program. Because they are regularly generated and updated as the
|
93
|
+
API and docs change, we won't accept any PRs that modify these files. Each of these files has a disclaimer on the top saying that they cannot
|
94
|
+
be edited by hand. By convention, they relate to things that are specific to the Recurly API that may change. For example:
|
95
|
+
|
96
|
+
* Response Schemas (Resources)
|
97
|
+
* Request Schemas (Requests)
|
98
|
+
* API endpoints (Operations)
|
99
|
+
* Errors
|
100
|
+
|
101
|
+
If you feel like you need one of these to change, please file an issue and we can discuss getting the change upstreamed.
|
102
|
+
|
data/GETTING_STARTED.md
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
# Recurly
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
### Installing
|
6
|
+
|
7
|
+
In your Gemfile, add `recurly` as a dependency.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'recurly', '~> 3.0'
|
11
|
+
```
|
12
|
+
|
13
|
+
> *Note*: We try to follow [semantic versioning](https://semver.org/) and will only apply breaking changes to major versions.
|
14
|
+
|
15
|
+
### Creating a client
|
16
|
+
|
17
|
+
Client instances are now explicitly created and referenced as opposed to V2's use of global, statically
|
18
|
+
initialized clients.
|
19
|
+
|
20
|
+
This makes multithreaded environments simpler and provides one location where every
|
21
|
+
operation can be found (rather than having them spread out among classes).
|
22
|
+
|
23
|
+
`Recurly::Client#new` initializes a new client. It only requires an API key which can be obtained on
|
24
|
+
the [API Credentials Page](https://app.recurly.com/go/integrations/api_keys).
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
API_KEY = '83749879bbde395b5fe0cc1a5abf8e5'
|
28
|
+
client = Recurly::Client.new(api_key: API_KEY)
|
29
|
+
sub = client.get_subscription(subscription_id: 'abcd123456')
|
30
|
+
```
|
31
|
+
|
32
|
+
You can also pass the initializer a block. This will give you a client scoped for just that block:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Recurly::Client.new(api_key: API_KEY) do |client|
|
36
|
+
sub = client.get_subscription(subscription_id: 'abcd123456')
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
If you plan on using the client for more than one site, you should initialize a new client for each site.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
client = Recurly::Client.new(api_key: API_KEY1)
|
44
|
+
sub = client.get_subscription(subscription_id: 'abcd123456')
|
45
|
+
|
46
|
+
# you should create a new client to connect to another site
|
47
|
+
client = Recurly::Client.new(api_key: API_KEY2)
|
48
|
+
sub = client.get_subscription(subscription_id: 'abcd7890')
|
49
|
+
```
|
50
|
+
|
51
|
+
### Operations
|
52
|
+
|
53
|
+
The {Recurly::Client} contains every `operation` you can perform on the site as a list of methods. Each method is documented explaining
|
54
|
+
the types and descriptions for each input and return type. You can view all available operations by looking at the `Instance Methods Summary` list
|
55
|
+
on the {Recurly::Client} documentation page. Clicking a method will give you detailed information about its inputs and returns. Take the `create_account`
|
56
|
+
operation as an example: {Recurly::Client#create_account}.
|
57
|
+
|
58
|
+
### Pagination
|
59
|
+
|
60
|
+
Pagination is done by the class {Recurly::Pager}. All `list_*` methods on the client return an instance of this class.
|
61
|
+
The pager has an `each` method which accepts a block for each object in the entire list. Each page is fetched automatically
|
62
|
+
for you presenting the elements as a single enumerable.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
plans = client.list_plans()
|
66
|
+
plans.each do |plan|
|
67
|
+
puts "Plan: #{plan.id}"
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
You may also paginate in chunks with `each_page`.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
plans = client.list_plans()
|
75
|
+
plans.each_page do |data|
|
76
|
+
data.each do |plan|
|
77
|
+
puts "Plan: #{plan.id}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
Both {Pager#each} and {Pager#each_page} return Enumerators if a block is not given. This allows you to use other Enumerator methods
|
83
|
+
such as `map` or `each_with_index`.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
plans = client.list_plans()
|
87
|
+
plans.each_page.each_with_index do |data, page_num|
|
88
|
+
puts "Page Number #{page_num}"
|
89
|
+
data.each do |plan|
|
90
|
+
puts "Plan: #{plan.id}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
Pagination endpoints take a number of options to sort and filter the results. They can be passed in as keyword arguments.
|
96
|
+
The names, types, and descriptions of these arguments are listed in the rubydocs for each method:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
options = {
|
100
|
+
limit: 200, # number of items per page
|
101
|
+
state: :active, # only active plans
|
102
|
+
sort: :updated_at,
|
103
|
+
order: :asc,
|
104
|
+
begin_time: DateTime.new(2017,1,1), # January 1st 2017,
|
105
|
+
end_time: DateTime.now
|
106
|
+
}
|
107
|
+
|
108
|
+
plans = client.list_plans(**options)
|
109
|
+
plans.each do |plan|
|
110
|
+
puts "Plan: #{plan.id}"
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
**A note on `limit`**:
|
115
|
+
|
116
|
+
`limit` defaults to 20 items per page and can be set from 1 to 200. Choosing a lower limit means more network requests but smaller payloads.
|
117
|
+
We recommend keeping the default for most cases but increasing the limit if you are planning on iterating through many pages of items (e.g. all transactions in your site).
|
118
|
+
|
119
|
+
|
120
|
+
### Creating Resources
|
121
|
+
|
122
|
+
Currently, resources are created by passing in a `body` keyword argument in the form of a `Hash`.
|
123
|
+
This Hash must follow the schema of the documented request type. For example, the `create_plan` operation
|
124
|
+
takes a request of type {Recurly::Requests::PlanCreate}. Failing to conform to this schema will result in an argument
|
125
|
+
error.
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
require 'securerandom'
|
129
|
+
|
130
|
+
code = SecureRandom.uuid
|
131
|
+
plan_data = {
|
132
|
+
code: code,
|
133
|
+
interval_length: 1,
|
134
|
+
interval_unit: 'months',
|
135
|
+
name: code,
|
136
|
+
currencies: [
|
137
|
+
{
|
138
|
+
currency: 'USD',
|
139
|
+
setup_fee: 800,
|
140
|
+
unit_amount: 10
|
141
|
+
}
|
142
|
+
]
|
143
|
+
}
|
144
|
+
|
145
|
+
plan = client.create_plan(body: plan_data)
|
146
|
+
```
|
147
|
+
|
148
|
+
### Error Handling
|
149
|
+
|
150
|
+
This library currently throws 2 types of exceptions. {Recurly::Errors::APIError} and {Recurly::Errors::NetworkError}. See these 2 files for the types of exceptions you can catch:
|
151
|
+
|
152
|
+
1. [API Errors](./lib/recurly/errors/api_errors.rb)
|
153
|
+
2. [Network Errors](./lib/recurly/errors/network_errors.rb)
|
154
|
+
|
155
|
+
You will normally be working with {Recurly::Errors::APIError}. You can catch specific or generic versions of these exceptions. Example:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
begin
|
159
|
+
client = Recurly::Client.new(api_key: API_KEY)
|
160
|
+
code = "iexistalready"
|
161
|
+
plan_data = {
|
162
|
+
code: code,
|
163
|
+
interval_length: 1,
|
164
|
+
interval_unit: 'months',
|
165
|
+
name: code,
|
166
|
+
currencies: [
|
167
|
+
{
|
168
|
+
currency: 'USD',
|
169
|
+
setup_fee: 800,
|
170
|
+
unit_amount: 10
|
171
|
+
}
|
172
|
+
]
|
173
|
+
}
|
174
|
+
|
175
|
+
plan = client.create_plan(body: plan_data)
|
176
|
+
rescue Recurly::Errors::ValidationError => ex
|
177
|
+
puts ex.inspect
|
178
|
+
#=> #<Recurly::ValidationError: Recurly::ValidationError: Code 'iexistalready' already exists>
|
179
|
+
puts ex.recurly_error.inspect
|
180
|
+
#=> #<Recurly::Error:0x007fbbdf8a32c8 @attributes={:type=>"validation", :message=>"Code 'iexistalready' already exists", :params=>[{"param"=>"code", "message"=>"'iexistalready' already exists"}]}>
|
181
|
+
puts ex.status_code
|
182
|
+
#=> 422
|
183
|
+
rescue Recurly::Errors::APIError => ex
|
184
|
+
# catch a generic api error
|
185
|
+
rescue Recurly::Errors::TimeoutError => ex
|
186
|
+
# catch a specific network error
|
187
|
+
rescue Recurly::Errors::NetworkError => ex
|
188
|
+
# catch a generic network error
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
192
|
+
### HTTP Metadata
|
193
|
+
|
194
|
+
Sometimes you might want to get some additional information about the underlying HTTP request and response. Instead of
|
195
|
+
returning this information directly and forcing the programmer to unwrap it, we inject this metadata into the top level
|
196
|
+
resource that was returned. You can access the {Recurly::HTTP::Response} by calling `#get_response` on any {Recurly::Resource}.
|
197
|
+
|
198
|
+
**Warning**: Do not log or render whole requests or responses as they may contain PII or sensitive data.
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
account = @client.get_account(account_id: "code-benjamin")
|
202
|
+
response = account.get_response
|
203
|
+
response.rate_limit_remaining #=> 1985
|
204
|
+
response.request_id #=> "0av50sm5l2n2gkf88ehg"
|
205
|
+
response.request.path #=> "/sites/subdomain-mysite/accounts/code-benjamin"
|
206
|
+
response.request.body #=> None
|
207
|
+
```
|
208
|
+
|
209
|
+
This also works on {Recurly::Resources::Empty} responses:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
response = @client.remove_line_item(
|
213
|
+
line_item_id: "a959576b2b10b012"
|
214
|
+
).get_response
|
215
|
+
```
|
216
|
+
And it can be captured on exceptions through the {Recurly::ApiError} object:
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
begin
|
220
|
+
account = client.get_account(account_id: "code-benjamin")
|
221
|
+
rescue Recurly::Errors::NotFoundError => e
|
222
|
+
response = e.get_response()
|
223
|
+
puts "Give this request id to Recurly Support: #{response.request_id}"
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
### Webhooks
|
228
|
+
|
229
|
+
Recurly can send webhooks to any publicly accessible server.
|
230
|
+
When an event in Recurly triggers a webhook (e.g., an account is opened),
|
231
|
+
Recurly will attempt to send this notification to the endpoint(s) you specify.
|
232
|
+
You can specify up to 10 endpoints through the application. All notifications will
|
233
|
+
be sent to all configured endpoints for your site.
|
234
|
+
|
235
|
+
See our [product docs](https://docs.recurly.com/docs/webhooks) to learn more about webhooks
|
236
|
+
and see our [dev docs](https://dev.recurly.com/page/webhooks) to learn about what payloads
|
237
|
+
are available.
|
238
|
+
|
239
|
+
Although our API is now JSON, our webhook payloads are still formatted as XML for the time being.
|
240
|
+
This library is not yet responsible for handling webhooks. If you do need webhooks, we recommend using a simple
|
241
|
+
XML to Hash parser.
|
242
|
+
|
243
|
+
If you are using Rails, we'd recommend [Hash.from_xml](https://apidock.com/rails/Hash/from_xml/class).
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
notification = Hash.from_xml <<-XML
|
247
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
248
|
+
<new_account_notification>
|
249
|
+
<account>
|
250
|
+
<account_code>1</account_code>
|
251
|
+
<username nil="true"></username>
|
252
|
+
<email>verena@example.com</email>
|
253
|
+
<first_name>Verena</first_name>
|
254
|
+
<last_name>Example</last_name>
|
255
|
+
<company_name nil="true"></company_name>
|
256
|
+
</account>
|
257
|
+
</new_account_notification>
|
258
|
+
XML
|
259
|
+
|
260
|
+
code = notification["new_account_notification"]["account"]["account_code"]
|
261
|
+
puts "New Account with code #{code} created."
|
262
|
+
```
|
263
|
+
|
264
|
+
If you are not using Rails, we recommend you use [nokogiri](https://nokogiri.org/); however, heed security warnings
|
265
|
+
about parse options. Although the XML should only be coming from Recurly, you should parse it as untrusted to be safe.
|
266
|
+
Read more about the security implications of parsing untrusted XML in [this OWASP cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_Security_Cheat_Sheet.html).
|
data/README.md
CHANGED
@@ -1,205 +1,23 @@
|
|
1
1
|
# Recurly
|
2
2
|
|
3
|
-
This
|
4
|
-
|
3
|
+
This repository houses the official ruby client for Recurly's V3 API.
|
4
|
+
|
5
|
+
> *Note*:
|
6
|
+
> If you were looking for the V2 client, see the [master branch](https://github.com/recurly/recurly-client-ruby/tree/master).
|
5
7
|
|
6
8
|
## Getting Started
|
7
9
|
|
8
10
|
### Documentation
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
### Installing
|
14
|
-
|
15
|
-
This gem is a pre-release. In your Gemfile, add `recurly` as a dependency.
|
16
|
-
|
17
|
-
```ruby
|
18
|
-
gem 'recurly', '3.0.0.beta.5'
|
19
|
-
```
|
20
|
-
|
21
|
-
It's important that you lock on a specific version as there may be breaking changes between releases.
|
22
|
-
All beta releases will have the format `3.0.0.beta.x` until we go live.
|
23
|
-
|
24
|
-
### Creating a client
|
25
|
-
|
26
|
-
Client instances are now explicitly created and referenced as opposed to V2's use of global, statically
|
27
|
-
initialized clients.
|
28
|
-
|
29
|
-
This makes multithreaded environments simpler and provides one location where every
|
30
|
-
operation can be found (rather than having them spread out among classes).
|
31
|
-
|
32
|
-
`Recurly::Client#new` initializes a new client. It requires an API key and a site id:
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
API_KEY = '83749879bbde395b5fe0cc1a5abf8e5'
|
36
|
-
SITE_ID = 'dqzlv9shi7wa'
|
37
|
-
client = Recurly::Client.new(site_id: SITE_ID, api_key: API_KEY)
|
38
|
-
# You may use the subdomain instead of the site_id if you do not know the site_id
|
39
|
-
client = Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY)
|
40
|
-
sub = client.get_subscription(subscription_id: 'abcd123456')
|
41
|
-
```
|
42
|
-
|
43
|
-
You can also pass the initializer a block. This will give you a client scoped for just that block:
|
44
|
-
|
45
|
-
```ruby
|
46
|
-
Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY) do |client|
|
47
|
-
sub = client.get_subscription(subscription_id: 'abcd123456')
|
48
|
-
end
|
49
|
-
```
|
50
|
-
|
51
|
-
If you plan on using the client for more than one site, you should initialize a new client for each site.
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
# Give a `site_id`
|
55
|
-
client = Recurly::Client.new(api_key: API_KEY, site_id: SITE_ID)
|
56
|
-
# Or use the subdomain
|
57
|
-
client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-dev')
|
58
|
-
|
59
|
-
sub = client.get_subscription(subscription_id: 'abcd123456')
|
60
|
-
|
61
|
-
# you should create a new client to connect to another site
|
62
|
-
client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-prod')
|
63
|
-
sub = client.get_subscription(subscription_id: 'abcd7890')
|
64
|
-
```
|
65
|
-
|
66
|
-
### Operations
|
67
|
-
|
68
|
-
The {Recurly::Client} contains every `operation` you can perform on the site as a list of methods. Each method is documented explaining
|
69
|
-
the types and descriptions for each input and return type. You can view all available operations by looking at the `Instance Methods Summary` list
|
70
|
-
on the {Recurly::Client} documentation page. Clicking a method will give you detailed information about its inputs and returns. Take the `create_account`
|
71
|
-
operation as an example: {Recurly::Client#create_account}.
|
72
|
-
|
73
|
-
### Pagination
|
74
|
-
|
75
|
-
Pagination is done by the class `Recurly::Pager`. All `list_*` methods on the client return an instance of this class.
|
76
|
-
The pager has an `each` method which accepts a block for each object in the entire list. Each page is fetched automatically
|
77
|
-
for you presenting the elements as a single enumerable.
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
plans = client.list_plans()
|
81
|
-
plans.each do |plan|
|
82
|
-
puts "Plan: #{plan.id}"
|
83
|
-
end
|
84
|
-
```
|
85
|
-
|
86
|
-
You may also paginate in chunks with `each_page`.
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
plans = client.list_plans()
|
90
|
-
plans.each_page do |data|
|
91
|
-
data.each do |plan|
|
92
|
-
puts "Plan: #{plan.id}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
```
|
96
|
-
|
97
|
-
Both `Pager#each` and `Pager#each_page` return Enumerators if a block is not given. This allows you to use other Enumerator methods
|
98
|
-
such as `map` or `each_with_index`.
|
99
|
-
|
100
|
-
```ruby
|
101
|
-
plans = client.list_plans()
|
102
|
-
plans.each_page.each_with_index do |data, page_num|
|
103
|
-
puts "Page Number #{page_num}"
|
104
|
-
data.each do |plan|
|
105
|
-
puts "Plan: #{plan.id}"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
```
|
109
|
-
|
110
|
-
Pagination endpoints take a number of options to sort and filter the results. They can be passed in as keyword arguments.
|
111
|
-
The names, types, and descriptions of these arguments are listed in the rubydocs for each method:
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
options = {
|
115
|
-
limit: 200, # number of items per page
|
116
|
-
state: :active, # only active plans
|
117
|
-
sort: :updated_at,
|
118
|
-
order: :asc,
|
119
|
-
begin_time: DateTime.new(2017,1,1), # January 1st 2017,
|
120
|
-
end_time: DateTime.now
|
121
|
-
}
|
122
|
-
|
123
|
-
plans = client.list_plans(**options)
|
124
|
-
plans.each do |plan|
|
125
|
-
puts "Plan: #{plan.id}"
|
126
|
-
end
|
127
|
-
```
|
128
|
-
|
129
|
-
**A note on `limit`**:
|
130
|
-
|
131
|
-
`limit` defaults to 20 items per page and can be set from 1 to 200. Choosing a lower limit means more network requests but smaller payloads.
|
132
|
-
We recommend keeping the default for most cases but increasing the limit if you are planning on iterating through many pages of items (e.g. all transactions in your site).
|
133
|
-
|
134
|
-
|
135
|
-
### Creating Resources
|
136
|
-
|
137
|
-
Currently, resources are created by passing in a `body` keyword argument in the form of a `Hash`.
|
138
|
-
This Hash must follow the schema of the documented request type. For example, the `create_plan` operation
|
139
|
-
takes a request of type {Recurly::Requests::PlanCreate}. Failing to conform to this schema will result in an argument
|
140
|
-
error.
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
require 'securerandom'
|
144
|
-
|
145
|
-
code = SecureRandom.uuid
|
146
|
-
plan_data = {
|
147
|
-
code: code,
|
148
|
-
interval_length: 1,
|
149
|
-
interval_unit: 'months',
|
150
|
-
name: code,
|
151
|
-
currencies: [
|
152
|
-
{
|
153
|
-
currency: 'USD',
|
154
|
-
setup_fee: 800,
|
155
|
-
unit_amount: 10
|
156
|
-
}
|
157
|
-
]
|
158
|
-
}
|
159
|
-
|
160
|
-
plan = client.create_plan(body: plan_data)
|
161
|
-
```
|
162
|
-
|
163
|
-
### Error Handling
|
164
|
-
|
165
|
-
This library currently throws 2 types of exceptions. {Recurly::Errors::APIError} and {Recurly::Errors::NetworkError}. See these 2 files for the types of exceptions you can catch:
|
12
|
+
> *Note*:
|
13
|
+
> Until rubydoc.info respects our `.yardopts` file, see documentation [here](GETTING_STARTED.md).
|
166
14
|
|
167
|
-
|
168
|
-
|
15
|
+
Ruby documentation and the getting started instructions can be found
|
16
|
+
on rubydoc.info: [https://www.rubydoc.info/github/recurly/recurly-client-ruby/](https://www.rubydoc.info/github/recurly/recurly-client-ruby/).
|
169
17
|
|
170
|
-
|
18
|
+
Documentation for the HTTP API and example code can be found
|
19
|
+
[on our Developer Portal](https://developers.recurly.com/api/v2019-10-10/).
|
171
20
|
|
172
|
-
|
173
|
-
begin
|
174
|
-
client = Recurly::Client.new(site_id: SITE_ID, api_key: API_KEY)
|
175
|
-
code = "iexistalready"
|
176
|
-
plan_data = {
|
177
|
-
code: code,
|
178
|
-
interval_length: 1,
|
179
|
-
interval_unit: 'months',
|
180
|
-
name: code,
|
181
|
-
currencies: [
|
182
|
-
{
|
183
|
-
currency: 'USD',
|
184
|
-
setup_fee: 800,
|
185
|
-
unit_amount: 10
|
186
|
-
}
|
187
|
-
]
|
188
|
-
}
|
21
|
+
### Contributing
|
189
22
|
|
190
|
-
|
191
|
-
rescue Recurly::Errors::ValidationError => ex
|
192
|
-
puts ex.inspect
|
193
|
-
#=> #<Recurly::ValidationError: Recurly::ValidationError: Code 'iexistalready' already exists>
|
194
|
-
puts ex.recurly_error.inspect
|
195
|
-
#=> #<Recurly::Error:0x007fbbdf8a32c8 @attributes={:type=>"validation", :message=>"Code 'iexistalready' already exists", :params=>[{"param"=>"code", "message"=>"'iexistalready' already exists"}]}>
|
196
|
-
puts ex.status_code
|
197
|
-
#=> 422
|
198
|
-
rescue Recurly::Errors::APIError => ex
|
199
|
-
# catch a generic api error
|
200
|
-
rescue Recurly::Errors::TimeoutError => ex
|
201
|
-
# catch a specific network error
|
202
|
-
rescue Recurly::Errors::NetworkError => ex
|
203
|
-
# catch a generic network error
|
204
|
-
end
|
205
|
-
```
|
23
|
+
Please see our [Contributing Guide](CONTRIBUTING.md).
|