dwolla-ruby 2.6.4 → 2.6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +8 -8
- data/.travis.yml +6 -6
- data/Gemfile +1 -1
- data/README.md +198 -192
- 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 +59 -50
- data/examples/offsiteGateway.rb +31 -31
- data/examples/transactions.rb +72 -38
- data/examples/users.rb +30 -30
- data/gemfiles/json.gemfile +2 -2
- data/lib/dwolla.rb +326 -326
- data/lib/dwolla/accounts.rb +27 -27
- data/lib/dwolla/balance.rb +15 -15
- data/lib/dwolla/contacts.rb +30 -30
- 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/masspay.rb +52 -52
- data/lib/dwolla/oauth.rb +83 -75
- data/lib/dwolla/offsite_gateway.rb +152 -152
- data/lib/dwolla/requests.rb +56 -56
- data/lib/dwolla/transactions.rb +111 -56
- data/lib/dwolla/users.rb +39 -39
- data/lib/dwolla/version.rb +3 -3
- data/test/test_accounts.rb +18 -18
- data/test/test_balance.rb +9 -9
- data/test/test_contacts.rb +19 -19
- data/test/test_funding_sources.rb +64 -64
- data/test/test_masspay.rb +47 -47
- data/test/test_oauth.rb +36 -30
- data/test/test_offsite_gateway.rb +57 -57
- data/test/test_requests.rb +29 -29
- data/test/test_transactions.rb +117 -51
- data/test/test_users.rb +33 -33
- metadata +21 -21
data/examples/users.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
# Include the Dwolla gem
|
2
|
-
require 'rubygems'
|
3
|
-
require 'pp'
|
4
|
-
require 'dwolla'
|
5
|
-
|
6
|
-
# Include any required keys
|
7
|
-
require '_keys.rb'
|
8
|
-
|
9
|
-
# Instantiate a new Dwolla User client
|
10
|
-
# And, seed a previously generated access token
|
11
|
-
Dwolla::token = @token
|
12
|
-
Dwolla::api_key = @api_key
|
13
|
-
Dwolla::api_secret = @api_secret
|
14
|
-
|
15
|
-
# EXAMPLE 1:
|
16
|
-
# Fetch account information for the
|
17
|
-
# account associated with the provided
|
18
|
-
# OAuth token
|
19
|
-
pp Dwolla::Users.get
|
20
|
-
|
21
|
-
|
22
|
-
# EXAMPLE 2:
|
23
|
-
# Fetch basic account information
|
24
|
-
# for a given Dwolla ID
|
25
|
-
pp Dwolla::Users.get('812-626-8794')
|
26
|
-
|
27
|
-
|
28
|
-
# EXAMPLE 3:
|
29
|
-
# Fetch basic account information
|
30
|
-
# for a given Email address
|
1
|
+
# Include the Dwolla gem
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pp'
|
4
|
+
require 'dwolla'
|
5
|
+
|
6
|
+
# Include any required keys
|
7
|
+
require '_keys.rb'
|
8
|
+
|
9
|
+
# Instantiate a new Dwolla User client
|
10
|
+
# And, seed a previously generated access token
|
11
|
+
Dwolla::token = @token
|
12
|
+
Dwolla::api_key = @api_key
|
13
|
+
Dwolla::api_secret = @api_secret
|
14
|
+
|
15
|
+
# EXAMPLE 1:
|
16
|
+
# Fetch account information for the
|
17
|
+
# account associated with the provided
|
18
|
+
# OAuth token
|
19
|
+
pp Dwolla::Users.get
|
20
|
+
|
21
|
+
|
22
|
+
# EXAMPLE 2:
|
23
|
+
# Fetch basic account information
|
24
|
+
# for a given Dwolla ID
|
25
|
+
pp Dwolla::Users.get('812-626-8794')
|
26
|
+
|
27
|
+
|
28
|
+
# EXAMPLE 3:
|
29
|
+
# Fetch basic account information
|
30
|
+
# for a given Email address
|
31
31
|
pp Dwolla::Users.get('michael@dwolla.com')
|
data/gemfiles/json.gemfile
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
gemspec :path => File.join(File.dirname(__FILE__), "..")
|
1
|
+
source "https://rubygems.org"
|
2
|
+
gemspec :path => File.join(File.dirname(__FILE__), "..")
|
3
3
|
gem "json"
|
data/lib/dwolla.rb
CHANGED
@@ -1,326 +1,326 @@
|
|
1
|
-
# Dwolla Ruby API Wrapper
|
2
|
-
# Heavily based off Stripe's Ruby Gem
|
3
|
-
# API spec at https://developers.dwolla.com
|
4
|
-
require 'openssl'
|
5
|
-
require 'rest_client'
|
6
|
-
require 'multi_json'
|
7
|
-
require 'addressable/uri'
|
8
|
-
|
9
|
-
# Version
|
10
|
-
require_relative 'dwolla/version'
|
11
|
-
|
12
|
-
# Resources
|
13
|
-
require_relative 'dwolla/json'
|
14
|
-
require_relative 'dwolla/transactions'
|
15
|
-
require_relative 'dwolla/requests'
|
16
|
-
require_relative 'dwolla/contacts'
|
17
|
-
require_relative 'dwolla/users'
|
18
|
-
require_relative 'dwolla/balance'
|
19
|
-
require_relative 'dwolla/funding_sources'
|
20
|
-
require_relative 'dwolla/oauth'
|
21
|
-
require_relative 'dwolla/offsite_gateway'
|
22
|
-
require_relative 'dwolla/accounts'
|
23
|
-
require_relative 'dwolla/masspay'
|
24
|
-
|
25
|
-
# Errors
|
26
|
-
require_relative 'dwolla/errors/dwolla_error'
|
27
|
-
require_relative 'dwolla/errors/api_connection_error'
|
28
|
-
require_relative 'dwolla/errors/api_error'
|
29
|
-
require_relative 'dwolla/errors/missing_parameter_error'
|
30
|
-
require_relative 'dwolla/errors/authentication_error'
|
31
|
-
require_relative 'dwolla/errors/invalid_request_error'
|
32
|
-
|
33
|
-
module Dwolla
|
34
|
-
@@api_key = nil
|
35
|
-
@@api_secret = nil
|
36
|
-
@@token = nil
|
37
|
-
@@api_base = '/oauth/rest'
|
38
|
-
@@verify_ssl_certs = true
|
39
|
-
@@api_version = nil
|
40
|
-
@@debug = false
|
41
|
-
@@sandbox = false
|
42
|
-
@@scope = 'send|transactions|balance|request|contacts|accountinfofull|funding'
|
43
|
-
|
44
|
-
def self.api_key=(api_key)
|
45
|
-
@@api_key = api_key
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.api_key
|
49
|
-
@@api_key
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.api_secret=(api_secret)
|
53
|
-
@@api_secret = api_secret
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.api_secret
|
57
|
-
@@api_secret
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.sandbox=(sandbox)
|
61
|
-
@@sandbox = sandbox
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.sandbox
|
65
|
-
@@sandbox
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.debug
|
69
|
-
@@debug
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.debug=(debug)
|
73
|
-
@@debug = debug
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.api_version=(api_version)
|
77
|
-
@@api_version = api_version
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.api_version
|
81
|
-
@@api_version
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.verify_ssl_certs=(verify_ssl_certs)
|
85
|
-
@@verify_ssl_certs = verify_ssl_certs
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.verify_ssl_certs
|
89
|
-
@@verify_ssl_certs
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.token=(token)
|
93
|
-
@@token = token
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.token
|
97
|
-
@@token
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.scope=(scope)
|
101
|
-
@@scope = scope
|
102
|
-
end
|
103
|
-
|
104
|
-
def self.scope
|
105
|
-
@@scope
|
106
|
-
end
|
107
|
-
|
108
|
-
def self.hostname
|
109
|
-
if not @@sandbox
|
110
|
-
return 'https://www.dwolla.com'
|
111
|
-
else
|
112
|
-
return 'https://uat.dwolla.com'
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.endpoint_url(endpoint)
|
117
|
-
self.hostname + @@api_base + endpoint
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.request(method, url, params={}, headers={}, oauth=true, parse_response=true, custom_url=false)
|
121
|
-
# if oauth is nil, assume default [true]
|
122
|
-
oauth = true if oauth.nil?
|
123
|
-
|
124
|
-
# figure out which auth to use
|
125
|
-
if oauth and not params[:oauth_token]
|
126
|
-
if not oauth.is_a?(TrueClass) # was token passed in the oauth param?
|
127
|
-
params = {
|
128
|
-
:oauth_token => oauth
|
129
|
-
}.merge(params)
|
130
|
-
else
|
131
|
-
raise AuthenticationError.new('No OAuth Token Provided.') unless token
|
132
|
-
params = {
|
133
|
-
:oauth_token => token
|
134
|
-
}.merge(params)
|
135
|
-
end
|
136
|
-
elsif oauth and params[:oauth_token]
|
137
|
-
raise AuthenticationError.new('No OAuth Token Provided.') unless params[:oauth_token]
|
138
|
-
else not oauth
|
139
|
-
raise AuthenticationError.new('No App Key & Secret Provided.') unless (api_key && api_secret)
|
140
|
-
params = {
|
141
|
-
:client_id => api_key,
|
142
|
-
:client_secret => api_secret
|
143
|
-
}.merge(params)
|
144
|
-
end
|
145
|
-
|
146
|
-
if !verify_ssl_certs
|
147
|
-
$stderr.puts "WARNING: Running without SSL cert verification."
|
148
|
-
else
|
149
|
-
ssl_opts = {
|
150
|
-
:use_ssl => true
|
151
|
-
}
|
152
|
-
end
|
153
|
-
|
154
|
-
uname = (@@uname ||= RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
|
155
|
-
lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
156
|
-
ua = {
|
157
|
-
:bindings_version => Dwolla::VERSION,
|
158
|
-
:lang => 'ruby',
|
159
|
-
:lang_version => lang_version,
|
160
|
-
:platform => RUBY_PLATFORM,
|
161
|
-
:publisher => 'dwolla',
|
162
|
-
:uname => uname
|
163
|
-
}
|
164
|
-
|
165
|
-
url = self.endpoint_url(url) unless custom_url
|
166
|
-
|
167
|
-
case method.to_s.downcase.to_sym
|
168
|
-
when :get
|
169
|
-
# Make params into GET parameters
|
170
|
-
if params && params.count > 0
|
171
|
-
uri = Addressable::URI.new
|
172
|
-
uri.query_values = params
|
173
|
-
url += '?' + uri.query
|
174
|
-
end
|
175
|
-
payload = nil
|
176
|
-
else
|
177
|
-
payload = JSON.dump(params)
|
178
|
-
end
|
179
|
-
|
180
|
-
begin
|
181
|
-
headers = { :x_dwolla_client_user_agent => Dwolla::JSON.dump(ua) }.merge(headers)
|
182
|
-
rescue => e
|
183
|
-
headers = {
|
184
|
-
:x_dwolla_client_raw_user_agent => ua.inspect,
|
185
|
-
:error => "#{e} (#{e.class})"
|
186
|
-
}.merge(headers)
|
187
|
-
end
|
188
|
-
|
189
|
-
headers = {
|
190
|
-
:user_agent => "Dwolla Ruby API Wrapper/#{Dwolla::VERSION}",
|
191
|
-
:content_type => 'application/json'
|
192
|
-
}.merge(headers)
|
193
|
-
|
194
|
-
if self.api_version
|
195
|
-
headers[:dwolla_version] = self.api_version
|
196
|
-
end
|
197
|
-
|
198
|
-
opts = {
|
199
|
-
:method => method,
|
200
|
-
:url => url,
|
201
|
-
:headers => headers,
|
202
|
-
:open_timeout => 30,
|
203
|
-
:payload => payload,
|
204
|
-
:timeout => 80
|
205
|
-
}.merge(ssl_opts)
|
206
|
-
|
207
|
-
if self.debug
|
208
|
-
if self.sandbox
|
209
|
-
puts "[DWOLLA SANDBOX MODE OPERATION]"
|
210
|
-
end
|
211
|
-
|
212
|
-
puts "Firing request with options and headers:"
|
213
|
-
puts opts
|
214
|
-
puts headers
|
215
|
-
end
|
216
|
-
|
217
|
-
begin
|
218
|
-
response = execute_request(opts)
|
219
|
-
rescue SocketError => e
|
220
|
-
self.handle_restclient_error(e)
|
221
|
-
rescue NoMethodError => e
|
222
|
-
# Work around RestClient bug
|
223
|
-
if e.message =~ /\WRequestFailed\W/
|
224
|
-
e = APIConnectionError.new('Unexpected HTTP response code')
|
225
|
-
self.handle_restclient_error(e)
|
226
|
-
else
|
227
|
-
raise
|
228
|
-
end
|
229
|
-
rescue RestClient::ExceptionWithResponse => e
|
230
|
-
if rcode = e.http_code and rbody = e.http_body
|
231
|
-
self.handle_api_error(rcode, rbody)
|
232
|
-
else
|
233
|
-
self.handle_restclient_error(e)
|
234
|
-
end
|
235
|
-
rescue RestClient::Exception, Errno::ECONNREFUSED => e
|
236
|
-
self.handle_restclient_error(e)
|
237
|
-
end
|
238
|
-
|
239
|
-
rbody = response.body
|
240
|
-
rcode = response.code
|
241
|
-
|
242
|
-
if self.debug
|
243
|
-
puts "Raw response headers received:"
|
244
|
-
puts headers
|
245
|
-
puts "Raw response body received:"
|
246
|
-
puts rbody
|
247
|
-
end
|
248
|
-
|
249
|
-
resp = self.extract_json(rbody, rcode)
|
250
|
-
|
251
|
-
if parse_response
|
252
|
-
return self.parse_response(resp)
|
253
|
-
else
|
254
|
-
return resp
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
private
|
259
|
-
|
260
|
-
def self.execute_request(opts)
|
261
|
-
RestClient::Request.execute(opts)
|
262
|
-
end
|
263
|
-
|
264
|
-
def self.extract_json(rbody, rcode)
|
265
|
-
begin
|
266
|
-
resp = Dwolla::JSON.load(rbody)
|
267
|
-
rescue MultiJson::DecodeError
|
268
|
-
raise APIError.new("There was an error parsing Dwolla's API response: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
|
269
|
-
end
|
270
|
-
|
271
|
-
return resp
|
272
|
-
end
|
273
|
-
|
274
|
-
def self.parse_response(resp)
|
275
|
-
raise APIError.new(resp['Message']) unless resp.has_key?('Success') and resp['Success'] == true
|
276
|
-
|
277
|
-
return resp['Response']
|
278
|
-
end
|
279
|
-
|
280
|
-
def self.handle_api_error(rcode, rbody)
|
281
|
-
begin
|
282
|
-
error_obj = Dwolla::JSON.load(rbody)
|
283
|
-
error = error_obj[:error] or raise DwollaError.new # escape from parsing
|
284
|
-
rescue MultiJson::DecodeError, DwollaError
|
285
|
-
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
|
286
|
-
end
|
287
|
-
|
288
|
-
case rcode
|
289
|
-
when 400, 404 then
|
290
|
-
raise invalid_request_error(error, rcode, rbody, error_obj)
|
291
|
-
when 401
|
292
|
-
raise authentication_error(error, rcode, rbody, error_obj)
|
293
|
-
else
|
294
|
-
raise api_error(error, rcode, rbody, error_obj)
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
def self.invalid_request_error(error, rcode, rbody, error_obj)
|
299
|
-
InvalidRequestError.new(error[:message], error[:param], rcode, rbody, error_obj)
|
300
|
-
end
|
301
|
-
|
302
|
-
def self.authentication_error(error, rcode, rbody, error_obj)
|
303
|
-
AuthenticationError.new(error[:message], rcode, rbody, error_obj)
|
304
|
-
end
|
305
|
-
|
306
|
-
def self.api_error(error, rcode, rbody, error_obj)
|
307
|
-
APIError.new(error[:message], rcode, rbody, error_obj)
|
308
|
-
end
|
309
|
-
|
310
|
-
def self.handle_restclient_error(e)
|
311
|
-
case e
|
312
|
-
when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
|
313
|
-
message = "Could not connect to Dwolla (#{@@api_base}). Please check your internet connection and try again. If this problem persists, you should check Dwolla's service status at https://twitter.com/Dwolla, or let us know at support@Dwolla.com."
|
314
|
-
when RestClient::SSLCertificateNotVerified
|
315
|
-
message = "Could not verify Dwolla's SSL certificate. If this problem persists, let us know at support@dwolla.com."
|
316
|
-
when SocketError
|
317
|
-
message = "Unexpected error communicating when trying to connect to Dwolla. If this problem persists, let us know at support@dwolla.com."
|
318
|
-
else
|
319
|
-
message = "Unexpected error communicating with Dwolla. If this problem persists, let us know at support@dwolla.com."
|
320
|
-
end
|
321
|
-
|
322
|
-
message += "\n\n(Network error: #{e.message})"
|
323
|
-
|
324
|
-
raise APIConnectionError.new(message)
|
325
|
-
end
|
326
|
-
end
|
1
|
+
# Dwolla Ruby API Wrapper
|
2
|
+
# Heavily based off Stripe's Ruby Gem
|
3
|
+
# API spec at https://developers.dwolla.com
|
4
|
+
require 'openssl'
|
5
|
+
require 'rest_client'
|
6
|
+
require 'multi_json'
|
7
|
+
require 'addressable/uri'
|
8
|
+
|
9
|
+
# Version
|
10
|
+
require_relative 'dwolla/version'
|
11
|
+
|
12
|
+
# Resources
|
13
|
+
require_relative 'dwolla/json'
|
14
|
+
require_relative 'dwolla/transactions'
|
15
|
+
require_relative 'dwolla/requests'
|
16
|
+
require_relative 'dwolla/contacts'
|
17
|
+
require_relative 'dwolla/users'
|
18
|
+
require_relative 'dwolla/balance'
|
19
|
+
require_relative 'dwolla/funding_sources'
|
20
|
+
require_relative 'dwolla/oauth'
|
21
|
+
require_relative 'dwolla/offsite_gateway'
|
22
|
+
require_relative 'dwolla/accounts'
|
23
|
+
require_relative 'dwolla/masspay'
|
24
|
+
|
25
|
+
# Errors
|
26
|
+
require_relative 'dwolla/errors/dwolla_error'
|
27
|
+
require_relative 'dwolla/errors/api_connection_error'
|
28
|
+
require_relative 'dwolla/errors/api_error'
|
29
|
+
require_relative 'dwolla/errors/missing_parameter_error'
|
30
|
+
require_relative 'dwolla/errors/authentication_error'
|
31
|
+
require_relative 'dwolla/errors/invalid_request_error'
|
32
|
+
|
33
|
+
module Dwolla
|
34
|
+
@@api_key = nil
|
35
|
+
@@api_secret = nil
|
36
|
+
@@token = nil
|
37
|
+
@@api_base = '/oauth/rest'
|
38
|
+
@@verify_ssl_certs = true
|
39
|
+
@@api_version = nil
|
40
|
+
@@debug = false
|
41
|
+
@@sandbox = false
|
42
|
+
@@scope = 'send|transactions|balance|request|contacts|accountinfofull|funding|scheduled'
|
43
|
+
|
44
|
+
def self.api_key=(api_key)
|
45
|
+
@@api_key = api_key
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.api_key
|
49
|
+
@@api_key
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.api_secret=(api_secret)
|
53
|
+
@@api_secret = api_secret
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.api_secret
|
57
|
+
@@api_secret
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.sandbox=(sandbox)
|
61
|
+
@@sandbox = sandbox
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.sandbox
|
65
|
+
@@sandbox
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.debug
|
69
|
+
@@debug
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.debug=(debug)
|
73
|
+
@@debug = debug
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.api_version=(api_version)
|
77
|
+
@@api_version = api_version
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.api_version
|
81
|
+
@@api_version
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.verify_ssl_certs=(verify_ssl_certs)
|
85
|
+
@@verify_ssl_certs = verify_ssl_certs
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.verify_ssl_certs
|
89
|
+
@@verify_ssl_certs
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.token=(token)
|
93
|
+
@@token = token
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.token
|
97
|
+
@@token
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.scope=(scope)
|
101
|
+
@@scope = scope
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.scope
|
105
|
+
@@scope
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.hostname
|
109
|
+
if not @@sandbox
|
110
|
+
return 'https://www.dwolla.com'
|
111
|
+
else
|
112
|
+
return 'https://uat.dwolla.com'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.endpoint_url(endpoint)
|
117
|
+
self.hostname + @@api_base + endpoint
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.request(method, url, params={}, headers={}, oauth=true, parse_response=true, custom_url=false)
|
121
|
+
# if oauth is nil, assume default [true]
|
122
|
+
oauth = true if oauth.nil?
|
123
|
+
|
124
|
+
# figure out which auth to use
|
125
|
+
if oauth and not params[:oauth_token]
|
126
|
+
if not oauth.is_a?(TrueClass) # was token passed in the oauth param?
|
127
|
+
params = {
|
128
|
+
:oauth_token => oauth
|
129
|
+
}.merge(params)
|
130
|
+
else
|
131
|
+
raise AuthenticationError.new('No OAuth Token Provided.') unless token
|
132
|
+
params = {
|
133
|
+
:oauth_token => token
|
134
|
+
}.merge(params)
|
135
|
+
end
|
136
|
+
elsif oauth and params[:oauth_token]
|
137
|
+
raise AuthenticationError.new('No OAuth Token Provided.') unless params[:oauth_token]
|
138
|
+
else not oauth
|
139
|
+
raise AuthenticationError.new('No App Key & Secret Provided.') unless (api_key && api_secret)
|
140
|
+
params = {
|
141
|
+
:client_id => api_key,
|
142
|
+
:client_secret => api_secret
|
143
|
+
}.merge(params)
|
144
|
+
end
|
145
|
+
|
146
|
+
if !verify_ssl_certs
|
147
|
+
$stderr.puts "WARNING: Running without SSL cert verification."
|
148
|
+
else
|
149
|
+
ssl_opts = {
|
150
|
+
:use_ssl => true
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
uname = (@@uname ||= RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
|
155
|
+
lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
156
|
+
ua = {
|
157
|
+
:bindings_version => Dwolla::VERSION,
|
158
|
+
:lang => 'ruby',
|
159
|
+
:lang_version => lang_version,
|
160
|
+
:platform => RUBY_PLATFORM,
|
161
|
+
:publisher => 'dwolla',
|
162
|
+
:uname => uname
|
163
|
+
}
|
164
|
+
|
165
|
+
url = self.endpoint_url(url) unless custom_url
|
166
|
+
|
167
|
+
case method.to_s.downcase.to_sym
|
168
|
+
when :get || :delete
|
169
|
+
# Make params into GET/DELETE parameters
|
170
|
+
if params && params.count > 0
|
171
|
+
uri = Addressable::URI.new
|
172
|
+
uri.query_values = params
|
173
|
+
url += '?' + uri.query
|
174
|
+
end
|
175
|
+
payload = nil
|
176
|
+
else
|
177
|
+
payload = JSON.dump(params)
|
178
|
+
end
|
179
|
+
|
180
|
+
begin
|
181
|
+
headers = { :x_dwolla_client_user_agent => Dwolla::JSON.dump(ua) }.merge(headers)
|
182
|
+
rescue => e
|
183
|
+
headers = {
|
184
|
+
:x_dwolla_client_raw_user_agent => ua.inspect,
|
185
|
+
:error => "#{e} (#{e.class})"
|
186
|
+
}.merge(headers)
|
187
|
+
end
|
188
|
+
|
189
|
+
headers = {
|
190
|
+
:user_agent => "Dwolla Ruby API Wrapper/#{Dwolla::VERSION}",
|
191
|
+
:content_type => 'application/json'
|
192
|
+
}.merge(headers)
|
193
|
+
|
194
|
+
if self.api_version
|
195
|
+
headers[:dwolla_version] = self.api_version
|
196
|
+
end
|
197
|
+
|
198
|
+
opts = {
|
199
|
+
:method => method,
|
200
|
+
:url => url,
|
201
|
+
:headers => headers,
|
202
|
+
:open_timeout => 30,
|
203
|
+
:payload => payload,
|
204
|
+
:timeout => 80
|
205
|
+
}.merge(ssl_opts)
|
206
|
+
|
207
|
+
if self.debug
|
208
|
+
if self.sandbox
|
209
|
+
puts "[DWOLLA SANDBOX MODE OPERATION]"
|
210
|
+
end
|
211
|
+
|
212
|
+
puts "Firing request with options and headers:"
|
213
|
+
puts opts
|
214
|
+
puts headers
|
215
|
+
end
|
216
|
+
|
217
|
+
begin
|
218
|
+
response = execute_request(opts)
|
219
|
+
rescue SocketError => e
|
220
|
+
self.handle_restclient_error(e)
|
221
|
+
rescue NoMethodError => e
|
222
|
+
# Work around RestClient bug
|
223
|
+
if e.message =~ /\WRequestFailed\W/
|
224
|
+
e = APIConnectionError.new('Unexpected HTTP response code')
|
225
|
+
self.handle_restclient_error(e)
|
226
|
+
else
|
227
|
+
raise
|
228
|
+
end
|
229
|
+
rescue RestClient::ExceptionWithResponse => e
|
230
|
+
if rcode = e.http_code and rbody = e.http_body
|
231
|
+
self.handle_api_error(rcode, rbody)
|
232
|
+
else
|
233
|
+
self.handle_restclient_error(e)
|
234
|
+
end
|
235
|
+
rescue RestClient::Exception, Errno::ECONNREFUSED => e
|
236
|
+
self.handle_restclient_error(e)
|
237
|
+
end
|
238
|
+
|
239
|
+
rbody = response.body
|
240
|
+
rcode = response.code
|
241
|
+
|
242
|
+
if self.debug
|
243
|
+
puts "Raw response headers received:"
|
244
|
+
puts headers
|
245
|
+
puts "Raw response body received:"
|
246
|
+
puts rbody
|
247
|
+
end
|
248
|
+
|
249
|
+
resp = self.extract_json(rbody, rcode)
|
250
|
+
|
251
|
+
if parse_response
|
252
|
+
return self.parse_response(resp)
|
253
|
+
else
|
254
|
+
return resp
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
def self.execute_request(opts)
|
261
|
+
RestClient::Request.execute(opts)
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.extract_json(rbody, rcode)
|
265
|
+
begin
|
266
|
+
resp = Dwolla::JSON.load(rbody)
|
267
|
+
rescue MultiJson::DecodeError
|
268
|
+
raise APIError.new("There was an error parsing Dwolla's API response: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
|
269
|
+
end
|
270
|
+
|
271
|
+
return resp
|
272
|
+
end
|
273
|
+
|
274
|
+
def self.parse_response(resp)
|
275
|
+
raise APIError.new(resp['Message']) unless resp.has_key?('Success') and resp['Success'] == true
|
276
|
+
|
277
|
+
return resp['Response']
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.handle_api_error(rcode, rbody)
|
281
|
+
begin
|
282
|
+
error_obj = Dwolla::JSON.load(rbody)
|
283
|
+
error = error_obj[:error] or raise DwollaError.new # escape from parsing
|
284
|
+
rescue MultiJson::DecodeError, DwollaError
|
285
|
+
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
|
286
|
+
end
|
287
|
+
|
288
|
+
case rcode
|
289
|
+
when 400, 404 then
|
290
|
+
raise invalid_request_error(error, rcode, rbody, error_obj)
|
291
|
+
when 401
|
292
|
+
raise authentication_error(error, rcode, rbody, error_obj)
|
293
|
+
else
|
294
|
+
raise api_error(error, rcode, rbody, error_obj)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def self.invalid_request_error(error, rcode, rbody, error_obj)
|
299
|
+
InvalidRequestError.new(error[:message], error[:param], rcode, rbody, error_obj)
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.authentication_error(error, rcode, rbody, error_obj)
|
303
|
+
AuthenticationError.new(error[:message], rcode, rbody, error_obj)
|
304
|
+
end
|
305
|
+
|
306
|
+
def self.api_error(error, rcode, rbody, error_obj)
|
307
|
+
APIError.new(error[:message], rcode, rbody, error_obj)
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.handle_restclient_error(e)
|
311
|
+
case e
|
312
|
+
when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
|
313
|
+
message = "Could not connect to Dwolla (#{@@api_base}). Please check your internet connection and try again. If this problem persists, you should check Dwolla's service status at https://twitter.com/Dwolla, or let us know at support@Dwolla.com."
|
314
|
+
when RestClient::SSLCertificateNotVerified
|
315
|
+
message = "Could not verify Dwolla's SSL certificate. If this problem persists, let us know at support@dwolla.com."
|
316
|
+
when SocketError
|
317
|
+
message = "Unexpected error communicating when trying to connect to Dwolla. If this problem persists, let us know at support@dwolla.com."
|
318
|
+
else
|
319
|
+
message = "Unexpected error communicating with Dwolla. If this problem persists, let us know at support@dwolla.com."
|
320
|
+
end
|
321
|
+
|
322
|
+
message += "\n\n(Network error: #{e.message})"
|
323
|
+
|
324
|
+
raise APIConnectionError.new(message)
|
325
|
+
end
|
326
|
+
end
|