csingley / ofxtools

Python OFX Library
Other
301 stars 68 forks source link

DTACCTUP date format for Wells Fargo #86

Closed autotrader425 closed 4 years ago

autotrader425 commented 4 years ago

Hi. New to ofxtools. So excited to use in python. I have gotten most banks to work but a bit stuck with Wells Fargo. I've isolated the issue to the date format for DTACCTUP. WF is expecting '19900101' while I get '19991231000000.000[0:GMT]' from ofxget. Even if I use '19991231' it does not work.

Is there a parameter to specify this date? Or any pointers on how I would go about replacing? Worst case I might just hard-code my queries for WF.

Thank you, and apologies if not the right place to post this. Carlos

Sample request:

OFXHEADER:100
DATA:OFXSGML
VERSION:103
SECURITY:NONE
ENCODING:USASCII
CHARSET:NONE
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:##some-uuid4##

<OFX><SIGNONMSGSRQV1><SONRQ><DTCLIENT>20200709235859.106[0:GMT]</DTCLIENT><USERID>##anonymous_user##</USERID><USERPASS>anonymous00000000000000000000000</USERPASS><LANGUAGE>ENG</LANGUAGE><FI><ORG>WF</ORG><FID>3000</FID></FI><APPID>QWIN</APPID><APPVER>2700</APPVER><CLIENTUID>##some-uuid-NO-HYPHENS##</CLIENTUID></SONRQ></SIGNONMSGSRQV1><SIGNUPMSGSRQV1><ACCTINFOTRNRQ><TRNUID>##some-uuid4##</TRNUID><ACCTINFORQ><DTACCTUP>19991231000000.000[0:GMT]</DTACCTUP></ACCTINFORQ></ACCTINFOTRNRQ></SIGNUPMSGSRQV1></OFX>
csingley commented 4 years ago

Sure, this is the right place to post troubleshooting info, feature requests, etc, not only bug reports.

Let me focus on this part first:

WF is expecting '19900101' while I get '19991231000000.000[0:GMT]' from ofxget. Even if I use '19991231' it does not work.

If '19900101' works but '19991231' doesn't, that does not sound like a data formatting problem... or maybe not JUST a data formatting problem. Another possible avenue is to instead look at the data value first to start narrowing the focus. What I want to know first is - does WF puke and fall over if you send <DTACCTUP>19900101000000.000[0:GMT]</DTACCTUP> ?

I have not (yet) implemented a facility to change DTACCTUP with the ofxget utility, but there is such a facility in the underlying ofxtools.Client module used by the script. So for a quick test, you have two choices:

  1. (much easier) Directly edit the ofxget.py script inside your ofxtools installation, which you can find like this:
>>> from ofxtools import scripts
>>> scripts.__file__

ofxget.py will be located in that directory. You're looking for a function called _request_acctinfo(), which is after line 574 in my installation. The second line of the function hard-codes a completely arbitrary datetime that sounds like it's blowing up for you. Change that value from this:

dtacctup = datetime.datetime(1999, 12, 31, tzinfo=utils.UTC)

to this:

dtacctup = datetime.datetime(1990, 1, 1, tzinfo=utils.UTC)

Now try again to send your request with ofxget.

  1. (much less of a nasty horrible hack) Don't use the ofxget utility, but rather jump into a live Python interpreter and build your requests manually.
>>> from ofxtools.Client import OFXClient
>>> client = OFXClient(
...     url="https://ofxdc.wellsfargo.com/ofx/process.ofx",
...     org="WF",
...     fid="3000",
...     version=220,
...     userid="USERID",  # FIXME
...     clientuid="CLIENTUID",  # FIXME
... )
>>> # Basically copy ofxtools.scripts.ofxget._request_acctinfo()
>>> from datetime import datetime
>>> from ofxtools import utils
>>> dtacctup = datetime(1990, 1, 1, tzinfo=utils.UTC)
>>> with client.request_accounts(
...         "MYSECRETPASSWORD",  # FIXME
...         dtacctup
...    ) as f:
...         response = f.read()
... 
>>> print(response)

Let me know the results!

autotrader425 commented 4 years ago

Hello again, wow, thank you for the thorough explanation. So it is the value that it is picky about, not the format. Both formats worked as long as the value represents this:

datetime.datetime(1990, 1, 1, tzinfo=utils.UTC)

So to confirm, both formats worked.

I started doing all my configuration on the command line, though my end goal is to do all this in python; so it is really as simple as your Option 2 above. My mind was stuck getting the command line to work that didn't realize dtacctup is a required argument for request_accounts. :-)

All set for this one. Thanks again for the prompt response. Great handy tool!

csingley commented 4 years ago

Glad we got that figured out.

Look, here's the deal - obviously I just slapped that hard-wired date in there as a quick hack, and it's never been a problem for anyone previously so I just never back around to improving the implementation.

If you read section 8.5 of the OFX spec, it says this:

Requests and responses include a <DTACCTUP> element. Responses contain the last time a server
updated the information. Clients are REQUIRED to send this in a subsequent request, and servers are
REQUIRED to compare this to the current modification time and only send information if it is more
recent. The server sends the entire account information response if the client’s time is older; there is no
attempt to incrementally update specific account information. <ACCTINFORS> should not be sent when
the client is up-to-date.

Clearly my goal was, by default, to make sure the client's update timestamp is always older than the server's update timestamp... and I thought going back to the previous millennium ought to be good enough. WF is showing us clearly that in fact my assumption here was wrong.

So from my point of view the right way to address this situation is to wind back the default DTACCTUP even more... I suppose datetime(1776, 7, 4) really ought to do the trick! Then fix ofxget.py to expose DTACCTUP to the user as a CLI option, so the default can be overriden conveniently.

That way I can keep you trapped as a helpless prisoner of the CLI for a little while longer, instead of giving you the freedom to import ofxtools.Client yourself and do whatever you please.

So please don't close this ticket just yet, until I've perfected my evil scheme.

Thanks for reporting.

csingley commented 4 years ago

Should be all set with 6d93346