dwolla-ruby 2.5.1 → 2.5.5
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.
- checksums.yaml +5 -13
- data/.gitignore +8 -8
- data/.travis.yml +7 -7
- data/Gemfile +1 -1
- data/README.md +154 -138
- data/Rakefile +8 -8
- data/dwolla-ruby.gemspec +27 -27
- data/examples/balance.rb +15 -15
- data/examples/contacts.rb +32 -32
- data/examples/fundingSources.rb +39 -39
- data/examples/oauth.rb +34 -34
- data/examples/offsiteGateway.rb +31 -31
- data/examples/transactions.rb +38 -38
- data/examples/users.rb +30 -30
- data/gemfiles/json.gemfile +2 -2
- data/lib/dwolla.rb +326 -326
- data/lib/dwolla/accounts.rb +21 -21
- data/lib/dwolla/balance.rb +15 -15
- data/lib/dwolla/contacts.rb +22 -22
- data/lib/dwolla/errors/api_connection_error.rb +3 -3
- data/lib/dwolla/errors/api_error.rb +3 -3
- data/lib/dwolla/errors/authentication_error.rb +3 -3
- data/lib/dwolla/errors/dwolla_error.rb +19 -19
- data/lib/dwolla/errors/invalid_request_error.rb +10 -10
- data/lib/dwolla/errors/missing_parameter_error.rb +3 -3
- data/lib/dwolla/exceptions.rb +4 -4
- data/lib/dwolla/funding_sources.rb +65 -65
- data/lib/dwolla/json.rb +20 -20
- data/lib/dwolla/oauth.rb +51 -51
- data/lib/dwolla/offsite_gateway.rb +152 -144
- data/lib/dwolla/register.rb +55 -55
- data/lib/dwolla/requests.rb +56 -56
- data/lib/dwolla/transactions.rb +71 -71
- data/lib/dwolla/users.rb +36 -36
- data/lib/dwolla/version.rb +3 -3
- data/test/test_dwolla.rb +197 -197
- data/test/test_helper.rb +423 -423
- metadata +17 -18
@@ -1,144 +1,152 @@
|
|
1
|
-
module Dwolla
|
2
|
-
class OffsiteGateway
|
3
|
-
@products = []
|
4
|
-
@discount = 0
|
5
|
-
@tax = 0
|
6
|
-
@shipping = 0
|
7
|
-
@notes = nil
|
8
|
-
@facilitator_amount = nil
|
9
|
-
@test_mode = false
|
10
|
-
@allow_funding_sources = true
|
11
|
-
@additional_funding_sources = true
|
12
|
-
@order_id = nil
|
13
|
-
|
14
|
-
def self.clear_session
|
15
|
-
@products = []
|
16
|
-
@discount = 0
|
17
|
-
@tax = 0
|
18
|
-
@shipping = 0
|
19
|
-
@notes = nil
|
20
|
-
@facilitator_amount = nil
|
21
|
-
@test_mode = false
|
22
|
-
@allow_funding_sources = true
|
23
|
-
@additional_funding_sources = true
|
24
|
-
@order_id = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
class << self
|
28
|
-
attr_writer :tax
|
29
|
-
attr_writer :shipping
|
30
|
-
attr_writer :notes
|
31
|
-
attr_writer :order_id
|
32
|
-
attr_writer :redirect
|
33
|
-
attr_writer :callback
|
34
|
-
attr_writer :test_mode
|
35
|
-
attr_writer :allow_funding_sources
|
36
|
-
attr_writer :additional_funding_sources
|
37
|
-
attr_writer :facilitator_amount
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.add_product(name=nil, description=nil, price=nil, quantity=1)
|
41
|
-
@products.push({
|
42
|
-
:name => name,
|
43
|
-
:description => description,
|
44
|
-
:price => price,
|
45
|
-
:quantity => quantity
|
46
|
-
})
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.set_customer_info(first_name=nil, last_name=nil, email=nil, city=nil, state=nil, zip=nil)
|
50
|
-
@customerInfo = {
|
51
|
-
:firstName => first_name,
|
52
|
-
:lastName => last_name,
|
53
|
-
:email => email,
|
54
|
-
:city => city,
|
55
|
-
:state => state,
|
56
|
-
:zip => zip
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.discount=(discount)
|
61
|
-
@discount = -(discount.abs)
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.get_checkout_url(destinationId)
|
65
|
-
params = {
|
66
|
-
:key => Dwolla::api_key,
|
67
|
-
:secret => Dwolla::api_secret,
|
68
|
-
:allowFundingSources => @allow_funding_sources,
|
69
|
-
:additionalFundingSources => @additional_funding_sources,
|
70
|
-
:test => @test_mode,
|
71
|
-
:callback => @callback,
|
72
|
-
:redirect => @redirect,
|
73
|
-
:orderId => @order_id,
|
74
|
-
:notes => @notes,
|
75
|
-
:purchaseOrder => {
|
76
|
-
:customerInfo => @customerInfo,
|
77
|
-
:destinationId => destinationId,
|
78
|
-
:orderItems => @products,
|
79
|
-
:facilitatorAmount => @facilitator_amount,
|
80
|
-
:discount => @discount,
|
81
|
-
:shipping => @shipping,
|
82
|
-
:tax => @tax,
|
83
|
-
:total => self.calculate_total
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
|
-
resp = Dwolla.request(:post, request_url, params, {}, false, false, true)
|
88
|
-
raise APIError.new(resp['Message']) unless resp['Result'] == 'Success'
|
89
|
-
|
90
|
-
return checkout_url + resp['CheckoutId']
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.read_callback(body)
|
94
|
-
data = JSON.load(body)
|
95
|
-
|
96
|
-
verify_callback_signature(data['Signature'], data['CheckoutId'], data['Amount'])
|
97
|
-
|
98
|
-
return data
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.validate_webhook(signature, body)
|
102
|
-
verify_webhook_signature(signature, body)
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def self.verify_callback_signature(candidate=nil, checkout_id=nil, amount=nil)
|
108
|
-
key = "#{checkout_id}&#{amount}"
|
109
|
-
digest = OpenSSL::Digest::Digest.new('sha1')
|
110
|
-
signature = OpenSSL::HMAC.hexdigest(digest, Dwolla::api_secret, key)
|
111
|
-
|
112
|
-
raise APIError.new("Invalid callback signature (#{candidate} vs #{signature})") unless candidate == signature
|
113
|
-
end
|
114
|
-
|
115
|
-
def self.verify_webhook_signature(candidate=nil, body=nil)
|
116
|
-
digest = OpenSSL::Digest::Digest.new('sha1')
|
117
|
-
signature = OpenSSL::HMAC.hexdigest(digest, Dwolla::api_secret, body)
|
118
|
-
|
119
|
-
raise APIError.new("Invalid Webhook signature (#{candidate} vs #{signature})") unless candidate == signature
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.request_url
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
def self.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
total
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
1
|
+
module Dwolla
|
2
|
+
class OffsiteGateway
|
3
|
+
@products = []
|
4
|
+
@discount = 0
|
5
|
+
@tax = 0
|
6
|
+
@shipping = 0
|
7
|
+
@notes = nil
|
8
|
+
@facilitator_amount = nil
|
9
|
+
@test_mode = false
|
10
|
+
@allow_funding_sources = true
|
11
|
+
@additional_funding_sources = true
|
12
|
+
@order_id = nil
|
13
|
+
|
14
|
+
def self.clear_session
|
15
|
+
@products = []
|
16
|
+
@discount = 0
|
17
|
+
@tax = 0
|
18
|
+
@shipping = 0
|
19
|
+
@notes = nil
|
20
|
+
@facilitator_amount = nil
|
21
|
+
@test_mode = false
|
22
|
+
@allow_funding_sources = true
|
23
|
+
@additional_funding_sources = true
|
24
|
+
@order_id = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
attr_writer :tax
|
29
|
+
attr_writer :shipping
|
30
|
+
attr_writer :notes
|
31
|
+
attr_writer :order_id
|
32
|
+
attr_writer :redirect
|
33
|
+
attr_writer :callback
|
34
|
+
attr_writer :test_mode
|
35
|
+
attr_writer :allow_funding_sources
|
36
|
+
attr_writer :additional_funding_sources
|
37
|
+
attr_writer :facilitator_amount
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.add_product(name=nil, description=nil, price=nil, quantity=1)
|
41
|
+
@products.push({
|
42
|
+
:name => name,
|
43
|
+
:description => description,
|
44
|
+
:price => price,
|
45
|
+
:quantity => quantity
|
46
|
+
})
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.set_customer_info(first_name=nil, last_name=nil, email=nil, city=nil, state=nil, zip=nil)
|
50
|
+
@customerInfo = {
|
51
|
+
:firstName => first_name,
|
52
|
+
:lastName => last_name,
|
53
|
+
:email => email,
|
54
|
+
:city => city,
|
55
|
+
:state => state,
|
56
|
+
:zip => zip
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.discount=(discount)
|
61
|
+
@discount = -(discount.abs)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.get_checkout_url(destinationId)
|
65
|
+
params = {
|
66
|
+
:key => Dwolla::api_key,
|
67
|
+
:secret => Dwolla::api_secret,
|
68
|
+
:allowFundingSources => @allow_funding_sources,
|
69
|
+
:additionalFundingSources => @additional_funding_sources,
|
70
|
+
:test => @test_mode,
|
71
|
+
:callback => @callback,
|
72
|
+
:redirect => @redirect,
|
73
|
+
:orderId => @order_id,
|
74
|
+
:notes => @notes,
|
75
|
+
:purchaseOrder => {
|
76
|
+
:customerInfo => @customerInfo,
|
77
|
+
:destinationId => destinationId,
|
78
|
+
:orderItems => @products,
|
79
|
+
:facilitatorAmount => @facilitator_amount,
|
80
|
+
:discount => @discount,
|
81
|
+
:shipping => @shipping,
|
82
|
+
:tax => @tax,
|
83
|
+
:total => self.calculate_total
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
resp = Dwolla.request(:post, request_url, params, {}, false, false, true)
|
88
|
+
raise APIError.new(resp['Message']) unless resp['Result'] == 'Success'
|
89
|
+
|
90
|
+
return checkout_url + resp['CheckoutId']
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.read_callback(body)
|
94
|
+
data = JSON.load(body)
|
95
|
+
|
96
|
+
verify_callback_signature(data['Signature'], data['CheckoutId'], data['Amount'])
|
97
|
+
|
98
|
+
return data
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.validate_webhook(signature, body)
|
102
|
+
verify_webhook_signature(signature, body)
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def self.verify_callback_signature(candidate=nil, checkout_id=nil, amount=nil)
|
108
|
+
key = "#{checkout_id}&#{amount}"
|
109
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
110
|
+
signature = OpenSSL::HMAC.hexdigest(digest, Dwolla::api_secret, key)
|
111
|
+
|
112
|
+
raise APIError.new("Invalid callback signature (#{candidate} vs #{signature})") unless candidate == signature
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.verify_webhook_signature(candidate=nil, body=nil)
|
116
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
117
|
+
signature = OpenSSL::HMAC.hexdigest(digest, Dwolla::api_secret, body)
|
118
|
+
|
119
|
+
raise APIError.new("Invalid Webhook signature (#{candidate} vs #{signature})") unless candidate == signature
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.request_url
|
123
|
+
if Dwolla::sandbox
|
124
|
+
return 'https://uat.dwolla.com/payment/request'
|
125
|
+
else
|
126
|
+
return 'https://www.dwolla.com/payment/request'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.checkout_url
|
131
|
+
if Dwolla::sandbox
|
132
|
+
return 'https://uat.dwolla.com/payment/request'
|
133
|
+
else
|
134
|
+
return 'https://www.dwolla.com/payment/request'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.calculate_total
|
139
|
+
total = 0.0
|
140
|
+
|
141
|
+
@products.each { |product|
|
142
|
+
total += product[:price] * product[:quantity]
|
143
|
+
}
|
144
|
+
|
145
|
+
total += @shipping
|
146
|
+
total += @tax
|
147
|
+
total += @discount
|
148
|
+
|
149
|
+
return total.round(2)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/lib/dwolla/register.rb
CHANGED
@@ -1,55 +1,55 @@
|
|
1
|
-
module Dwolla
|
2
|
-
class Register
|
3
|
-
def self.step(token=nil)
|
4
|
-
url = register_url + 'step'
|
5
|
-
|
6
|
-
Dwolla.request(:get, url, {}, {}, token)
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.create(token=nil)
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.resend_email(token=nil)
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.verify_email(token=nil)
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.add_phone(token=nil)
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.resend_phone(token=nil)
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.verify_phone(token=nil)
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.set_address(token=nil)
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.get_kba(token=nil)
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.answer_kba(token=nil)
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.set_general_info(token=nil)
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def self.register_url
|
52
|
-
return '/register/'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
1
|
+
module Dwolla
|
2
|
+
class Register
|
3
|
+
def self.step(token=nil)
|
4
|
+
url = register_url + 'step'
|
5
|
+
|
6
|
+
Dwolla.request(:get, url, {}, {}, token)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create(token=nil)
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.resend_email(token=nil)
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.verify_email(token=nil)
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.add_phone(token=nil)
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.resend_phone(token=nil)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.verify_phone(token=nil)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.set_address(token=nil)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get_kba(token=nil)
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.answer_kba(token=nil)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.set_general_info(token=nil)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def self.register_url
|
52
|
+
return '/register/'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/dwolla/requests.rb
CHANGED
@@ -1,56 +1,56 @@
|
|
1
|
-
module Dwolla
|
2
|
-
class Requests
|
3
|
-
def self.get(id=nil, filters={}, token=nil)
|
4
|
-
url = requests_url
|
5
|
-
|
6
|
-
if id.is_a?(Hash)
|
7
|
-
filters = id
|
8
|
-
id = nil
|
9
|
-
else
|
10
|
-
filters = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
url += id.to_s unless id.nil?
|
14
|
-
|
15
|
-
Dwolla.request(:get, url, filters, {}, token)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.delete(id=nil, token=nil)
|
19
|
-
raise MissingParameterError.new('No Request ID Provided.') if id.nil?
|
20
|
-
|
21
|
-
url = requests_url + id.to_s + '/cancel'
|
22
|
-
|
23
|
-
Dwolla.request(:post, url, {}, {}, token)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.create(params={}, token=nil)
|
27
|
-
raise MissingParameterError.new('No Source ID Provided.') unless params[:sourceId]
|
28
|
-
raise MissingParameterError.new('No Amount Provided.') unless params[:amount]
|
29
|
-
|
30
|
-
url = requests_url
|
31
|
-
|
32
|
-
Dwolla.request(:post, url, params, {}, token)
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.fulfill(id=nil, params={}, token=nil)
|
36
|
-
raise MissingParameterError.new('No Request ID Provided.') if id.nil?
|
37
|
-
raise MissingParameterError.new('No PIN Provided.') unless params[:pin]
|
38
|
-
|
39
|
-
url = requests_url + id.to_s + '/fulfill'
|
40
|
-
|
41
|
-
Dwolla.request(:post, url, params, {}, token)
|
42
|
-
end
|
43
|
-
|
44
|
-
class << self
|
45
|
-
alias_method :pending, :get
|
46
|
-
alias_method :cancel, :delete
|
47
|
-
alias_method :request, :create
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def self.requests_url
|
53
|
-
return '/requests/'
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
1
|
+
module Dwolla
|
2
|
+
class Requests
|
3
|
+
def self.get(id=nil, filters={}, token=nil)
|
4
|
+
url = requests_url
|
5
|
+
|
6
|
+
if id.is_a?(Hash)
|
7
|
+
filters = id
|
8
|
+
id = nil
|
9
|
+
else
|
10
|
+
filters = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
url += id.to_s unless id.nil?
|
14
|
+
|
15
|
+
Dwolla.request(:get, url, filters, {}, token)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.delete(id=nil, token=nil)
|
19
|
+
raise MissingParameterError.new('No Request ID Provided.') if id.nil?
|
20
|
+
|
21
|
+
url = requests_url + id.to_s + '/cancel'
|
22
|
+
|
23
|
+
Dwolla.request(:post, url, {}, {}, token)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.create(params={}, token=nil)
|
27
|
+
raise MissingParameterError.new('No Source ID Provided.') unless params[:sourceId]
|
28
|
+
raise MissingParameterError.new('No Amount Provided.') unless params[:amount]
|
29
|
+
|
30
|
+
url = requests_url
|
31
|
+
|
32
|
+
Dwolla.request(:post, url, params, {}, token)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.fulfill(id=nil, params={}, token=nil)
|
36
|
+
raise MissingParameterError.new('No Request ID Provided.') if id.nil?
|
37
|
+
raise MissingParameterError.new('No PIN Provided.') unless params[:pin]
|
38
|
+
|
39
|
+
url = requests_url + id.to_s + '/fulfill'
|
40
|
+
|
41
|
+
Dwolla.request(:post, url, params, {}, token)
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
alias_method :pending, :get
|
46
|
+
alias_method :cancel, :delete
|
47
|
+
alias_method :request, :create
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.requests_url
|
53
|
+
return '/requests/'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|