balanced 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/CONTRIBUTORS +4 -0
- data/Gemfile +3 -0
- data/Guardfile +7 -0
- data/README.md +31 -2
- data/balanced.gemspec +4 -1
- data/examples/examples.rb +18 -2
- data/lib/balanced.rb +16 -25
- data/lib/balanced/client.rb +16 -39
- data/lib/balanced/resources.rb +13 -241
- data/lib/balanced/resources/account.rb +134 -0
- data/lib/balanced/resources/api_key.rb +18 -0
- data/lib/balanced/resources/bank_account.rb +34 -0
- data/lib/balanced/resources/card.rb +34 -0
- data/lib/balanced/resources/credit.rb +20 -0
- data/lib/balanced/resources/debit.rb +42 -0
- data/lib/balanced/resources/hold.rb +42 -0
- data/lib/balanced/resources/marketplace.rb +77 -0
- data/lib/balanced/resources/merchant.rb +25 -0
- data/lib/balanced/resources/refund.rb +21 -0
- data/lib/balanced/resources/resource.rb +130 -0
- data/lib/balanced/resources/transaction.rb +18 -0
- data/lib/balanced/version.rb +1 -1
- data/spec/balanced/resources/account_spec.rb +422 -0
- data/spec/balanced/resources/api_key_spec.rb +55 -0
- data/spec/balanced/resources/marketplace_spec.rb +97 -0
- data/spec/balanced_spec.rb +73 -12
- data/spec/client_spec.rb +2 -2
- data/spec/spec_helper.rb +24 -0
- data/spec/utils_spec.rb +2 -2
- metadata +85 -7
- data/lib/balanced/base.rb +0 -129
- data/spec/api_key_spec.rb +0 -20
@@ -0,0 +1,134 @@
|
|
1
|
+
module Balanced
|
2
|
+
# An Account represents a user within your Marketplace. An Account can have
|
3
|
+
# two +roles+. If the Account has the +buyer+ role then you may create
|
4
|
+
# Debits using this Account. If they have the +merchant+ role then you may
|
5
|
+
# create Credits to transfer funds to this Account.
|
6
|
+
#
|
7
|
+
class Account
|
8
|
+
include Balanced::Resource
|
9
|
+
|
10
|
+
def initialize attributes = {}
|
11
|
+
Balanced::Utils.stringify_keys! attributes
|
12
|
+
unless attributes.has_key? 'uri'
|
13
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
14
|
+
end
|
15
|
+
super attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a new Debit that represents a flow of money from this
|
19
|
+
# Account to your Marketplace.
|
20
|
+
#
|
21
|
+
# @return [Debit]
|
22
|
+
def debit (amount=nil,
|
23
|
+
appears_on_statement_as=nil,
|
24
|
+
hold_uri=nil,
|
25
|
+
meta={},
|
26
|
+
description=nil,
|
27
|
+
source_uri=nil)
|
28
|
+
debit = Debit.new(
|
29
|
+
:uri => self.debits_uri,
|
30
|
+
:amount => amount,
|
31
|
+
:appears_on_statement_as => appears_on_statement_as,
|
32
|
+
:hold_uri => hold_uri,
|
33
|
+
:meta => meta,
|
34
|
+
:description => description,
|
35
|
+
:source_uri => source_uri,
|
36
|
+
)
|
37
|
+
debit.save
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a new Hold that represents a reservation of money on this
|
41
|
+
# Account which can be transferred via a Debit to your Marketplace
|
42
|
+
# up to 7 days later.
|
43
|
+
#
|
44
|
+
# @param [String] source_uri A specific funding source such as a Card
|
45
|
+
# associated with this account. If not specified the most recently
|
46
|
+
# added Card is used.
|
47
|
+
# @return [Hold] A Hold representing the reservation of funds from
|
48
|
+
# this Account to your Marketplace.
|
49
|
+
def hold amount, meta={}, source_uri=nil
|
50
|
+
hold = Hold.new(
|
51
|
+
:uri => self.holds_uri,
|
52
|
+
:amount => amount,
|
53
|
+
:meta => meta,
|
54
|
+
:source_uri => source_uri,
|
55
|
+
)
|
56
|
+
hold.save
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a new Credit representing a transfer of funds from your
|
60
|
+
# Marketplace to this Account.
|
61
|
+
#
|
62
|
+
# @param [String] destination_uri A specific funding destination such as
|
63
|
+
# a BankAccount already associated with this account.
|
64
|
+
# @return [Credit] A Credit representing the transfer of funds from
|
65
|
+
# your Marketplace to this Account.
|
66
|
+
def credit amount, description=nil, meta={}, destination_uri=nil
|
67
|
+
credit = Credit.new(
|
68
|
+
:uri => self.credits_uri,
|
69
|
+
:amount => amount,
|
70
|
+
:meta => meta,
|
71
|
+
:description => description,
|
72
|
+
:destination_uri => destination_uri,
|
73
|
+
)
|
74
|
+
credit.save
|
75
|
+
end
|
76
|
+
|
77
|
+
# Associates the Card represented by +card_uri+ with this Account.
|
78
|
+
#
|
79
|
+
# @return [Card]
|
80
|
+
def add_card card_uri
|
81
|
+
self.card_uri = card_uri
|
82
|
+
save
|
83
|
+
end
|
84
|
+
|
85
|
+
# Associates the BankAccount represented by +bank_account_uri+ with this
|
86
|
+
# Account.
|
87
|
+
#
|
88
|
+
# @return [BankAccount]
|
89
|
+
def add_bank_account bank_account_uri
|
90
|
+
self.bank_account_uri = bank_account_uri
|
91
|
+
save
|
92
|
+
end
|
93
|
+
|
94
|
+
# Adds the role Merchant to this Account.
|
95
|
+
#
|
96
|
+
# The merchant data for a *person* should look like:
|
97
|
+
#
|
98
|
+
# {
|
99
|
+
# :type => "person",
|
100
|
+
# :name => "William James", # Legal name
|
101
|
+
# :street_address => "167 West 74th Street",
|
102
|
+
# :postal_code => "10023",
|
103
|
+
# :country_code => "USA", # ISO 3166-1 alpha-3
|
104
|
+
# :dob => "1842-01",
|
105
|
+
# :phone_number => "+16505551234"
|
106
|
+
# }
|
107
|
+
#
|
108
|
+
# For a *business*, the payload should look like:
|
109
|
+
#
|
110
|
+
# {
|
111
|
+
# :name => "Levain Bakery",
|
112
|
+
# :tax_id => "253912384", # Optional
|
113
|
+
# :street_address => "167 West 74th Street",
|
114
|
+
# :postal_code => "10023",
|
115
|
+
# :phone_number => "+16505551234",
|
116
|
+
# :country_code => "USA", # ISO 3166-1 alpha-3
|
117
|
+
# :person => {
|
118
|
+
# :name => "William James", # Legal name
|
119
|
+
# :tax_id => "393483992", # Optional
|
120
|
+
# :street_address => "167 West 74th Street", # Home address
|
121
|
+
# :postal_code => "10023",
|
122
|
+
# :dob => "1842-01-01",
|
123
|
+
# :phone_number => "+16505551234",
|
124
|
+
# :country_code => "USA" # ISO 3166-1 alpha-3
|
125
|
+
# }
|
126
|
+
# }
|
127
|
+
#
|
128
|
+
def promote_to_merchant merchant_data
|
129
|
+
self.merchant = merchant_data
|
130
|
+
save
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Balanced
|
2
|
+
|
3
|
+
# Your ApiKey is used to authenticate when performing operations on the
|
4
|
+
# Balanced API.
|
5
|
+
#
|
6
|
+
# *NOTE:* Never give out or expose your ApiKey. You may POST to this
|
7
|
+
# endpoint to create new ApiKeys and then DELETE any old keys.
|
8
|
+
class ApiKey
|
9
|
+
include Balanced::Resource
|
10
|
+
|
11
|
+
def save
|
12
|
+
Balanced.configure nil
|
13
|
+
super
|
14
|
+
end
|
15
|
+
def wut; end;
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A BankAccount is both a source, and a destination of, funds. You may
|
3
|
+
# create Debits and Credits to and from, this funding source.
|
4
|
+
#
|
5
|
+
# *NOTE:* The BankAccount resource does not support creating a Hold.
|
6
|
+
#
|
7
|
+
class BankAccount
|
8
|
+
include Balanced::Resource
|
9
|
+
|
10
|
+
def initialize attributes = {}
|
11
|
+
Balanced::Utils.stringify_keys! attributes
|
12
|
+
unless attributes.has_key? 'uri'
|
13
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
14
|
+
end
|
15
|
+
super attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
# Creates a Debit of funds from this BankAccount to your Marketplace.
|
19
|
+
#
|
20
|
+
# @param [String] appears_on_statement_as If nil then Balanced will use
|
21
|
+
# the +domain_name+ property from your Marketplace.
|
22
|
+
# @return [Debit]
|
23
|
+
def debit amount, appears_on_statement_as=nil, meta={}, description=nil
|
24
|
+
self.account.debit(amount, appears_on_statement_as, meta, description, self.uri)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates a Credit of funds from your Marketplace to this Account.
|
28
|
+
#
|
29
|
+
# @return [Credit]
|
30
|
+
def credit amount, description=nil, meta={}
|
31
|
+
self.account.credit(amount, description, meta, self.uri)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A card represents a source of funds for an Account. You may Hold or Debit
|
3
|
+
# funds from the account associated with the Card.
|
4
|
+
#
|
5
|
+
class Card
|
6
|
+
include Balanced::Resource
|
7
|
+
|
8
|
+
def initialize attributes = {}
|
9
|
+
Balanced::Utils.stringify_keys! attributes
|
10
|
+
unless attributes.has_key? 'uri'
|
11
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
12
|
+
end
|
13
|
+
super attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates a Debit of funds from this Card to your Marketplace.
|
17
|
+
#
|
18
|
+
# If +appears_on_statement_as+ is nil, then Balanced will use the
|
19
|
+
# +domain_name+ property from your Marketplace.
|
20
|
+
#
|
21
|
+
# @return [Debit]
|
22
|
+
def debit amount=nil, appears_on_statement_as=nil, holds_uri=nil, meta={}, description=nil
|
23
|
+
self.account.debit(amount, appears_on_statement_as, holds_uri, meta, description, self.uri)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a Hold of funds from this Card to your Marketplace.
|
27
|
+
#
|
28
|
+
# @return [Hold]
|
29
|
+
def hold amount=nil, meta=nil
|
30
|
+
self.account.hold(amount, meta, self.uri)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A Credit represents a transfer of funds from your Marketplace to a
|
3
|
+
# Merchant's Account within your Marketplace.
|
4
|
+
#
|
5
|
+
# By default, a Credit is sent to the most recently added funding
|
6
|
+
# destination associated with an Account. You may specify a specific
|
7
|
+
# funding source.
|
8
|
+
#
|
9
|
+
class Credit
|
10
|
+
include Balanced::Resource
|
11
|
+
def initialize attributes = {}
|
12
|
+
Balanced::Utils.stringify_keys! attributes
|
13
|
+
unless attributes.has_key? 'uri'
|
14
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
15
|
+
end
|
16
|
+
super attributes
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A Debit represents a transfer of funds from a buyer's Account to your
|
3
|
+
# Marketplace.
|
4
|
+
#
|
5
|
+
# A Debit may be created directly, or it will be created as a side-effect
|
6
|
+
# of capturing a Hold. If you create a Debit directly it will implicitly
|
7
|
+
# create the associated Hold if the funding source supports this.
|
8
|
+
#
|
9
|
+
# If no Hold is specified the Debit will by default be created using the
|
10
|
+
# most recently added funding source associated with the Account. You
|
11
|
+
# cannot change the funding source between creating a Hold and capturing
|
12
|
+
# it.
|
13
|
+
#
|
14
|
+
class Debit
|
15
|
+
include Balanced::Resource
|
16
|
+
|
17
|
+
def initialize attributes = {}
|
18
|
+
Balanced::Utils.stringify_keys! attributes
|
19
|
+
unless attributes.has_key? 'uri'
|
20
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
21
|
+
end
|
22
|
+
super attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
# Refunds this Debit. If no amount is specified it will refund the entire
|
26
|
+
# amount of the Debit, you may create many Refunds up to the sum total
|
27
|
+
# of the original Debit's amount.
|
28
|
+
#
|
29
|
+
# @return [Refund]
|
30
|
+
def refund amount=nil, description=nil
|
31
|
+
refund = Refund.new(
|
32
|
+
:uri => self.refunds_uri,
|
33
|
+
:debit_uri => self.uri,
|
34
|
+
:amount => amount,
|
35
|
+
:description => description,
|
36
|
+
)
|
37
|
+
refund.save
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A Hold is a reservation of funds on a funding source such as a Card. This
|
3
|
+
# reservation is guaranteed until the +expires_at+ date. You may capture
|
4
|
+
# the Hold at any time before then which will create a Debit and transfer
|
5
|
+
# the funds to your Marketplace. If you do not capture the Hold it will
|
6
|
+
# be marked as invalid which is represented by the +is_void+ field being
|
7
|
+
# set to +true+.
|
8
|
+
#
|
9
|
+
# By default a Hold is created using the most recently added funding source
|
10
|
+
# on the Account. You may specify a specific funding source such as a Card
|
11
|
+
# or BankAccount uri.
|
12
|
+
#
|
13
|
+
class Hold
|
14
|
+
include Balanced::Resource
|
15
|
+
|
16
|
+
def initialize attributes = {}
|
17
|
+
Balanced::Utils.stringify_keys! attributes
|
18
|
+
unless attributes.has_key? 'uri'
|
19
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
20
|
+
end
|
21
|
+
super attributes
|
22
|
+
end
|
23
|
+
|
24
|
+
# Cancels an active Hold.
|
25
|
+
#
|
26
|
+
def void
|
27
|
+
@is_void = true
|
28
|
+
save
|
29
|
+
end
|
30
|
+
|
31
|
+
# Captures a valid Hold and returns a Debit representing the transfer of
|
32
|
+
# funds from the buyer's Account to your Marketplace.
|
33
|
+
#
|
34
|
+
# @return [Debit]
|
35
|
+
def capture amount=nil, appears_on_statement_as=nil, meta={}, description=nil
|
36
|
+
amount ||= self.amount
|
37
|
+
self.account.debit(amount, appears_on_statement_as, self.uri, meta, description)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Balanced
|
2
|
+
#
|
3
|
+
#
|
4
|
+
class Marketplace
|
5
|
+
include Balanced::Resource
|
6
|
+
|
7
|
+
# Returns an instance representing the marketplace associated with
|
8
|
+
# the current API key.
|
9
|
+
#
|
10
|
+
# @return [Marketplace]
|
11
|
+
def self.my_marketplace
|
12
|
+
# TODO: use query
|
13
|
+
response = Balanced.get collection_path
|
14
|
+
return nil if response.body.to_s.length.zero? or response.body['total'] == 0
|
15
|
+
payload = response.body
|
16
|
+
construct_from_response payload['items'][0]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an instance representing the marketplace associated with
|
20
|
+
# the current API key.
|
21
|
+
#
|
22
|
+
# @return [Marketplace]
|
23
|
+
def my_marketplace
|
24
|
+
self.class.my_marketplace
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create a buyer Account associated with this Marketplace.
|
28
|
+
#
|
29
|
+
# @return [Account]
|
30
|
+
def create_buyer email_address, card_uri, name=nil, meta={}
|
31
|
+
account = Account.new(
|
32
|
+
:uri => self.accounts_uri,
|
33
|
+
:email_address => email_address,
|
34
|
+
:card_uri => card_uri,
|
35
|
+
:name => name,
|
36
|
+
:meta => meta,
|
37
|
+
)
|
38
|
+
account.save
|
39
|
+
end
|
40
|
+
|
41
|
+
# Creates a Merchant Account associated with this Marketplace.
|
42
|
+
#
|
43
|
+
# This method may return 300 if you have not supplied enough information
|
44
|
+
# for Balanced to identify the Merchant. You may re-submit the request
|
45
|
+
# with more information, or redirect the Merchant to the supplied url
|
46
|
+
# so they may manually sign up.
|
47
|
+
#
|
48
|
+
# When you receive a merchant_uri from balanced, just pass it in:
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# Account.create_merchant('bob@example.com', '/v1/TEST-MRxxxx')
|
52
|
+
#
|
53
|
+
# @return [Account]
|
54
|
+
def create_merchant email_address, merchant, bank_account_uri=nil, name=nil, meta={}
|
55
|
+
account_attributes = Hash.new(
|
56
|
+
:uri => self.accounts_uri,
|
57
|
+
:email_address => email_address,
|
58
|
+
:bank_account_uri => bank_account_uri,
|
59
|
+
:name => name,
|
60
|
+
:meta => meta,
|
61
|
+
)
|
62
|
+
|
63
|
+
if merchant.is_a? Hash
|
64
|
+
account_attributes[:merchant] = merchant
|
65
|
+
else
|
66
|
+
account_attributes[:merchant_uri] = merchant
|
67
|
+
end
|
68
|
+
|
69
|
+
account_attributes
|
70
|
+
account = Account.new account_attributes
|
71
|
+
account.save
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Balanced
|
2
|
+
class Merchant
|
3
|
+
include Balanced::Resource
|
4
|
+
|
5
|
+
# Returns the Merchant associated with your Marketplace.
|
6
|
+
#
|
7
|
+
# @return [Merchant]
|
8
|
+
def self.me
|
9
|
+
# TODO: use query
|
10
|
+
response = Balanced.get collection_path
|
11
|
+
return nil if response.body.to_s.length.zero? or response.body['total'] == 0
|
12
|
+
payload = response.body
|
13
|
+
construct_from_response payload['items'][0]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the Merchant associated with your Marketplace.
|
17
|
+
#
|
18
|
+
# @return [Merchant]
|
19
|
+
def me
|
20
|
+
self.class.me
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Balanced
|
2
|
+
# A Refund represents a reversal of funds from a Debit. A Debit can have
|
3
|
+
# many Refunds associated with it up to the total amount of the original
|
4
|
+
# Debit. Funds are returned to your Marketplace's Merchant Account
|
5
|
+
# proportional to the amoun of the Refund.
|
6
|
+
#
|
7
|
+
class Refund
|
8
|
+
include Balanced::Resource
|
9
|
+
|
10
|
+
def initialize attributes = {}
|
11
|
+
Balanced::Utils.stringify_keys! attributes
|
12
|
+
unless attributes.has_key? 'uri'
|
13
|
+
attributes['uri'] = Balanced::Marketplace.my_marketplace.send(self.class.collection_name + '_uri')
|
14
|
+
end
|
15
|
+
super attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|