zuora-ruby 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +27 -3
- data/README.md +37 -19
- data/lib/zuora.rb +51 -0
- data/lib/zuora/client.rb +51 -25
- data/lib/zuora/models.rb +4 -3
- data/lib/zuora/models/account.rb +58 -47
- data/lib/zuora/models/card_holder.rb +46 -52
- data/lib/zuora/models/contact.rb +65 -38
- data/lib/zuora/models/dirty.rb +192 -0
- data/lib/zuora/models/payment_methods/credit_card.rb +23 -23
- data/lib/zuora/models/rate_plan.rb +6 -10
- data/lib/zuora/models/rate_plan_charge.rb +111 -49
- data/lib/zuora/models/subscription.rb +72 -42
- data/lib/zuora/models/tier.rb +16 -16
- data/lib/zuora/models/validation_predicates.rb +29 -0
- data/lib/zuora/resources.rb +0 -11
- data/lib/zuora/resources/accounts.rb +9 -8
- data/lib/zuora/resources/payment_methods/credit_card.rb +1 -3
- data/lib/zuora/resources/subscriptions.rb +2 -6
- data/lib/zuora/serializers/attribute.rb +3 -3
- data/lib/zuora/version.rb +1 -1
- data/zuora/fixtures/vcr_cassettes/account_create_.yml +111 -0
- data/zuora/fixtures/vcr_cassettes/account_update_.yml +113 -0
- data/zuora/fixtures/vcr_cassettes/subscription_create_.yml +114 -0
- data/zuora/fixtures/vcr_cassettes/subscription_update_.yml +114 -0
- data/zuora_ruby.gemspec +2 -3
- metadata +13 -8
- data/lib/zuora/models/utils.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da6c115de2be80e51003cee17072c6c06e578199
|
4
|
+
data.tar.gz: 6e48747729c511bd9fd2892eb8d97b1b9a3786a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1ea116b905657af8fef4d060239583187eefa02fbceb623ce1676a083efd3a2cb46916cec0c0beed5cedab0ca802abf3ccf42aab24b1bf3d2613744ae00e713
|
7
|
+
data.tar.gz: 7bdeb438f2581dfa8dc1aa9d01c008ba8cfdad614831bf0de642ef56a3e6ecf197b81a2919082d735dc5c7c62bfcefa3c6af858210e90062482587aabfc932fd
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -17,6 +17,30 @@ Style/Encoding:
|
|
17
17
|
AbcSize:
|
18
18
|
Enabled: false
|
19
19
|
|
20
|
-
|
21
|
-
Enabled:
|
22
|
-
|
20
|
+
Rails/TimeZone:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Style/AlignParameters:
|
24
|
+
EnforcedStyle: with_fixed_indentation
|
25
|
+
SupportedStyles:
|
26
|
+
- with_first_parameter
|
27
|
+
- with_fixed_indentation
|
28
|
+
|
29
|
+
Style/CaseIndentation:
|
30
|
+
IndentWhenRelativeTo: end
|
31
|
+
SupportedStyles:
|
32
|
+
- case
|
33
|
+
- end
|
34
|
+
IndentOneStep: false
|
35
|
+
|
36
|
+
Style/IndentHash:
|
37
|
+
EnforcedStyle: consistent
|
38
|
+
SupportedStyles:
|
39
|
+
- special_inside_parentheses
|
40
|
+
- consistent
|
41
|
+
|
42
|
+
Style/MultilineOperationIndentation:
|
43
|
+
EnforcedStyle: indented
|
44
|
+
SupportedStyles:
|
45
|
+
- aligned
|
46
|
+
- indented
|
data/README.md
CHANGED
@@ -5,9 +5,27 @@
|
|
5
5
|
# Zuora REST API: Ruby Client
|
6
6
|
|
7
7
|
This library implements a Ruby client wrapping Zuora's REST API.
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
|
9
|
+
### Model
|
10
|
+
A base module called `DirtyValidAttr` provides `dirty_model_attr`
|
11
|
+
* **Accessors**: attribute name provides getters and setters, as in `attr_accessor`
|
12
|
+
* **Validations** `valid: max_length(3) `
|
13
|
+
* Includes a library of predicate higher order validation functions
|
14
|
+
* **Coercions** `coerce: ->(value) { value.to_s } `
|
15
|
+
* **Type Checks** `type: String`
|
16
|
+
* **Required Attributes**: `:required: true`
|
17
|
+
|
18
|
+
### Resource
|
19
|
+
* **HTTP requests**: that are authenticated with provided credentials
|
20
|
+
* **Zuora API endpoints**:
|
21
|
+
|
22
|
+
### Utilities
|
23
|
+
- **Serialization**: Ruby <=> JSON serializer provided, just provide a module or class that respnds to `.serialize(hash)`
|
24
|
+
|
25
|
+
### Development: Specs and Testing
|
26
|
+
- **Factories**: for generating sample valid and invalid data that works with the API
|
27
|
+
- **Unit**: factories for testing model valdiations
|
28
|
+
- **Integration**: Tests against or memoized (via `VCR`) HTTP responses
|
11
29
|
|
12
30
|
## Quickstart
|
13
31
|
```ruby
|
@@ -15,9 +33,6 @@ This library implements a Ruby client wrapping Zuora's REST API.
|
|
15
33
|
client = Zuora::Client.new(username, password)
|
16
34
|
# Create a model
|
17
35
|
account = Zuora::Models::Account.new(...)
|
18
|
-
# Validate
|
19
|
-
account.valid? # true or false, check account.errors if false
|
20
|
-
# Select a serializer (snake_case -> lowerCamelCase)
|
21
36
|
serializer = Zuora::Serializers::Attribute
|
22
37
|
# Low level HTTP API
|
23
38
|
client.get('/rest/v1/accounts', serializer.serialze account)
|
@@ -33,14 +48,10 @@ used in subsequent requests. An optional third, truthy value enables Sandbox ins
|
|
33
48
|
Use `client.<get|post|put>(url, params)` to make HTTP requests via the authenticated client. Request and response body will be converted to/from Ruby via `farraday_middleware`.
|
34
49
|
|
35
50
|
3. ***Models:*** Ruby interface for constructing valid Zuora objects.
|
36
|
-
-
|
37
|
-
- `account.valid?` a boolean indicating validity
|
38
|
-
- `account.errors` a hash of error message(s)
|
39
|
-
- `account.attributes` an array of attribute names
|
51
|
+
- Documentation coming soon. In the mean time, check comments in `Zuora::Models::Dirty`.
|
40
52
|
|
41
53
|
4. **Serializers:** Recursive data transformations for mapping between formats; a Ruby -> JSON serializer is included; `snake_case` attributes are transformed into JSON `lowerCamelCase` recursively in a nested structure.
|
42
54
|
- ex. `Zuora::Serializers::Attribute.serialize account`
|
43
|
-
|
44
55
|
|
45
56
|
5. **Resources:** Wraps Zuora REST API endpoints. Hand a valid model and (optionally) a serializer to a Resource to trigger a request. Request will be made for valid models only. An exception will be raised if the model is invalid. Otherwise, a `Farraday::Response` object will be returned (responding to `.status`, `.headers`, and `.body`).
|
46
57
|
|
@@ -68,9 +79,9 @@ Models implement (recursive, nested) Zuora validations using `ActiveModel::Model
|
|
68
79
|
## Resources
|
69
80
|
In module `Zuora::Resources::`
|
70
81
|
* `Account.create!` **[working]**
|
71
|
-
* `Account.update!` [
|
72
|
-
* `Subscription.create!` [
|
73
|
-
* `Subscription.update!` [
|
82
|
+
* `Account.update!` **[working]**
|
83
|
+
* `Subscription.create!` **[working]**
|
84
|
+
* `Subscription.update!` **[working]**
|
74
85
|
* `Subscription.cancel!` [in progress]
|
75
86
|
* `PaymentMethod.update!` [in progress]
|
76
87
|
|
@@ -181,11 +192,18 @@ pp response
|
|
181
192
|
@on_complete_callbacks=[]>
|
182
193
|
```
|
183
194
|
# Changelog
|
184
|
-
* **[0.1.0] Initial release
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
*
|
195
|
+
* **[0.1.0 - 2016-01-12]** Initial release
|
196
|
+
* **[0.2.0] - 2016-01-14]** Models
|
197
|
+
- Refactored client to clarify logic
|
198
|
+
- Replaces `ActiveRecord::Model` and `::Validations` with a base module that provides powerful and extensible facilities for modeling remote resources in Ruby.
|
199
|
+
* required attributes, coercions, validations, type checking
|
200
|
+
* dirty attribute tracking
|
201
|
+
* extensible predicate library
|
202
|
+
- Implements fine-grained validations per Zuora spec
|
203
|
+
- Removes invalid model state paradigm used via `ActiveModel` in version 0.1.0.
|
204
|
+
- A model now performs its validations on `.new`, and will raise a detailed exception on mistyped, invalid or uncoercable data.
|
205
|
+
- Adds VCR for mocking out HTTP requests
|
206
|
+
- Adds integration specs for `Subscribe` `create!` and `update!` and `Account` `create!` and `update!`
|
189
207
|
|
190
208
|
# Commit rights
|
191
209
|
Anyone who has a patch accepted may request commit rights. Please do so inside the pull request post-merge.
|
data/lib/zuora.rb
CHANGED
@@ -23,7 +23,58 @@ module Zuora
|
|
23
23
|
|
24
24
|
PAYMENT_TERMS = ['Due Upon Receipt', 'Net 30', 'Net 60', 'Net 90']
|
25
25
|
|
26
|
+
# SUBSCRIPTION
|
27
|
+
|
26
28
|
SUBSCRIPTION_TERM_TYPES = %w(TERMED EVERGREEN)
|
29
|
+
|
30
|
+
DISCOUNT_TYPES = %w(ONETIME
|
31
|
+
RECURRING
|
32
|
+
USAGE
|
33
|
+
ONETIMERECURRING
|
34
|
+
ONETIMEUSAGE
|
35
|
+
RECURRINGUSAGE
|
36
|
+
ONETIMERECURRINGUSAG) # typo in zuora docs?
|
37
|
+
|
38
|
+
DISCOUNT_LEVELS = %w(rateplan subscription account)
|
39
|
+
|
40
|
+
LIST_PRICE_BASES = %w(Per_Billing_Period
|
41
|
+
Per_Month
|
42
|
+
Per_Week)
|
43
|
+
|
44
|
+
TRIGGER_EVENTS = %w(UCE USA UCA USD)
|
45
|
+
|
46
|
+
END_DATE_CONDITIONS = %w(Subscription_End
|
47
|
+
Fixed_Period
|
48
|
+
Specific_End_Date)
|
49
|
+
|
50
|
+
UP_TO_PERIODS = %w(Days Weeks Months Years)
|
51
|
+
|
52
|
+
BILLING_PERIODS = %w(Month
|
53
|
+
Quarter
|
54
|
+
Semi_Annual
|
55
|
+
Annual
|
56
|
+
Eighteen_Months
|
57
|
+
Two_Years
|
58
|
+
Three_Years
|
59
|
+
Five_Years
|
60
|
+
Specific_Months
|
61
|
+
Subscription_Term
|
62
|
+
Week
|
63
|
+
Specific_Weeks)
|
64
|
+
|
65
|
+
BILLING_TIMINGS = %w(IN_ADVANCE IN_ARREARS)
|
66
|
+
|
67
|
+
BILL_CYCLE_TYPES = %w(DefaultFromCustomer
|
68
|
+
SpecificDayofMonth
|
69
|
+
SubscriptionStartDay
|
70
|
+
ChargeTriggerDay
|
71
|
+
SpecificDayOfWeek)
|
72
|
+
|
73
|
+
PRICE_CHANGE_OPTIONS = %w(NoChange
|
74
|
+
SpecificPercentageValue
|
75
|
+
UseLatestProductCatalogPricing)
|
76
|
+
|
77
|
+
WEEKDAYS = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
|
27
78
|
end
|
28
79
|
|
29
80
|
require_relative 'zuora/version'
|
data/lib/zuora/client.rb
CHANGED
@@ -11,7 +11,7 @@ module Zuora
|
|
11
11
|
ErrorResponse = Class.new StandardError
|
12
12
|
|
13
13
|
class Client
|
14
|
-
|
14
|
+
attr_reader :connection
|
15
15
|
|
16
16
|
# Creates a connection instance.
|
17
17
|
# Makes an initial HTTP request to fetch session token.
|
@@ -22,30 +22,19 @@ module Zuora
|
|
22
22
|
# @param [Boolean] sandbox
|
23
23
|
# @return [Zuora::Client] with .connection, .put, .post
|
24
24
|
def initialize(username, password, sandbox = false)
|
25
|
-
|
25
|
+
base_url = api_url sandbox
|
26
|
+
conn = connection base_url
|
26
27
|
|
27
|
-
response =
|
28
|
-
req.url '/rest/v1/connections'
|
29
|
-
req.headers['apiAccessKeyId'] = username
|
30
|
-
req.headers['apiSecretAccessKey'] = password
|
31
|
-
req.headers['Content-Type'] = 'application/json'
|
32
|
-
end
|
28
|
+
response = auth_request conn, username, password
|
33
29
|
|
34
|
-
|
35
|
-
@auth_cookie = response.headers['set-cookie'].split(' ')[0]
|
36
|
-
@connection = connection(url)
|
37
|
-
else
|
38
|
-
fail ConnectionError, response.body['reasons']
|
39
|
-
end
|
30
|
+
handle_response response, conn
|
40
31
|
end
|
41
32
|
|
42
33
|
# @param [String] url - URL of request
|
43
34
|
# @return [Faraday::Response] A response, with .headers, .status & .body
|
44
35
|
def get(url)
|
45
36
|
@connection.get do |req|
|
46
|
-
req
|
47
|
-
req.headers['Content-Type'] = 'application/json'
|
48
|
-
req.headers['Cookie'] = @auth_cookie
|
37
|
+
set_request_headers! req, url
|
49
38
|
end
|
50
39
|
end
|
51
40
|
|
@@ -54,9 +43,7 @@ module Zuora
|
|
54
43
|
# @return [Faraday::Response] A response, with .headers, .status & .body
|
55
44
|
def post(url, params)
|
56
45
|
response = @connection.post do |req|
|
57
|
-
req
|
58
|
-
req.headers['Content-Type'] = 'application/json'
|
59
|
-
req.headers['Cookie'] = @auth_cookie
|
46
|
+
set_request_headers! req, url
|
60
47
|
req.body = JSON.generate params
|
61
48
|
end
|
62
49
|
|
@@ -72,11 +59,9 @@ module Zuora
|
|
72
59
|
# @param [Params] params - Data to be sent in request body
|
73
60
|
# @return [Faraday::Response] A response, with .headers, .status & .body
|
74
61
|
def put(url, params)
|
75
|
-
response = @connection.put do |
|
76
|
-
|
77
|
-
|
78
|
-
req.headers['Cookie'] = @auth_cookie
|
79
|
-
req.body = JSON.generate params
|
62
|
+
response = @connection.put do |request|
|
63
|
+
set_request_headers! request, url
|
64
|
+
request.body = JSON.generate params
|
80
65
|
end
|
81
66
|
|
82
67
|
response
|
@@ -89,6 +74,47 @@ module Zuora
|
|
89
74
|
|
90
75
|
private
|
91
76
|
|
77
|
+
# Make connection attempt
|
78
|
+
# @param [Faraday::Connection] conn
|
79
|
+
# @param [String] username
|
80
|
+
# @param [String] password
|
81
|
+
def auth_request(conn, username, password)
|
82
|
+
conn.post do |request|
|
83
|
+
set_auth_request_headers! request, username, password
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sets instance variables or throws Connection error
|
88
|
+
# @param [Faraday::Response] response
|
89
|
+
# @param [Faraday::Connection] conn
|
90
|
+
def handle_response(response, conn)
|
91
|
+
if response.status == 200
|
92
|
+
@auth_cookie = response.headers['set-cookie'].split(' ')[0]
|
93
|
+
@connection = conn
|
94
|
+
else
|
95
|
+
fail ConnectionError, response.body['reasons']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param [Faraday::Request] request - Faraday::Request builder
|
100
|
+
# @param [String] username - Zuora username
|
101
|
+
# @param [String] password - Zuora password
|
102
|
+
def set_auth_request_headers!(request, username, password)
|
103
|
+
request.url '/rest/v1/connections'
|
104
|
+
request.headers['apiAccessKeyId'] = username
|
105
|
+
request.headers['apiSecretAccessKey'] = password
|
106
|
+
request.headers['Content-Type'] = 'application/json'
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param [Faraday::Request] request - Faraday Request builder
|
110
|
+
# @param [String] url - Relative URL for HTTP request
|
111
|
+
# @return [Nil]
|
112
|
+
def set_request_headers!(request, url)
|
113
|
+
request.url url
|
114
|
+
request.headers['Content-Type'] = 'application/json'
|
115
|
+
request.headers['Cookie'] = @auth_cookie
|
116
|
+
end
|
117
|
+
|
92
118
|
# @param [String] url
|
93
119
|
# @return [Faraday::Client]
|
94
120
|
def connection(url)
|
data/lib/zuora/models.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
require_relative 'models/
|
1
|
+
require_relative 'models/dirty'
|
2
|
+
require_relative 'models/validation_predicates'
|
2
3
|
|
3
|
-
require_relative 'models/account'
|
4
|
-
require_relative 'models/card_holder'
|
5
4
|
require_relative 'models/contact'
|
6
5
|
require_relative 'models/payment_method'
|
6
|
+
require_relative 'models/account'
|
7
|
+
require_relative 'models/card_holder'
|
7
8
|
require_relative 'models/rate_plan'
|
8
9
|
require_relative 'models/rate_plan_charge'
|
9
10
|
require_relative 'models/subscription'
|
data/lib/zuora/models/account.rb
CHANGED
@@ -1,53 +1,64 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Zuora
|
4
2
|
module Models
|
5
3
|
class Account
|
6
|
-
include
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
4
|
+
include DirtyValidAttr
|
5
|
+
|
6
|
+
dirty_valid_attr :account_number,
|
7
|
+
type: String
|
8
|
+
|
9
|
+
dirty_valid_attr :auto_pay,
|
10
|
+
type: Boolean,
|
11
|
+
required?: true
|
12
|
+
|
13
|
+
dirty_valid_attr :bill_to_contact,
|
14
|
+
type: Zuora::Models::Contact,
|
15
|
+
required?: true
|
16
|
+
|
17
|
+
dirty_valid_attr :bill_cycle_day,
|
18
|
+
type: String
|
19
|
+
|
20
|
+
dirty_valid_attr :crm_id,
|
21
|
+
type: String
|
22
|
+
|
23
|
+
dirty_valid_attr :currency,
|
24
|
+
type: String,
|
25
|
+
valid?: length(3)
|
26
|
+
|
27
|
+
dirty_valid_attr :credit_card,
|
28
|
+
type: Zuora::Models::PaymentMethods::CreditCard,
|
29
|
+
required?: true
|
30
|
+
|
31
|
+
dirty_valid_attr :name,
|
32
|
+
type: String
|
33
|
+
|
34
|
+
dirty_valid_attr :hpm_credit_card_payment_method_id,
|
35
|
+
type: String
|
36
|
+
|
37
|
+
dirty_valid_attr :notes,
|
38
|
+
type: String
|
39
|
+
|
40
|
+
dirty_valid_attr :invoice_template_id,
|
41
|
+
type: String
|
42
|
+
|
43
|
+
dirty_valid_attr :communication_profile_id,
|
44
|
+
type: String
|
45
|
+
|
46
|
+
dirty_valid_attr :payment_gateway,
|
47
|
+
type: String
|
48
|
+
|
49
|
+
dirty_valid_attr :payment_term,
|
50
|
+
type: String,
|
51
|
+
required?: true,
|
52
|
+
valid?: one_of(Zuora::PAYMENT_TERMS)
|
53
|
+
|
54
|
+
dirty_valid_attr :sold_to_contact,
|
55
|
+
type: Zuora::Models::Contact,
|
56
|
+
required?: true
|
57
|
+
|
58
|
+
dirty_valid_attr :subscription,
|
59
|
+
type: String
|
60
|
+
|
61
|
+
alias_method :initialize, :initialize_attributes!
|
51
62
|
end
|
52
63
|
end
|
53
64
|
end
|