plaid / plaid-ruby Goto Github PK
View Code? Open in Web Editor NEWRuby bindings for Plaid
Home Page: https://plaid.com/docs
License: MIT License
Ruby bindings for Plaid
Home Page: https://plaid.com/docs
License: MIT License
@ALL -
Plaid is in the process of a major overhaul to the plaid-ruby library. Once completed, plaid-ruby will be an officially supported Plaid API client library. Our goals are to make the library more consistent and up-to-date with the API, more robust when it comes to error handling, and better documented (to name a few)!
Keep an eye out for a additional details and a release in the next few weeks!
Info method is not handled in an object oriented fashion (following the rest of the libraries format).
TODO:
MFA list option should be a more simple flow, not requiring the user to pass in a hash as a parameter
TODO:
Type is passed in on most calls and is a bother for going through MFA flows
TODO:
Test file is massive and repeats code throughout
TODO:
user.rb is getting a bit out of hand and could use a bit of cleanup
TODO:
Error handling can be removed and replaced with Plaid's internal handling, converted into ruby
TODO:
More validators and tests
TODO:
Sub-type is a valid field, but does not happen on all accounts. The library should populate a field if it does exist.
Some calls to the Plaid.add_user
endpoint are timing out. Plaid support has informed me to set the timeout to at least 2 minutes. Is this something we can support here or should I fork?
https://plaid.com/docs/#update-user
Any way to do this in the gem? I've been looking but haven't seen it yet and just want to be sure.
Although I see references to gem 1.4.2
or 1.4.3
and mentions of fixes, I don't see them here.
I'd like the project to follow standard open-source processes to make it easier to follow code updates and make pull requests:
master
branch should contain the latest codeFollowing semantic versioning standards would mean let us make major, but breaking improvements to the gem. For example, #37 fixes a bug with passing connection options, but requires a breaking the method signature in order to fix it. There may be other architectural concerns that need to be addressed to make this gem more robust.
What do you guys think?
RestClient::PaymentRequired: 402 Payment Required
As detailed here.
The bank I am connected to is Chase. I have successfully connected an account and am getting 2 year's worth of transactional data.
However, I am having difficulty filtering that to a start and end date. I put in a date object and the run is successful, but I keep only getting the whole 2 years worth of transactions.
I've added a filed named 'plaid.rb' in config/initializers.
and added the code with updated configuration i.e. client_id and secret-
Plaid.config do |p|
p.client_id = '<<< Plaid provided client ID >>>'
p.secret = '<<< Plaid provided secret key >>>'
p.env = :tartan # or :api for production
end
It is showing the error "undefined method `client_id=' for Plaid:Module (NoMethodError)" on statting the server.
Hi Am trying to limit the transactions I obtain from Plaid by date using the lte and gte options.
Currently this is the method I'm calling:
user.get_connect({"start_date"=>"2016/05/09", "end_date"=>"2016/05/11"})
but I get all the transactions.
Am I doing something wrong or is this not working properly?
I am using this previous issue as a reference as well as the documentation: #23 My Plaid gem version is 1.7
Whenever I try to add a user with real credentials I get the above error message. Not sure why this is happening & it was working a few days ago. Has something changed in the last view days regarding the API?
UPDATE: a few of us have tried logging in with our credentials with the same result, so I don't think it's an issue with inputting the wrong username/password. The request looks like this: Plaid.add_user('auth', 'username', 'password', 'citi')
. Also - environment location is set to 'https://tartan.plaid.com/'
UPDATE 2: I believe I figured out the issue - I've added too many accounts to my test account. Shouldn't the error message be more responsive?
The config values in the README still refer to :api
instead of :production
, despite it not being an accepted value
Webhooks don't seem to work for MFA accounts (BofA / USAA) but do otherwise with the test credentials. Do I need to pass the webhook options for each response?
I've tried passing a 'pin' or 'PIN' in the base json call and in a credentials hash, as well as passing the pin the regular mfa paramters. I can't get it to work. Anyone got it to work? Have a gist?
The gem is about 4 months old now without a good refactoring. Add small, non-breaking issues below so they can be attended to.
I am running the exchange_token method thru and whether I use a real account with my public key or the sandbox account with the test key I keep getting corrupted public_token response. I see the public token in both cases and I have the key to save to my database and run the method in my model but cant get it to respond with an access key. Any idea what I could be doing wrong?
'auth' has a specific meaning in the Plaid API similar to 'connect' - it denotes a level of API access: https://plaid.com/docs/?api-overview/#auth
Plaid.auth is more similar to the Plaid API 'add user' method under auth and connect. Should we think about renaming this? Or perhaps more appropriately, recreate auth to align with the auth API and do the same for connect?
With the current structure there's no strait forward way (without using post) that I can see to submit get_connect or get_auth requests without resubmitting user credentials.
Allows more consistent handling.
Hi,
Needs to integrate Plaid with UI widget of https://github.com/plaid/link and 'Plaid' gem for internal operation of exchange_token.
But I had found that supported version of this gem (i.e 1.0.0) for ruby 1.9.3 does not have Plaid#exchange_token.
Please advise, any way so that I can use above gem with ruby 1.9.3.
Thanks,
Nitesh
Looking at the code for User#delete_user
, it looks like it would only work for the "info" product. Does that mean I have to upgrade the user to "info" before deleting them? Also, will that delete them across all products?
plaid-ruby 1.6.0
When Plaid.set_user is called with multiple services, the accounts are not merged.
The accounts from each service are added to the user.
Plaid.set_user('test_wells', ['auth']).accounts.each {|a| puts a.id}
QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK
nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy
XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo
pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k
Plaid.set_user('test_wells', ['connect']).accounts.each {|a| puts a.id}
QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK
nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy
XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo
pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k
Plaid.set_user('test_wells', ['connect', 'auth']).accounts.each {|a| puts a.id}
QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK
nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy
XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo
pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k
QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK
nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy
XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo
pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k
Looking at the code in User.rb on line 160, there is no way the merging could ever work. The accounts.any? and accounts.find are both comparing accounts to account id's - apples to oranges. I am also unclear on what owned_account.new(account) is trying to accomplish.
res['accounts'].each do |account|
if self.accounts.any? { |h| h == account['_id'] }
owned_account = self.accounts.find { |h| h == account['_id'] }
owned_account.new(account)
else
self.accounts << Account.new(account)
end
end if res['accounts']
I'm not sure what the rules are when updating the permissions attribute in the user object but my flow is generally:
plaid_user = Plaid.set_user(access_token,[])
--> Plaid user object with blank attributes besides access_token
plaid_user.upgrade('connect')
--> Plaid user object with info from connect but permissions attribute remains an empty array
transactions = Plaid.transactions(plaid_user.access_token, account: plaid_user.accounts[0].id)
--> Plaid transactions array, plaid user object still shows permissions as an empty array
Is this a bug or am I doing something that is not properly updating the permissions?
This is probably moot at this point since v2.0 is out now but in the gem pre 2.0, but I'm still using v1.7 and I'm sure others are as well. I'm not sure how the User.get_info
method ever worked. The 2 issues were:
User.get_info
calls User.get('info') which in turn will return false immediately unless the
User.permissions` array includes 'info'. The problem there is that when creating a user or restoring a user, it runs into this same problem where it will try and make a request to 'info/get' but obviously the permissions don't include it and therefore it will simply return false.unless self.permit? auth_level
then you would be stuck trying to make the Connection.secure_get('info', self.access_token)
The problem with this call is that the secure_get
never includes the client_id
or the secret
; which per the Plaid API Docs are required in a GET request to '/info/get'There are ways around this (some hacky-er) than others but I just thought I'd bring it up since v2.0 is out and I'm sure not everyone has upgraded just yet.
Would it be possible to loosen the version requirement for multi_json
to just the major version number? I believe the latest available gem is 1.12.1
while the gemspec is tied to 1.11.x
.
The test suite passes with the latest and I haven't encountered any issues.
Thank you for providing such a nice gem.
2 empty arrays returned from successful Plaid MFA call
Type and _id are missing from User::Account
"Type" is no longer a required parameter with every sandbox request - instead, access tokens are now in the format "test_{type}" (https://plaid.com/docs/#sandbox). The previous style - of providing type={type} and access_token=test - still works, but is less user friendly.
Hello I am working with the gem but I am having issue with how to pull specific items from the array that comes back for transactions on a User. I am missing something with the gem documentation. Using the test user and account how would I pull the amount for "Payroll" using the category id. I know this is probably a basic question but I am struggling to see how to do it. Any help would be greatly appreciated.
P.S. I can see the transaction in the array when I call User.transactions in the ruby console but cant seem to pull specific items
Any thoughts on using your API with devise (via omniauth)? I've been dwelling on it, and I'd be open to suggestions on a strategy.
I have been messing with this plaid-link module and plaid ruby gem over the weekend and I cant see what is wrong. I get the module to send me a public_token but cannot see how I am to put that into my app to exchange it for an access_token. I have tried changing the action in the form but that sends it to a page and it does not send any identifying information with it like the user_id. So my model cant receive the public_token.
I am unsure how to fix this because I know my app and I dont know how to manipulate the link module. Can someone take a look and point me in the right direction?
Here is how my module looks right now...
<form id="user" method="GET" action="/users/transactions"></form>
<script
src="https://cdn.plaid.com/link/stable/link-initialize.js"
data-client-name="your report"
data-form-id="user"
data-key="test_key"
data-product="auth"
data-env="tartan"
data-webhook="">
</script>
It is suppose to take the public_token response and send it to the transactions model and then the model will run
def plaid_exchange(options = {})
options.merge!({client_id: @client_id, secret: @secret, public_token: @public_token})
self.access_token = Plaid.exchange_token(body: options).parsed_response
end
If I understand everything, after this method it will return an access_token and I can run
def plaid_login(options = {})
options.merge!({access_token: @access_token, ['auth']})
@tenant = Plaid.set_user(body: options).parsed_response
end
From there I can call all the transactions. I cant figure out what I am missing and I need your help!!!!!
Thanks
I'm getting a user with an existing access_token in the following way:
def build_plaid_user
@plaid_user ||= Plaid::User.new
@plaid_user.permissions = %w{connect}
@plaid_user.access_token = self.access_token
@plaid_user
end
I'm then trying to get transactions:
def retrieve_transactions
@plaid_user.get_connect
@plaid_user.transactions
# => [ ["eJXpMzpR65FP4RYno6yjhBDxgkM6pXC9RKM9o3", "QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK", -3042.44, "Company Payroll", {"location"=>{}}, nil, false, {"location"=>{}, "name"=>1}, {"primary"=>"special"}, ["Transfer", "Payroll"], "21009000"] , ... ]
end
As you can see the return value is an array of arrays, rather than transaction objects. Is there a better way to do this so I can get Plaid::User::Transaction
instances?
So after getting a live test account I see that no transaction dates are given in the response. Is this just with the gem because the docs show a transaction date. If this is just with the gem can this PLEAZZZZE Be added to the gem because it is a significant piece of my application. I need the dates of transactions.
Thanks for the gem and am loving the changes in 1.4 (better set_user methods made retrieving information dramatically easier halfway through my work).
I'm having trouble with the MFA process as documented. Returning 402 Request Failed errors when trying to set_user with the access token in between steps of the MFA process. However, am getting the pending_mfa_response.
Could you link to an implementation of the whole process, and include in the wiki?
Carl @ plaid said I should send my support questions here.
I was working with the 1.4.0 gem, and used the test credentials from the api doc. What I got in return was:
#<Plaid::User:0x007fa5f6072788
@access_token="test_wells",
@account=
#<Plaid::Account:0x007fa5f6076ec8
@available_balance=9930,
@current_balance=2275.58,
@id="pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k",
@institution_type="fake_institution",
@meta={"limit"=>12500, "number"=>"3002", "name"=>"Plaid Credit Card"},
@name=[nil, 9930, 2275.58, "fake_institution", "pJPM4LMBNQFrOwp0jqEyTwyxJQrQbgU6kq37k", "credit"],
@numbers={},
@type="credit">,
@accounts=
[#<Plaid::Account:0x007fa5f6071b80
@available_balance=1203.42,
@current_balance=1274.93,
@id="QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK",
@institution_type="fake_institution",
@meta={"number"=>"9606", "name"=>"Plaid Savings"},
@name=[nil, 1203.42, 1274.93, "fake_institution", "QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK", "depository"],
@numbers={"routing"=>"021000021", "account"=>"9900009606", "wireRouting"=>"021000021"},
@type="depository">,
#<Plaid::Account:0x007fa5f6070bb8
@available_balance=1081.78,
@current_balance=1253.32,
@id="nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy",
@institution_type="fake_institution",
@meta={"number"=>"1702", "name"=>"Plaid Checking"},
@name=[nil, 1081.78, 1253.32, "fake_institution", "nban4wnPKEtnmEpaKzbYFYQvA7D7pnCaeDBMy", "depository"],
@numbers={"routing"=>"021000021", "account"=>"9900001702", "wireRouting"=>"021000021"},
@type="depository">,
#<Plaid::Account:0x007fa5f6077940
@available_balance=7205.23,
@current_balance=7255.23,
@id="XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo",
@institution_type="fake_institution",
@meta={"number"=>"5204", "name"=>"Plaid Premier Checking"},
@name=[nil, 7205.23, 7255.23, "fake_institution", "XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo", "depository"],
@numbers={"routing"=>"021000021", "account"=>"9900005204", "wireRouting"=>"021000021"},
@type="depository">,
#<Plaid::Account:0x007fa5f6076ec8
[3] pry(main)>
So maybe I don't understand the API design. As far as I understand it, a user has multiple accounts, right? So how come what I am getting here lists @account
and @accounts
? The gem docs don't mention @account
. Yet, the account held in @account
is not in @accounts
array.
I'm concerned that, I would have to check both @account
and @accounts
to get the complete list of accounts on my end of the code.
So what's going on here, can anyone explain?
Are there issues deleting users in Plaid? I am using the delete_user() method on a user set with an active access token but the method doesn't seem to do anything and i'm able to use that access token to pull data without any issues.
plaid_user=Plaid.set_user(token)
plaid_user.delete_user()
When i delete the same user via a simple curl request, it does get deleted. Has anyone used the delete_user method successfully?
Thank you
Ruben
I am not sure if this is your issue or if this is a bank specific issue but I seem to be getting duplicate transactions data when issuing the user.get('connect')
call using Chase as the Bank. I tried to duplicate the problem with your tests using Wells Fargo as the bank but I did not get duplicate transactions this way. The data I get back from the call contains 2 copies of the same id for each transaction.
Can anyone else confirm this problem?
Below is the code that returns the duplicate data.
user = Plaid.set_user(access_token, ['connect'])
user.get('connect')
Currently, the code shown for using User.exchange_token
with more options reads:
user2 = Plaid::User.exchange_token('public_token', account_id: '...', product: :auth)
But this throws an unknown keyword: account_id
error.
The code that is working without error for me is:
user2 = Plaid::User.exchange_token('public_token', 'account_id', product: :auth)
I'm sorry if this isn't the right place to post this but I've dug through the source and cannot understand why this isn't working:
Plaid.set_user('test_boa', ['connect'], 'bofa')
I am getting RuntimeError: It appears that the access token has been corrupted
I have tried this with real users as well. Creating them works fine, I can verify their access token exists on the plaid website, but I get the same error.
Any suggestions would be welcomed.
I am working on a project that looks at a users bank information and I noticed that for all the information that is given from a plaid request, there doesn't seem to be a name of account holder piece of the response unless I missed it. Can that be added to reduce fraud of someone using another persons bank information? i.e a daughter using her mothers bank information?
Makes it easier to look up (and more consistent presumably) for us to match up categories by id than by parsing the category response. Or was the id removed b/c they are expected to change on Plaid's side?
Hi,
I am having an issue with delete_user
in tartan:
plaid_user = Plaid::User.new
plaid_user.access_token = "[USER_ACCESS_TOKEN]"
plaid_user.delete_user()
I get: <Net::HTTPUnauthorized 401 Unauthorized readbody=true>
If I try straight with curl:
curl -X DELETE https://tartan.plaid.com/info \
-d client_id=[CLIENT_ID]\
-d secret=[CLIENT_SECRET} \
-d access_token=[USER_ACCESS_TOKEN]
Then I get:
{
"code": 1110,
"message": "product not enabled",
"resolve": "This product is not enabled for this item. Use the upgrade route to add it.",
"access_token": "[USER_ACCESS_TOKEN]"
}
I imagine this is all happening because the new info
endpoint. If I do that same call to https://tartan.plaid.com/connect
then it works out fine.
Currently I am using plaid-ruby version 1.4.3
. On the README it says it's the stable version (?).
I tried as well with plaid-ruby version 1.4.0
(the one that loads through gem 'plaid'
) but as well there it's making the delete_user
call to /info
.
Could you guys provide me any light into this issue? Thanks.
There is no way to recall a a user if the session has been ended (at least no easy way now).
The user class needs a method to reconstruct a user based on a single auth_token being passed in as a parameter. This should also be noted in the wiki documentation.
Hi Guys, I do not know if this is correct behaviour.
I add_user with auth scope. I want to get bank data, because then I will try to get transactions related to the accounts.
user_auth = Plaid.add_user('auth', 'plaid_test', 'plaid_good', 'usaa', '1234')
auth_data = user_auth.mfa_authentication('tomato')
Checking the user permissions seems right, the user only have access to the auth scope.
user_auth.permit?('connect') # returns false
user_auth.permit?('auth') # returns true
Based on the code, I see I can easily upgrade the user to fetch data related to the connect
scope.
user_auth.upgrade # or user_auth.upgrade('connect')
The thing is that using the gem, still the user has no permissions. So transaction data is empty.
user_auth.permit?('connect') # returns false
user_auth.permit?('auth') # returns true
user_auth.transactions
The only way I could upgrade the user, and fetching his transactions was by using Connection
manually.
Plaid::Connection.post('upgrade', { access_token: user_auth.access_token, upgrade_to: 'connect' })
payload = { access_token: user_auth.access_token }
Plaid::Connection.post('connect/get', payload)
The reason I am doing this its because I want to be able of fetching all of users information in a background process, after the user signup.
Is this the correct behaviour?
Thanks,
The gem does not return the actual JSON response from plaid. Instead it proscribes a certain approach to handling responses, especially transactions and errors. This is adding complexity without any apparent advantages, and especially in the case of errors, requires reading the source code to map the responses defined in the Plaid API documentation to how this Gem handles them.
Much better to just return the full response including the HTTP status and let people decide how they want to use it. This is approach is lighter weight, more transparent, and more flexible.
Not sure if you are aware, but version 0.1.6 is not published and all the documentation in the README is related to this version. Was confusing trying to integrate. Also, version tags would be really helpful.
The README dictates that the developer should create an initializer with the following:
Plaid.config do |p|
p.client_id = '<<< Plaid provided client ID >>>'
p.secret = '<<< Plaid provided secret key >>>'
p.env = :tartan # or :production
end
However, none of these attributes exist on the called configuration class:
# /usr/local/bundle/gems/plaid-1.7.1/lib/plaid/config.rb
module Plaid
module Configure
attr_accessor :customer_id, :secret, :environment_location
KEYS = [:customer_id, :secret, :environment_location]
def config
yield self
# Add trailing slash to api url if it is not present
if self.environment_location[-1] != '/'
self.environment_location += '/'
end
self
end
end
end
Any attempt to set these keys per the documentation leads to missing accessor errors, such as:
/code/config/initializers/plaid.rb:2:in `block in <top (required)>': undefined method `client_id=' for Plaid:Module (NoMethodError)
from /usr/local/bundle/gems/plaid-1.7.1/lib/plaid/config.rb:8:in `config'
from /code/config/initializers/plaid.rb:1:in `<top (required)>'
Here's my initializer:
# config/initializers/plaid.rb
Plaid.config do |p|
p.client_id = ENV['PLAID_CLIENT_ID']
p.secret = ENV['PLAID_SECRET_KEY']
if Rails.env.development? || Rails.env.test?
p.env = :tartan
else
p.env = :production
end
end
> user.upgrade(:info)
OpenSSL::SSL::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv2/v3 read server hello A
from /Users/dcorwin/.rbenv/versions/2.2.3/lib/ruby/2.2.0/net/http.rb:923:in `connect'
I am on a El Capitan and received this error with both openssl 0.9.8zh and 1.0.2h.
Brief googling reveals this may be an issue with the version of TLS or the cipher used by the server, but the bowels of encryption aren't really my cup o tea.
Thoughts? More details below:
plaid (2.0.0)
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin15]
OpenSSL 1.0.2h 3 May 2016
built on: reproducible build, date unspecified
platform: darwin64-x86_64-cc
options: bn(64,64) rc4(ptr,int) des(idx,cisc,16,int) idea(int) blowfish(idx)
compiler: clang -I. -I.. -I../include -fPIC -fno-common -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -arch x86_64 -O3 -DL_ENDIAN -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
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.