dwolla / dwolla-v2-ruby Goto Github PK
View Code? Open in Web Editor NEWOfficial Ruby Wrapper for Dwolla's API v2
Home Page: https://developers.dwolla.com/
License: MIT License
Official Ruby Wrapper for Dwolla's API v2
Home Page: https://developers.dwolla.com/
License: MIT License
I've been working with the library since beginning of last week to learn how to implement our system at work with Dwolla to cover all our cases. Everything has gone great but one of the issues we have is the inconsistency in casing which would leads us to write code that utilizes the Dwolla library with mixed case, both camel (response properties) and kebab (for _links values). As is standard for Ruby projects we write code in snake case. Would the team be interested in accepting changes so requests can be provided in snake case and converted to camel case and responses the other way around? I've dealt with this before successfully with another service. Has this topic ever come up internally? Would their be any desire to have specific response objects?
I spent time on this today and came up with changes that would work with hashie, just something quick to see if it was even doable. I looked into using Dash and their property transformation extension but it requires that you define all available properties so that was a no go. The other issue is because of the mixed case and how method_missing
works, I couldn't get around by just changing the SuperHash
class but also had to update the Response
class too. I wanted to see if I could get this to work so at least responses could use snake_case but still support the original casing too. This is what I came up with:
For the Response
class:
def method_missing method, *args, &block
if method != :_links && method != :_embedded
method = method.to_s.gsub(/(?:_+)([a-z])/) { $1.upcase }.to_sym
end
# ...
end
For the SuperHash
class:
def method_missing method
dashed_method = method.to_s.gsub(/_/, "-").to_sym
if key? dashed_method
self[dashed_method]
elsif key? method
self[method]
else
super method
end
end
With these changes I can for example do the following:
customer = app_token.get(customer_url)
customer.first_name
# => "Javier"
customer._links.self.resource_type
# => "customer"
Would you open to any enhancements to the library in some way to handle this? I'm happy to do the work. I'm wondering if you'd be willing to have a discussion around it and especially if its already come up amongst your team. Thanks.
Since we use both Dwolla and Plaid together, Plaid recently has made major updates and with updating to Plaid v14, it requires Faraday v1 at a minimum. The Dwolla library seems to play well with Faraday v1 but can cause many reported deprecation warnings due to this line:
dwolla-v2-ruby/lib/dwolla_v2/token.rb
Line 56 in d829ed1
WARNING:
Faraday::Connection#authorization
is deprecated; it will be removed in version 2.0.
While initializing your connection, use#request(:authorization, ...)
instead.
See https://lostisland.github.io/faraday/middleware/authentication for more usage info.
I believe the affected line should be changed to the following and that should do it:
f.request :authorization, 'Bearer', access_token if access_token
It seems this should be supported as far back as Faraday v0.15 so it should be safe for a minor or patch release.
So I ran into an issue this morning trying to make a request to create a business customer. I thought that my hash was malformed, and passing in the wrong number of arguments, and finally threw a binding.pry in the source of the error (the hashie gem) and found the following:
` From: /Users/andrewsoep/.rvm/gems/ruby-2.4.1/gems/hashie-
3.5.7/lib/hashie/extensions/indifferent_access.rb @ line 79
Hashie::Extensions::IndifferentAccess#convert!:
77: def convert!
78: binding.pry
=> 79: keys.each do |k|
80: regular_writer convert_key(k), indifferent_value(regular_delete(k))
81: end
82: self
83: end
[1] pry(#Pry::Config)> keys
=> ["access_token", "token_type", "expires_in"]`
It seems as if the library is passing in an odd number of arguments, which is causing the issue at hand. The odd thing is, I use this gem for a lot of requests to the API, and it works fine, so I'm confused why this would be an issue. My code can be found below, if it illustrates something I'm doing in error.
` business_params = {
firstName: name[0],
lastName: name[1],
email: params[:admin_email],
type: org.client_type,
address1: org.address_line_1,
city: org.city,
state: org.region,
postalCode: org.postal_code,
businessName: org.name,
businessType: params[:business_type],
businessClassification: params[:business_classification],
ein: params[:ein]
}
business_params = business_params.merge({
controller: {
firstName: controller_name[0],
lastName: controller_name[1],
title: params[:controller][:title],
dateOfBirth: params[:controller][:date_of_birth],
address: {
address1: params[:controller][:address_line_1],
address2: params[:controller][:address_line_2],
city: params[:controller][:city],
state: params[:controller][:stateProvinceRegion],
postalCode: params[:controller][:postal_code],
country: params[:controller][:country]
}
}
}) if params["business_type"] != "soleProprietorship"
begin
response = Client.post "customers", business_params
location = response.headers[:location]
rescue DwollaV2::Error => e
location = duplicate_location_for(e) || raise
end`
The reliance on Faraday middleware makes this unusable on really any modern ruby application. Is Dwolla still alive/is this gem updated? If so, is there a way to remove the middleware dependency?
> AwesomePrint.irb!
> dwolla_client.get "/"
Traceback (most recent call last):
NameError (undefined method `to_hash' for class `DwollaV2::Response')
Did you mean? to_s
According to the documentation (https://docs.dwolla.com/#list-and-search-customers), you can stack statuses for a unique query (such as getting all suspended and unverified customers). However when I use the dwolla gem, instead of sending the multiple status (as the Dwolla API documentation indicates), it overwrites and only the last one is sent.
Example: $dwolla.get "customers", status: "suspended", status: "unverified"
The result is only status=unverified gets sent.
I also tried to send the whole url as a string, same result: $dwolla.get "https://api.dwolla.com/customers?status=suspended&status=unverified"
Opened ticket with Dwolla support thinking it was an issue with the API documentation. Instead it's an issue with the Gem and its inability to handle same status without overwriting.
Is there a known workaround for this issue?
We don't want to go over OAuth path, we are going to use White Label API.
This is my config in /initializers
$dwolla = DwollaV2::Client.new(id: "4ccmHuxwlohsKxxxxxxxxxxxxxxxxxxxxxxxxx", secret: "B0SlLhSLGsOkBl8zBjxxxxxxxxxxxxxxxxx") do |optional_config|
optional_config.environment = :sandbox
end
When I tried to get an application token I got following error.
2.2.2 :015 > token = $dwolla.auths.client scope: "ManagerCustomers|Funding"
TypeError: no implicit conversion of Symbol into Integer
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/dwolla_v2-0.1.0/lib/dwolla_v2/auth.rb:49:in `[]'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/dwolla_v2-0.1.0/lib/dwolla_v2/auth.rb:49:in `request_token'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/dwolla_v2-0.1.0/lib/dwolla_v2/auth.rb:6:in `client'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/dwolla_v2-0.1.0/lib/dwolla_v2/portal.rb:9:in `public_send'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/dwolla_v2-0.1.0/lib/dwolla_v2/portal.rb:9:in `method_missing'
from (irb):15
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/railties-4.0.13/lib/rails/commands/console.rb:90:in `start'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/railties-4.0.13/lib/rails/commands/console.rb:9:in `start'
from /home/akaruilabs/.rvm/gems/ruby-2.2.2/gems/railties-4.0.13/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
I was sent over here by my developer relations contact. I am having a weird issue that I'm struggling to diagnose. I thought it might be something related to our codebase, but a couple things is making me think it's related to this library:
We're trying to generate an IAV token to pass to the dwolla.js widget to initialize bank authorization. The entirety of our code is as follows:
response = Client.post("customers/#{customer_id}/iav-token") response.token
Where Client.post calls
$dwolla.auths.client.post endpoint, params
Where endpoint is what's being passed in in that string. I've verified that the correct customer_id is being passed, and correlates with a valid account. I asked our contact if the account not having certified beneficial ownership yet might be causing an issue, and he said no.
Any help would be appreciate on this as it's interfering with our customers experience. I'll also post the stack trace below:
By the way, the error is coming directly from the Client.post call.
[127.0.0.1] [ip-172-28-234-124.ec2.internal] odd number of arguments for Hash excluded from capture: No project_id specified [127.0.0.1] [ip-172-28-234-124.ec2.internal] [127.0.0.1] [ip-172-28-234-124.ec2.internal] ArgumentError (odd number of arguments for Hash): [127.0.0.1] [ip-172-28-234-124.ec2.internal] [127.0.0.1] [ip-172-28-234-124.ec2.internal] hashie (3.5.7) lib/hashie/extensions/indifferent_access.rb:46:in
[]'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] hashie (3.5.7) lib/hashie/extensions/indifferent_access.rb:46:in []' [127.0.0.1] [ip-172-28-234-124.ec2.internal] dwolla_v2 (1.2.2) lib/dwolla_v2/super_hash.rb:9:in
=='
[127.0.0.1] [ip-172-28-234-124.ec2.internal] dwolla_v2 (1.2.2) lib/dwolla_v2/error.rb:44:in ==' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/rescuable.rb:94:in
include?'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/rescuable.rb:94:in rescue_with_handler' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/rescuable.rb:97:in
rescue_with_handler'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/rescuable.rb:164:in rescue_with_handler' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal/rescue.rb:23:in
rescue in process_action'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal/rescue.rb:20:in process_action' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:32:in
block in process_action'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/notifications.rb:166:in block in instrument' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/notifications/instrumenter.rb:21:in
instrument'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/notifications.rb:166:in instrument' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:30:in
process_action'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal/params_wrapper.rb:252:in process_action' [127.0.0.1] [ip-172-28-234-124.ec2.internal] searchkick (3.0.0) lib/searchkick/logging.rb:209:in
process_action'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activerecord (5.1.6) lib/active_record/railties/controller_runtime.rb:22:in process_action' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/abstract_controller/base.rb:124:in
process'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionview (5.1.6) lib/action_view/rendering.rb:30:in process' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal.rb:189:in
dispatch'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_controller/metal.rb:253:in dispatch' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:49:in
dispatch'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:31:in serve' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/journey/router.rb:50:in
block in serve'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/journey/router.rb:33:in each' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/journey/router.rb:33:in
serve'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:844:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/etag.rb:25:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/conditional_get.rb:25:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/head.rb:12:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/session/abstract/id.rb:232:in context' [127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/session/abstract/id.rb:226:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/cookies.rb:613:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activerecord (5.1.6) lib/active_record/migration.rb:556:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/callbacks.rb:26:in block in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/callbacks.rb:97:in
run_callbacks'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/callbacks.rb:24:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/executor.rb:12:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/debug_exceptions.rb:59:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] web-console (3.5.1) lib/web_console/middleware.rb:135:in
call_app'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] web-console (3.5.1) lib/web_console/middleware.rb:28:in block in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] web-console (3.5.1) lib/web_console/middleware.rb:18:in
catch'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] web-console (3.5.1) lib/web_console/middleware.rb:18:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/show_exceptions.rb:31:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] railties (5.1.6) lib/rails/rack/logger.rb:36:in call_app' [127.0.0.1] [ip-172-28-234-124.ec2.internal] railties (5.1.6) lib/rails/rack/logger.rb:24:in
block in call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/tagged_logging.rb:69:in block in tagged' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/tagged_logging.rb:26:in
tagged'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/tagged_logging.rb:69:in tagged' [127.0.0.1] [ip-172-28-234-124.ec2.internal] railties (5.1.6) lib/rails/rack/logger.rb:24:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/remote_ip.rb:79:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/request_id.rb:25:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/method_override.rb:22:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/runtime.rb:22:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] activesupport (5.1.6) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/executor.rb:12:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] actionpack (5.1.6) lib/action_dispatch/middleware/static.rb:125:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] rack (2.0.6) lib/rack/sendfile.rb:111:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] rack-cors (1.0.2) lib/rack/cors.rb:97:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] sentry-raven (2.7.4) lib/raven/integrations/rack.rb:51:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] webpacker (3.5.5) lib/webpacker/dev_server_proxy.rb:22:in
perform_request'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] rack-proxy (0.6.5) lib/rack/proxy.rb:57:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] railties (5.1.6) lib/rails/engine.rb:522:in
call'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] puma (3.10.0) lib/puma/configuration.rb:225:in call' [127.0.0.1] [ip-172-28-234-124.ec2.internal] puma (3.10.0) lib/puma/server.rb:605:in
handle_request'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] puma (3.10.0) lib/puma/server.rb:437:in process_client' [127.0.0.1] [ip-172-28-234-124.ec2.internal] puma (3.10.0) lib/puma/server.rb:301:in
block in run'
[127.0.0.1] [ip-172-28-234-124.ec2.internal] puma (3.10.0) lib/puma/thread_pool.rb:120:in block in spawn_thread'
When using faraday response middleware (for say debug logging) in the on_complete
the response details (status, headers, body etc.) are missing.
For example the middleware below (the response logger that ships with faraday gives me the same results)
def call(env)
info "#{env.method} #{env.url.to_s}"
debug('request') { dump_headers env.request_headers }
debug('request') { dump_body(env[:body]) } if env[:body] && log_body?(:request)
@app.call(env).on_complete do |response_env|
info('Status') { response_env.status.to_s }
debug('response') { dump_headers response_env.response_headers }
debug('response') { dump_body response_env[:body] } if env[:body] && log_body?(:response)
end
end
When a Dwolla request is ran response_env.response_headers
is nil
and the response_env.body
is actually the request body.
I've used this type of response middleware logging before (with other faraday setups) without issue and it's very helpful for debugging requests.
Time.iso8601("2016-01-28T21:36:00Z")
is there a way to get a customer by its email?
Are there any examples of rspec testing with responses and errors?(using webmock of course)
Our specs fail when updating to ruby 3.2. We traced the issue back to
dwolla-v2-ruby/lib/dwolla_v2/client.rb
Lines 22 to 25 in 9808533
https://www.ruby-lang.org/en/news/2022/12/25/ruby-3-2-0-released/
Methods taking a rest parameter (like *args) and wishing to delegate keyword arguments through foo(*args) must now be marked with ruby2_keywords (if not already the case). In other words, all methods wishing to delegate keyword arguments through *args must now be marked with ruby2_keywords, with no exception. This will make it easier to transition to other ways of delegation once a library can require Ruby 3+. Previously, the ruby2_keywords flag was kept if the receiving method took *args, but this was a bug and an inconsistency. A good technique to find potentially missing ruby2_keywords is to run the test suite, find the last method which must receive keyword arguments for each place where the test suite fails, and use puts nil, caller, nil there. Then check that each method/block on the call chain which must delegate keywords is correctly marked with ruby2_keywords
To fix we add the '**' before the opts
parameter and this resolved the issue.
One thing I've been thinking about is how there should be an easier way to access the responses of links
.
Example
DWOLLA_CLIENT = DwollaV2::Client.new(params)
funding_sources_link =
DWOLLA_CLIENT
.get('customers', limit: 1)
._embedded.dig('customers', 0 '_links', 'funding-sources', 'href')
DWOLLA_CLIENT.get("#{funding_source_link}", params)
So, granted I understand the HAL schema y'all are working off of, the fundamental basis of the schema will remain the same, but ideally my end goal would be to go
DWOLLA_CLIENT = DwollaV2::Client.new(params)
DWOLLA_CLIENT
.get('customers', limit: 1)
.links[0].get.funding_sources(params) # or funding_sources('get', params)
to accomplish roughly the same thing, where .links
dynamcially dispatches the link information to methods to then re-call the client.
So, codewise, I'd imagine that the https://github.com/Dwolla/dwolla-v2-ruby/blob/main/lib/dwolla_v2/response.rb would contain a method that would look directly into the response maps, pull out the direct child _links
and _embedded
links object and create new methods based on that. The only caveat that would be tricky to work through is carrying over the same client request for both, which I think given the way token works, by adding the token to the initializer of the Response
, we should (:crossed_fingers:) be able to easily pass over the request structure to the links by going
class Response
def initialize response, token
@response = response
@token = token
end
def links
@response.body["_links"].keys.each do |link|
# ideally we'd snakecase link here
define_method(method, link, params=nil, headers=nil) do |path, params, headers|
full_url = self.class.full_url client, path
@token.public_send(method, full_url, params_headers)
end
end
end
end
Granted I haven't tested this, but just thought it up over lunch, but if this is something amenable, I'd be happy to fork and set up a PR.
The Dwolla client initialization parameter name (id
) is extremely confusing to someone coming into this codebase with significant OAuth experience. I strongly suggest that:
id
parameter be updated to read key
ENV["DWOLLA_ID"]
and the like, the Client is initialized with something like ENV["DWOLLA_CONSUMER_KEY"]
or ENV["DWOLLA_KEY"]
Seems that scopes can't be changed as dwolla-v2 #usage suggests, at least not in sandbox environment.
Running the following, the only scope I get is managecustomers
:
If I want to create custom middleware say for parsing Dwolla responses, I can but the way the following is structured I have to specify not just the default adapter line but also the response type, otherwise my middleware receives a string, not a hash.
dwolla-v2-ruby/lib/dwolla_v2/token.rb
Lines 64 to 65 in 4a01a17
I have a middleware to snake_case the keys in the response body and to get it to work I have to specify:
dwolla = DwollaV2::Client.new(...) do |config|
config.faraday do |f|
f.use UnderscoreResponseBodyKeys
f.response :json, :content_type => /\bjson$/
f.adapter Faraday.default_adapter
end
end
I don't just have to specify the default adapter as mentioned but also the response type, otherwise my middleware will receive a string, not a hash. By having the response type after it works as expected and my middleware will receive a hash that DwollaV2 had parsed earlier in the stack.
I shouldn't have to specify the response type but it has to come before specifying the default adapter. At first I tried updating the Token
class to have:
def conn
@conn ||= Faraday.new do |f|
# ...
client.faraday.call(f) if client.faraday
f.response :json, :content_type => /\bjson$/
f.adapter Faraday.default_adapter unless client.faraday
end
end
But I receive a warning here, since by just specifying the client.faraday
block, the default adapter isn't set but it has to be the last item otherwise you receive a warning that this won't be supported:
WARNING: Unexpected middleware set after the adapter. This won't be supported from Faraday 1.0.
While I can temporarily specify the response type on my end I don't think the library should require that and I don't think that was the intention. But it seems you can get both specifying middleware or an adapter with the current configuration setup.
I would suggest breaking off the faraday adapter into its own block or config option that way devs can specify custom middleware while still retaining the defaults. I can submit a PR for that or another solution if you prefer something else?
Hi,
when retrieving a customer's Funding Source the "status" attribute/method clashes with Response#status (HTTP status code) and the latter is returned instead of Funding Source status (e.g "verified").
From API doc:
funding_source_url = 'https://api-sandbox.dwolla.com/funding-sources/692486f8-29f6-4516-a6a5-c69fd2ce854c'
# Using DwollaV2 - https://github.com/Dwolla/dwolla-v2-ruby (Recommended)
funding_source = app_token.get funding_source_url
funding_source.name # => "Test checking account"
funding_source.status # => 200 instead of, for example "verified"
I dug a bit the code, but I didn't find an easy solution that does not interfere with the rest of the SDK...
Knowing the issue, a workaround to get Funding Source's status may be something like this:
require 'json'
fs_data = JSON.load funding_source.to_json
fs_status = fs_data["status"] # => "verified"
I am testing this on heroku in my staging env which matches key for key with production. I am running everything using sandbox
for Dwolla, but keep getting this same issue.
Here is there service class I am using, the error is getting triggered by this line:
customer = @access_token.post 'customers', request_body
Any clue as to why this might be happening?
# Service for managing Dwolla customers
class DwollaCustomer
def initialize(params)
@dwolla = set_dwolla_instance
@user = params[:user]
@access_token = @dwolla.auths.client
end
def create
customer = @access_token.post 'customers', request_body
@user.update_attributes(dwolla_url: customer.headers[:location])
end
def funding_sources
return unless @user.merchant? || @user.dwolla_url.nil?
sources = @access_token.get "#{@user.dwolla_url}/funding-sources"
sources._embedded['funding-sources']
end
private
def request_body
{
firstName: @user.first_name,
lastName: @user.last_name,
businessName: @user.business_name,
email: @user.email,
type: 'personal',
address1: @user.street_address,
city: @user.city,
state: @user.state,
postalCode: @user.zipcode,
dateOfBirth: @user.dob.strftime('%Y-%m-%d').to_s,
ssn: @user.ssn.last(4)
}
end
def set_dwolla_instance
@dwolla = DwollaV2::Client.new(key: ENV['dwolla_key'], secret: ENV['dwolla_secret']) do |config|
config.environment = ENV['dwolla_env'].to_sym
end
end
end
Here is the entire error produced:
DwollaV2::ValidationError: {"code"=>"ValidationError", "message"=>"Validation error(s) present. See embedded errors list for more details.", "_embedded"=>{"errors"=>[{"code"=>"NotAllowed", "message"=>"DateOfBirth value not allowed.", "path"=>"/dateOfBirth", "_links"=>{}}]}}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.