jsmestad-chargify 0.3.0.pre5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +23 -0
- data/Gemfile +20 -0
- data/LICENSE +20 -0
- data/README.markdown +38 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/changelog.md +24 -0
- data/jsmestad-chargify.gemspec +97 -0
- data/lib/chargify.rb +22 -0
- data/lib/chargify/base.rb +88 -0
- data/lib/chargify/config.rb +86 -0
- data/lib/chargify/customer.rb +72 -0
- data/lib/chargify/error.rb +23 -0
- data/lib/chargify/parser.rb +13 -0
- data/lib/chargify/product.rb +26 -0
- data/lib/chargify/subscription.rb +93 -0
- data/lib/chargify/transaction.rb +14 -0
- data/spec/fixtures/charge_subscription.json +5 -0
- data/spec/fixtures/charge_subscription_missing_parameters.json +4 -0
- data/spec/fixtures/component.json +11 -0
- data/spec/fixtures/components.json +24 -0
- data/spec/fixtures/customer.json +12 -0
- data/spec/fixtures/customers.json +12 -0
- data/spec/fixtures/deleted_subscription.json +1 -0
- data/spec/fixtures/invalid_subscription.json +48 -0
- data/spec/fixtures/list_metered_subscriptions.json +3 -0
- data/spec/fixtures/migrate_subscription.json +51 -0
- data/spec/fixtures/new_customer.json +12 -0
- data/spec/fixtures/product.json +17 -0
- data/spec/fixtures/products.json +17 -0
- data/spec/fixtures/subscription.json +49 -0
- data/spec/fixtures/subscription_not_found.json +1 -0
- data/spec/fixtures/subscriptions.json +49 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/fakeweb_stubs.rb +33 -0
- data/spec/unit/chargify/config_spec.rb +147 -0
- data/spec/unit/chargify/customer_spec.rb +111 -0
- data/spec/unit/chargify/parser_spec.rb +7 -0
- data/spec/unit/chargify/product_spec.rb +35 -0
- data/spec/unit/chargify/subscription_spec.rb +304 -0
- data/spec/unit/chargify/transaction_spec.rb +11 -0
- metadata +154 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
module Chargify
|
2
|
+
class Customer < Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# options: page
|
7
|
+
def all(options={})
|
8
|
+
customers = api_request(:get, '/customers.json', :query => options)
|
9
|
+
customers.map{|c| Hashie::Mash.new c['customer']}
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(id)
|
13
|
+
return all if id == :all
|
14
|
+
|
15
|
+
request = api_request(:get, "/customers/#{id}.json")
|
16
|
+
success = request.code == 200
|
17
|
+
response = Hashie::Mash.new(request).customer if success
|
18
|
+
Hashie::Mash.new(response || {}).update(:success? => success)
|
19
|
+
end
|
20
|
+
|
21
|
+
# def find!(id)
|
22
|
+
# request = api_request(:get, "/customers/#{id}.json", :raise_errors => true)
|
23
|
+
# response = Hashie::Mash.new(request).customer
|
24
|
+
# end
|
25
|
+
|
26
|
+
def lookup(reference_id)
|
27
|
+
request = api_request(:get, "/customers/lookup.json?reference=#{reference_id}")
|
28
|
+
success = request.code == 200
|
29
|
+
response = Hashie::Mash.new(request).customer if success
|
30
|
+
Hashie::Mash.new(response || {}).update(:success? => success)
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# * first_name (Required)
|
35
|
+
# * last_name (Required)
|
36
|
+
# * email (Required)
|
37
|
+
# * organization (Optional) Company/Organization name
|
38
|
+
# * reference (Optional, but encouraged) The unique identifier used within your own application for this customer
|
39
|
+
#
|
40
|
+
def create(info={})
|
41
|
+
result = api_request(:post, "/customers.json", :body => {:customer => info})
|
42
|
+
created = true if result.code == 201
|
43
|
+
response = Hashie::Mash.new(result)
|
44
|
+
(response.customer || response).update(:success? => created)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# * first_name (Required)
|
49
|
+
# * last_name (Required)
|
50
|
+
# * email (Required)
|
51
|
+
# * organization (Optional) Company/Organization name
|
52
|
+
# * reference (Optional, but encouraged) The unique identifier used within your own application for this customer
|
53
|
+
#
|
54
|
+
def update(info={})
|
55
|
+
info.stringify_keys!
|
56
|
+
chargify_id = info.delete('id')
|
57
|
+
result = api_request(:put, "/customers/#{chargify_id}.json", :body => {:customer => info})
|
58
|
+
|
59
|
+
response = Hashie::Mash.new(result)
|
60
|
+
return response.customer unless response.customer.to_a.empty?
|
61
|
+
response
|
62
|
+
end
|
63
|
+
|
64
|
+
def subscriptions(id)
|
65
|
+
subscriptions = api_request(:get, "/customers/#{id}/subscriptions.json")
|
66
|
+
subscriptions.map{|s| Hashie::Mash.new s['subscription']}
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Chargify
|
2
|
+
module Error
|
3
|
+
|
4
|
+
class Base < StandardError
|
5
|
+
attr_reader :response
|
6
|
+
|
7
|
+
def initialize(response=nil)
|
8
|
+
@response = response
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AccessDenied < Base; end # 401 errors
|
13
|
+
class Forbidden < Base; end # 403 errors
|
14
|
+
class BadRequest < Base; end # 422 errors
|
15
|
+
class NotFound < Base; end # 404 errors
|
16
|
+
class GatewayTimeout < Base; end # 504 errors
|
17
|
+
class ConnectionFailed < Base; end
|
18
|
+
|
19
|
+
class UnexpectedResponse < Base; end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Chargify
|
2
|
+
class Product < Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def all
|
7
|
+
result = api_request(:get, "/products.json")
|
8
|
+
result.map{|p| Hashie::Mash.new p['product']}
|
9
|
+
end
|
10
|
+
|
11
|
+
def find(id)
|
12
|
+
return all if id == :all
|
13
|
+
|
14
|
+
result = api_request(:get, "/products/#{id}.json")
|
15
|
+
Hashie::Mash.new(result).product
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_by_handle(handle)
|
19
|
+
result = api_request(:get, "/products/handle/#{handle}.json")
|
20
|
+
Hashie::Mash.new(result).product
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Chargify
|
2
|
+
class Subscription < Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def find(id)
|
7
|
+
result = api_request(:get, "/subscriptions/#{id}.json")
|
8
|
+
return nil if result.code != 200
|
9
|
+
Hashie::Mash.new(result).subscription
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns all elements outputted by Chargify plus:
|
13
|
+
# response.success? -> true if response code is 201, false otherwise
|
14
|
+
def create(subscription_attributes={})
|
15
|
+
result = api_request(:post, "/subscriptions.json", :body => {:subscription => subscription_attributes})
|
16
|
+
created = true if result.code == 201
|
17
|
+
response = Hashie::Mash.new(result)
|
18
|
+
(response.subscription || response).update(:success? => created)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns all elements outputted by Chargify plus:
|
22
|
+
# response.success? -> true if response code is 200, false otherwise
|
23
|
+
def update(sub_id, subscription_attributes = {})
|
24
|
+
result = api_request(:put, "/subscriptions/#{sub_id}.json", :body => {:subscription => subscription_attributes})
|
25
|
+
updated = true if result.code == 200
|
26
|
+
response = Hashie::Mash.new(result)
|
27
|
+
(response.subscription || response).update(:success? => updated)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns all elements outputted by Chargify plus:
|
31
|
+
# response.success? -> true if response code is 200, false otherwise
|
32
|
+
def cancel(sub_id, message="")
|
33
|
+
result = api_request(:delete, "/subscriptions/#{sub_id}.json", :body => {:subscription => {:cancellation_message => message} })
|
34
|
+
deleted = true if result.code == 200
|
35
|
+
response = Hashie::Mash.new(result)
|
36
|
+
(response.subscription || response).update(:success? => deleted)
|
37
|
+
end
|
38
|
+
|
39
|
+
def reactivate(sub_id)
|
40
|
+
result = api_request(:put, "/subscriptions/#{sub_id}/reactivate.json", :body => "")
|
41
|
+
reactivated = true if result.code == 200
|
42
|
+
response = Hashie::Mash.new(result) rescue Hashie::Mash.new
|
43
|
+
(response.subscription || response).update(:success? => reactivated)
|
44
|
+
end
|
45
|
+
|
46
|
+
def charge(sub_id, subscription_attributes={})
|
47
|
+
result = api_request(:post, "/subscriptions/#{sub_id}/charges.json", :body => { :charge => subscription_attributes })
|
48
|
+
success = result.code == 201
|
49
|
+
result = {} if result.code == 404
|
50
|
+
|
51
|
+
response = Hashie::Mash.new(result)
|
52
|
+
(response.charge || response).update(:success? => success)
|
53
|
+
end
|
54
|
+
|
55
|
+
def migrate(sub_id, product_id)
|
56
|
+
result = api_request(:post, "/subscriptions/#{sub_id}/migrations.json", :body => {:product_id => product_id })
|
57
|
+
success = true if result.code == 200
|
58
|
+
response = Hashie::Mash.new(result)
|
59
|
+
(response.subscription || {}).update(:success? => success)
|
60
|
+
end
|
61
|
+
|
62
|
+
def transactions(sub_id, options={})
|
63
|
+
result = api_request(:get, "/subscriptions/#{sub_id}/transactions.json", :query => options)
|
64
|
+
result.map{|t| Hashie::Mash.new t['transaction']}
|
65
|
+
end
|
66
|
+
|
67
|
+
def components(subscription_id)
|
68
|
+
result = api_request(:get, "/subscriptions/#{subscription_id}/components.json")
|
69
|
+
result.map{|c| Hashie::Mash.new c['component']}
|
70
|
+
end
|
71
|
+
|
72
|
+
def find_component(subscription_id, component_id)
|
73
|
+
result = get("/subscriptions/#{subscription_id}/components/#{component_id}.json")
|
74
|
+
Hashie::Mash.new(result).component
|
75
|
+
end
|
76
|
+
|
77
|
+
def update_component(subscription_id, component_id, quantity)
|
78
|
+
result = api_request(:put, "/subscriptions/#{subscription_id}/components/#{component_id}.json", :body => {:component => {:allocated_quantity => quantity}})
|
79
|
+
result[:success?] = result.code == 200
|
80
|
+
Hashie::Mash.new(result)
|
81
|
+
end
|
82
|
+
|
83
|
+
def component_usage(subscription_id, component_id)
|
84
|
+
result = api_request(:get, "/subscriptions/#{subscription_id}/components/#{component_id}/usages.json")
|
85
|
+
success = result.code == 200
|
86
|
+
response = Hashie::Mash.new(result)
|
87
|
+
response.update(:success? => success)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"component": {
|
4
|
+
"kind": "quantity_based_component",
|
5
|
+
"name": "Extra Rubies",
|
6
|
+
"allocated_quantity": 42,
|
7
|
+
"subscription_id": 16,
|
8
|
+
"pricing_scheme": "per_unit",
|
9
|
+
"component_id": 84,
|
10
|
+
"unit_name": "band"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"component": {
|
15
|
+
"kind": "quantity_based_component",
|
16
|
+
"name": "IP addresses",
|
17
|
+
"allocated_quantity": 2,
|
18
|
+
"subscription_id": 16,
|
19
|
+
"pricing_scheme": "per_unit",
|
20
|
+
"component_id": 24,
|
21
|
+
"unit_name": "address"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"customer": {
|
3
|
+
"reference": "bradleyjoyce",
|
4
|
+
"updated_at": "2009-10-07T11:10:27-04:00",
|
5
|
+
"id": 16,
|
6
|
+
"organization": "Squeejee",
|
7
|
+
"first_name": "Bradley",
|
8
|
+
"last_name": "Joyce",
|
9
|
+
"email": "bradley@squeejee.com",
|
10
|
+
"created_at": "2009-10-07T11:10:27-04:00"
|
11
|
+
}
|
12
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
[{
|
2
|
+
"customer": {
|
3
|
+
"reference": "bradleyjoyce",
|
4
|
+
"updated_at": "2009-10-07T11:10:27-04:00",
|
5
|
+
"id": 16,
|
6
|
+
"organization": "Squeejee",
|
7
|
+
"first_name": "Bradley",
|
8
|
+
"last_name": "Joyce",
|
9
|
+
"email": "bradley@squeejee.com",
|
10
|
+
"created_at": "2009-10-07T11:10:27-04:00"
|
11
|
+
}
|
12
|
+
}]
|
@@ -0,0 +1 @@
|
|
1
|
+
{"created_at":"Tue Jan 26 18:40:32 -0600 2010","activated_at":"Tue Jan 26 18:40:33 -0600 2010","expires_at":null,"cancellation_message":"Optional message","trial_ended_at":null,"updated_at":"Tue Jan 26 18:40:35 -0600 2010","credit_card":{"card_type":"bogus","expiration_year":2013,"masked_card_number":"XXXX-XXXX-XXXX-1","expiration_month":3,"last_name":"Indicisive","first_name":"John"},"id":3642,"current_period_ends_at":"Fri Feb 26 18:40:32 -0600 2010","product":{"product_family":{"name":"ZipZoomAuto","handle":"zipzoomauto","accounting_code":null,"id":268,"description":""},"name":"Basic Plan","handle":"basic","price_in_cents":5000,"accounting_code":"","id":689,"interval":1,"description":"","interval_unit":"month"},"success?":true,"customer":{"reference":"11654","created_at":"Tue Jan 26 18:40:32 -0600 2010","updated_at":"Tue Jan 26 18:40:32 -0600 2010","id":3546,"last_name":"Indicisive","organization":null,"email":"john@doe.com","first_name":"John"},"trial_started_at":null,"balance_in_cents":0,"current_period_started_at":"Tue Jan 26 18:40:32 -0600 2010","state":"canceled"}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
"subscription": {
|
2
|
+
"customer": {
|
3
|
+
"reference": "bradleyjoyce",
|
4
|
+
"updated_at": "2009-10-07T11:10:27-04:00",
|
5
|
+
"id": 16,
|
6
|
+
"organization": "Squeejee",
|
7
|
+
"first_name": "Bradley",
|
8
|
+
"last_name": "Joyce",
|
9
|
+
"email": "bradley@squeejee.com",
|
10
|
+
"created_at": "2009-10-07T11:10:27-04:00"
|
11
|
+
},
|
12
|
+
"cancellation_message": null,
|
13
|
+
"updated_at": "2009-10-07T11:10:56-04:00",
|
14
|
+
"expires_at": null,
|
15
|
+
"activated_at": "2009-10-23T16:16:59-04:00",
|
16
|
+
"current_period_started_at": "2009-11-14T11:10:56-05:00",
|
17
|
+
"credit_card": {
|
18
|
+
"card_type": "bogus",
|
19
|
+
"expiration_year": 2015,
|
20
|
+
"masked_card_number": "XXXX-XXXX-XXXX-1",
|
21
|
+
"first_name": "Bradley",
|
22
|
+
"last_name": "Joyce",
|
23
|
+
"expiration_month": 7
|
24
|
+
},
|
25
|
+
"trial_ended_at": "2009-10-14T11:10:56-04:00",
|
26
|
+
"id": 14,
|
27
|
+
"product": {
|
28
|
+
"price_in_cents": 500,
|
29
|
+
"name": "Monthly",
|
30
|
+
"handle": "monthly",
|
31
|
+
"id": 8,
|
32
|
+
"accounting_code": "TSMO",
|
33
|
+
"product_family": {
|
34
|
+
"name": "TweetSaver",
|
35
|
+
"handle": "tweetsaver",
|
36
|
+
"id": 7,
|
37
|
+
"accounting_code": null
|
38
|
+
},
|
39
|
+
"interval_unit": "month",
|
40
|
+
"interval": 1
|
41
|
+
},
|
42
|
+
"current_period_ends_at": "2009-12-14T11:10:56-05:00",
|
43
|
+
"trial_started_at": "2009-10-07T11:10:56-04:00",
|
44
|
+
"balance_in_cents": 0,
|
45
|
+
"state": "active",
|
46
|
+
"created_at": "2009-10-07T11:10:56-04:00"
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
{
|
2
|
+
"subscription": {
|
3
|
+
"id": 123,
|
4
|
+
"state": "active",
|
5
|
+
"balance_in_cents": "auto generated",
|
6
|
+
"current_period_started_at": "auto generated",
|
7
|
+
"current_period_ends_at": "auto generated",
|
8
|
+
"activated_at": "auto generated",
|
9
|
+
"trial_ended_at": "auto generated",
|
10
|
+
"trial_started_at": "auto generated",
|
11
|
+
"expires_at": "auto generated",
|
12
|
+
"created_at": "auto generated",
|
13
|
+
"updated_at": "auto generated",
|
14
|
+
"cancellation_message": null,
|
15
|
+
"customer": {
|
16
|
+
"id": "auto generated",
|
17
|
+
"first_name": "your value",
|
18
|
+
"last_name": "your value",
|
19
|
+
"email": "your value",
|
20
|
+
"organization": "your value",
|
21
|
+
"reference": "your value",
|
22
|
+
"updated_at": "auto generated",
|
23
|
+
"created_at": "auto generated"
|
24
|
+
},
|
25
|
+
"product": {
|
26
|
+
"id": 354,
|
27
|
+
"name": "[@products.last.name]",
|
28
|
+
"handle": 354,
|
29
|
+
"price_in_cents": 1000,
|
30
|
+
"accounting_code": "[@products.last.accounting_code]",
|
31
|
+
"description": "your value",
|
32
|
+
"interval": 3600,
|
33
|
+
"interval_unit": "[@products.last.interval_unit]",
|
34
|
+
"product_family": {
|
35
|
+
"id": 15,
|
36
|
+
"name": "[@products.last.product_family.name]",
|
37
|
+
"handle": "[@products.last.product_family.handle]",
|
38
|
+
"accounting_code": "[@products.last.product_family.accounting_code]",
|
39
|
+
"description": "your value"
|
40
|
+
}
|
41
|
+
},
|
42
|
+
"credit_card": {
|
43
|
+
"first_name": "your value",
|
44
|
+
"last_name": "your value",
|
45
|
+
"masked_card_number": "your value",
|
46
|
+
"card_type": "auto generated",
|
47
|
+
"expiration_month": "your value",
|
48
|
+
"expiration_year": "your value"
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"customer": {
|
3
|
+
"created_at": "2009-11-18T10:56:22-05:00",
|
4
|
+
"email": "wynn.netherland@gmail.com",
|
5
|
+
"first_name": "Wynn",
|
6
|
+
"id": 333,
|
7
|
+
"last_name": "Netherland",
|
8
|
+
"organization": null,
|
9
|
+
"reference": null,
|
10
|
+
"updated_at": "2009-11-18T10:56:22-05:00"
|
11
|
+
}
|
12
|
+
}
|