shushu 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,7 +9,10 @@ module Shushu
9
9
  end
10
10
 
11
11
  def headers
12
- {:content_type => :json, :accept => :json}
12
+ {
13
+ :content_type => :json,
14
+ :accept => :json
15
+ }
13
16
  end
14
17
 
15
18
  def enc_json(hash)
@@ -26,19 +29,8 @@ module Shushu
26
29
  dec_json(resp.body)
27
30
  rescue RestClient::Exception => e
28
31
  body = dec_json(e.http_body)
29
- case e.http_code
30
- when 404
31
- when 401
32
- raise(AuthorizationError, "Response: #{body.inspect}")
33
- when 403
34
- when 409
35
- when 500
36
- raise(UnexpectedError, "Response: #{body.inspect}")
37
- when 503
38
- raise(ServiceDownError, "#{Shushu.url} is down for maintenance.")
39
- else
40
- raise(UnexpectedError, "Response: #{body.inspect}")
41
- end
32
+ code = e.http_code
33
+ raise(ShushuException, "Error in HTTP request. code=#{code} body=#{body}")
42
34
  end
43
35
  end
44
36
 
@@ -0,0 +1,20 @@
1
+ module Shushu
2
+ module PMethod
3
+ extend self
4
+
5
+ def create(args)
6
+ Shushu.handle_req {RestClient.post(p_method_url, args, Shushu.headers)}
7
+ end
8
+
9
+ def update(args)
10
+ id = args.delete(:id)
11
+ Shushu.handle_req {RestClient.put(p_method_url(id), args, Shushu.headers)}
12
+ end
13
+
14
+ def p_method_url(id=nil)
15
+ url = [Shushu.url, "/payment_methods"].join
16
+ id.nil? ? url : url << "/#{id}"
17
+ end
18
+
19
+ end
20
+ end
@@ -17,7 +17,7 @@ module Shushu
17
17
  eid = args.delete(:entity_id)
18
18
  hid = args[:hid]
19
19
  time = args[:time]
20
- Shushu.handle_req {RestClient.delete([res_own_url(aid, eid), build_q_params(:hid => hid, :time => time)].join)}
20
+ Shushu.handle_req {RestClient.delete([res_own_url(aid, eid), Shushu::HttpHelpers.build_q_params(:hid => hid, :time => time)].join)}
21
21
  end
22
22
 
23
23
  def query(args)
data/lib/shushu.rb CHANGED
@@ -13,12 +13,7 @@ module Shushu
13
13
  extend self
14
14
  extend HttpHelpers
15
15
 
16
- ShushuException = Class.new(Exception)
17
- AuthenticationError = Class.new(ShushuException)
18
- AuthorizationError = Class.new(ShushuException)
19
- ServiceDownError = Class.new(ShushuException)
20
- UnexpectedError = Class.new(ShushuException)
21
- SymanticError = Class.new(ShushuException)
16
+ ShushuException = Class.new(Exception)
22
17
 
23
18
  def url
24
19
  Client.url
@@ -58,6 +53,7 @@ require "models/res_own"
58
53
  require "models/r_code"
59
54
  require "models/rev_rep"
60
55
  require "models/heart_beat"
56
+ require "models/p_method"
61
57
 
62
58
  require "services/line_item_builder"
63
59
 
data/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Shushu Client
2
2
 
3
- This gem wraps the APIs defined [here](https://github.com/heroku/shushud/tree/master/doc).
3
+ This gem wraps the [Shushu API](https://github.com/heroku/shushud/tree/master/doc).
4
4
  The shushu client also provides a set of objects that help with the presentation
5
5
  of an invoice.
6
6
 
@@ -8,91 +8,115 @@ of an invoice.
8
8
 
9
9
  ```bash
10
10
  $ gem install shushu
11
+ $ export SHUSHU_URL=https://123:secret@shushu.heroku.com
11
12
  ```
12
13
 
13
- ```bash
14
- # Optional. When set, shushu will ignore bad responses from Shushu's API.
15
- # Default: false
14
+ ## Usage
16
15
 
17
- $SHUSHU_CLIENT_UNSAFE=true
18
- ```
16
+ There are two ways to interact with Shushu APIs using this client. The first
17
+ approach will rely on the credentials in `SHUSHU_URL`.
19
18
 
20
- ```bash
21
- # Required
22
- # Default: nil
23
-
24
- $SHUSHU_URL=https://shushu-stg.heroku.com
19
+ ```ruby
20
+ Shushu::BEvent.open({})
25
21
  ```
26
22
 
27
- **Ruby configuration will take precedence over environment variables.**
23
+ The second approach allows for credentials other than the ones stored in the
24
+ `SHUSHU_URL`.
28
25
 
29
26
  ```ruby
30
- Shushu.url = "https://core:secret@shushu-stg.heroku.com"
27
+ shushu = Shushu::Client.new("https://other_provider_id:other_provider_token@shushu.heroku.com")
28
+ shushu[:b_event].open({})
31
29
  ```
32
30
 
33
- ## Usage
31
+ ### PaymentMethod
32
+
33
+ This API deals primarily with credit cards. PaymentMethods can be created
34
+ indipendintly of Accounts. You will need a payment_method to generate an
35
+ invoice.
34
36
 
35
- You can call methods in models directly via the model's module or you can create
36
- a client object to dispatch methods to the model. This is useful if want to use
37
- provider credentials other than the ones defined in the `$SHUSHU_URL`
37
+ Reference: [PaymentMethod API](https://github.com/heroku/shushud/blob/master/doc/payment_methods_api.md)
38
+
39
+ Create a new payment method with encrypted values:
38
40
 
39
41
  ```ruby
40
- shushu = Shushu::Client.new("https://other_provider_id:other_provider_token@shushu.heroku.com")
41
- shushu[:b_event].open({})
42
+ PMethod.create(
43
+ :card_num => "some encrypted value",
44
+ :card_exp_year => "2012",
45
+ :card_exp_month => "12"
46
+ )
47
+ #=> {:id => "12345", :card_token => "abc123", :card_type => "visa", :card_last4 => "1111"}
42
48
  ```
43
- Is equivalent to:
49
+
50
+ Update a payment_method with a new credit card:
44
51
 
45
52
  ```ruby
46
- Shushu::BEvent.open({})
53
+ PMethod.update(
54
+ :id => "001",
55
+ :card_num => "some encrypted value",
56
+ :card_exp_year => "2012",
57
+ :card_exp_month => "12"
58
+ )
59
+ #=> {:id => "001", :card_token => "abc123", :card_type => "visa", :card_last4 => "1111"}
47
60
  ```
48
61
 
49
- ### PaymentMethods
62
+ Create a new payment_method with a token. Note, this endpoint is idempotent with
63
+ respect to the id and token.
50
64
 
51
- This API deals primarily with credit cards. PaymentMethods can be created
52
- indipendintly of Accounts. You will need a payment_method to generate an
53
- invoice.
65
+ ```ruby
66
+ PMethod.update(:id => "my-custom-id", :card_token => "abc123")
67
+ #=> {:id => "my-custom-id", :card_token => "abc123"}
68
+ ```
69
+ ```
70
+
71
+ To mark a payment_method in such a way that credit card processing will be
72
+ disabled:
54
73
 
55
74
  ```ruby
56
- #TODO Build API
75
+ PMethod.update(:id => "001", :non_receivable => true)
76
+ #=> {:id => "001", :non_receivable => true}
57
77
  ```
58
78
 
59
- ### Accounts
79
+ ### Account
60
80
 
61
81
  This API deals with accounts which is a primitive for grouping resources. You
62
82
  will need an account to generate a usage report.
63
83
 
64
84
  ```ruby
65
- Shushu::Account.create
66
- #=> {:id => "001"}
85
+ Shushu::Account.create
86
+ #=> {:id => "001"}
67
87
  ```
68
88
 
69
- ### AccountOwnerships
89
+ ### AccountOwnership
70
90
 
71
- Use this API when you want to setup associations between Vault accounts and
72
- Vault payment_methods.
91
+ Use this API when you want to setup associations between Shushu accounts and
92
+ Shushu payment_methods.
73
93
 
74
94
  Reference: [AccountOwnerships API](https://github.com/heroku/shushud/blob/master/doc/account_ownership_api.md)
75
95
 
96
+ To associate an account with a payment_method:
97
+
76
98
  ```ruby
77
- # To associate an account with a payment_method
78
- Shushu::AcctOwn.act(
79
- :account_id => vault_account_id,
80
- :payment_method_id => payment_method_id,
81
- :entity_id => entity_id,
82
- :time => time
83
- )
84
- #=> {"payment_method_id"=>"123", "account_id"=>"1", "entity_id"=>"entity123"}
85
-
86
- # Now we need to change the payment_method on an account
87
- Shushu::AcctOwn.xfr(
88
- :prev_payment_method_id => prev_payment_method_id,
89
- :payment_method_id => new_payment_method_id,
90
- :account_id => account_id,
91
- :prev_entity_id => prev_entity_id,
92
- :entity_id => entity_id,
93
- :time => time
94
- )
95
- #=> {"payment_method_id"=>"456", "account_id"=>"1", "entity_id"=>"event124"}
99
+ Shushu::AcctOwn.act(
100
+ :account_id => vault_account_id,
101
+ :payment_method_id => payment_method_id,
102
+ :entity_id => entity_id,
103
+ :time => time
104
+ )
105
+ #=> {"payment_method_id"=>"123", "account_id"=>"1", "entity_id"=>"entity123"}
106
+ ```
107
+
108
+ Now we need to change the payment_method on an account:
109
+
110
+ ```ruby
111
+ Shushu::AcctOwn.xfr(
112
+ :prev_payment_method_id => prev_payment_method_id,
113
+ :payment_method_id => new_payment_method_id,
114
+ :account_id => account_id,
115
+ :prev_entity_id => prev_entity_id,
116
+ :entity_id => entity_id,
117
+ :time => time
118
+ )
119
+ #=> {"payment_method_id"=>"456", "account_id"=>"1", "entity_id"=>"event124"}
96
120
  ```
97
121
 
98
122
  ### RateCode
@@ -107,12 +131,12 @@ RateCode.
107
131
  Reference: [RateCode API](https://github.com/heroku/shushud/blob/master/doc/rate_code_api.md)
108
132
 
109
133
  ```ruby
110
- Shushu::RCode.create(
111
- :rate => 5,
112
- :product_group => "addon",
113
- :product_name => "postgres"
114
- )
115
- #=> {:slug => "AO01", :rate => 5, :product_group => "addon", :product_name => "postgres"}
134
+ Shushu::RCode.create(
135
+ :rate => 5,
136
+ :product_group => "addon",
137
+ :product_name => "postgres"
138
+ )
139
+ #=> {:slug => "AO01", :rate => 5, :product_group => "addon", :product_name => "postgres"}
116
140
  ```
117
141
 
118
142
  ### ResourceOwnership
@@ -122,36 +146,42 @@ Heroku apps and Teams.
122
146
 
123
147
  Reference: [ResourceOwnership API](https://github.com/heroku/shushud/blob/master/doc/resource_ownership_api.md)
124
148
 
149
+ When a new app is created, activate a new resource_ownership record.
150
+
125
151
  ```ruby
126
- # When a new app is created, activate a new resource_ownership record.
127
- Shushu::ResOwn.act(
128
- :hid => hid,
129
- :entity_id => entity_id,
130
- :account_id => vault_account_id,
131
- :time => time
132
- )
133
- #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
152
+ Shushu::ResOwn.act(
153
+ :hid => hid,
154
+ :entity_id => entity_id,
155
+ :account_id => vault_account_id,
156
+ :time => time
157
+ )
158
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
159
+ ```
134
160
 
161
+ When an app is transfered to another vault account, transfer the resource_ownership record.
135
162
 
136
- # When an app is transfered to another vault account, transfer the resource_ownership record.
137
- Shushu::ResOwn.xfr(
138
- :hid => hid,
139
- :prev_entity_id => prev_entity_id,
140
- :prev_vault_account_id => prev_vault_account_id,
141
- :entity_id => entity_id,
142
- :account_id => new_vault_account_id,
143
- :time => time
144
- )
145
- #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
146
-
147
- # When an app is destroyed, deactivate the resource_ownership record.
148
- Shushu::ResOwn.deact(
149
- :hid => hid,
150
- :entity_id => entity_id,
151
- :account_id => vault_account_id,
152
- :time => time
153
- )
154
- #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
163
+ ```ruby
164
+ Shushu::ResOwn.xfr(
165
+ :hid => hid,
166
+ :prev_entity_id => prev_entity_id,
167
+ :prev_vault_account_id => prev_vault_account_id,
168
+ :entity_id => entity_id,
169
+ :account_id => new_vault_account_id,
170
+ :time => time
171
+ )
172
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
173
+ ```
174
+
175
+ When an app is destroyed, deactivate the resource_ownership record.
176
+
177
+ ```ruby
178
+ Shushu::ResOwn.deact(
179
+ :hid => hid,
180
+ :entity_id => entity_id,
181
+ :account_id => vault_account_id,
182
+ :time => time
183
+ )
184
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
155
185
  ```
156
186
 
157
187
  ### BillableEvent
@@ -161,42 +191,42 @@ emitting events prior to setting up relationships between accounts and
161
191
  payment_methods. (Although, usage reports and invoices will not be available
162
192
  until account_ownerships and resource_ownerships have been established.)
163
193
 
164
- For complete details on the semantics of this API, read the [BillableEvents
165
- API docs.](https://github.com/heroku/shushu/blob/master/doc/events_api.md)
166
-
167
194
  Reference: [BillableEvent API](https://github.com/heroku/shushud/blob/master/doc/billable_events_api.md)
168
195
 
196
+ Open an event when you would like to start billing.
197
+
169
198
  ```ruby
170
- # Open an event when you would like to start billing.
171
- Shushu::BEvent.open(
172
- :entity_id => entity_id,
173
- :hid => hid,
174
- :time => time,
175
- :rate_code => rate_code,
176
- :product_name => product_name,
177
- :qty => qty
178
- )
199
+ Shushu::BEvent.open(
200
+ :entity_id => entity_id,
201
+ :hid => hid,
202
+ :time => time,
203
+ :rate_code => rate_code,
204
+ :product_name => product_name,
205
+ :qty => qty
206
+ )
207
+ ```
208
+
209
+ Don't forget to close it.
179
210
 
180
- # Don't forget to close it.
211
+ ```ruby
181
212
  Shushu::BEvent.close(
182
213
  :entity_id => entity_id,
183
214
  :time => time
184
215
  )
185
216
  ```
186
217
 
187
- ### UsageReports
218
+ ### UsageReport
188
219
 
189
220
  ```ruby
190
- report = Shushu::UsageReport.new(account_id, from, to)
191
- report.billable_units
221
+ report = Shushu::UsageReport.new(account_id, from, to)
222
+ report.billable_units
192
223
  ```
193
224
 
194
-
195
- ### Invoices
225
+ ### Invoice
196
226
 
197
227
  ```ruby
198
- invoice = Shushu::UsageReport.new(account_id, from, to)
199
- invoice.billable_units
228
+ invoice = Shushu::UsageReport.new(account_id, from, to)
229
+ invoice.billable_units
200
230
  ```
201
231
 
202
232
 
@@ -237,7 +267,7 @@ You can customize the LineItemBuilder by creating a new class that responds to
237
267
  build and passing it to the ReportPresenter.
238
268
 
239
269
  ```ruby
240
- ReportPresenter.new(report, CustomLineItemBuilder)
270
+ ReportPresenter.new(report, CustomLineItemBuilder)
241
271
  ```
242
272
 
243
273
  #### LineItemPresenter
@@ -248,12 +278,10 @@ LineItemBuilder partitioned unit_groups based upon product_group, you can ask
248
278
  the LineItemPresenter for infomation about subsets of unit_groups. For instance:
249
279
 
250
280
  ```ruby
251
- line_item_presenter.unit_group_presenters("dyno")
252
- line_item_presenter.unit_group_total("dyno")
253
- line_item_presenter.unit_group_qty("dyno")
281
+ line_item_presenter.unit_group_presenters("dyno")
282
+ line_item_presenter.unit_group_total("dyno")
283
+ line_item_presenter.unit_group_qty("dyno")
254
284
  ```
255
-
256
-
257
285
  #### UnitGroupPresenter
258
286
 
259
287
  UnitGroups are collections of billable_units that are partitioned by
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class PMethodTest < ShushuTest
4
+
5
+ def test_create
6
+ params = {
7
+ :card_token => "abc123"
8
+ }
9
+ api_resp_body = Shushu::HttpHelpers.enc_json(params)
10
+ Shushu.url = "http://provider:password@shushu.heroku.com"
11
+ FakeWeb.register_uri(:post, (Shushu.url + "/payment_methods"), :body => api_resp_body)
12
+ response = Shushu::PMethod.create(params)
13
+ assert_equal("abc123", response["card_token"])
14
+ end
15
+
16
+ def test_update
17
+ params = {
18
+ :id => "1",
19
+ :card_token => "abc123"
20
+ }
21
+ api_resp_body = Shushu::HttpHelpers.enc_json(params)
22
+ Shushu.url = "http://provider:password@shushu.heroku.com"
23
+ FakeWeb.register_uri(:put, (Shushu.url + "/payment_methods/1"), :body => api_resp_body)
24
+ response = Shushu::PMethod.update(params)
25
+ assert_equal("abc123", response["card_token"])
26
+ assert_equal("1", response["id"])
27
+ end
28
+
29
+ end
@@ -4,7 +4,7 @@ class RevRepTest < ShushuTest
4
4
  def test_for_month
5
5
  api_resp_body = Shushu::HttpHelpers.enc_json({:ok => true})
6
6
  Shushu.url = "http://provider:password@shushu.heroku.com"
7
- url = Shushu.url + "/rev_rep?from%3D2011-01-01+00%3A00%3A00+UTC&to%3D2011-02-01+00%3A00%3A00+UTC"
7
+ url = Shushu.url + "/rev_report?from=2011-01-01+00%3A00%3A00+UTC&to=2011-02-01+00%3A00%3A00+UTC"
8
8
  FakeWeb.register_uri(:get, url, :body => api_resp_body)
9
9
  Shushu::RevRep.get(Time.utc(2011,1), Time.utc(2011,2))
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shushu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
16
- requirement: &8914300 !ruby/object:Gem::Requirement
16
+ requirement: &7563340 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *8914300
24
+ version_requirements: *7563340
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: yajl-ruby
27
- requirement: &8913620 !ruby/object:Gem::Requirement
27
+ requirement: &7555000 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 1.1.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *8913620
35
+ version_requirements: *7555000
36
36
  description: A ruby wrapper around Shushu's HTTP API.
37
37
  email: ryan@heroku.com
38
38
  executables: []
@@ -50,6 +50,7 @@ files:
50
50
  - lib/models/acct_own.rb
51
51
  - lib/models/report.rb
52
52
  - lib/models/unit_group.rb
53
+ - lib/models/p_method.rb
53
54
  - lib/models/rev_rep.rb
54
55
  - lib/models/line_item.rb
55
56
  - lib/models/heart_beat.rb
@@ -66,6 +67,7 @@ files:
66
67
  - test/models/billable_unit_test.rb
67
68
  - test/models/b_event_test.rb
68
69
  - test/models/unit_group_test.rb
70
+ - test/models/p_method_test.rb
69
71
  - test/models/rev_rep_test.rb
70
72
  - test/models/line_item_test.rb
71
73
  - test/services/line_item_builder_test.rb
@@ -101,6 +103,7 @@ test_files:
101
103
  - test/models/billable_unit_test.rb
102
104
  - test/models/b_event_test.rb
103
105
  - test/models/unit_group_test.rb
106
+ - test/models/p_method_test.rb
104
107
  - test/models/rev_rep_test.rb
105
108
  - test/models/line_item_test.rb
106
109
  - test/services/line_item_builder_test.rb