1
0
mirror of https://github.com/aclindsa/ofxgo.git synced 2024-10-30 05:20:05 -04:00
ofxgo/README.md

133 lines
5.2 KiB
Markdown
Raw Normal View History

2017-04-10 20:36:47 -04:00
# OFXGo
[![Go Report Card](https://goreportcard.com/badge/github.com/aclindsa/ofxgo)](https://goreportcard.com/report/github.com/aclindsa/ofxgo)
[![Build Status](https://github.com/aclindsa/ofxgo/workflows/ofxgo%20CI%20Test/badge.svg?branch=master)](https://github.com/aclindsa/ofxgo/actions?query=workflow%3A%22ofxgo+CI+Test%22+branch%3Amaster)
2017-04-10 08:17:34 -04:00
[![Coverage Status](https://coveralls.io/repos/github/aclindsa/ofxgo/badge.svg?branch=master)](https://coveralls.io/github/aclindsa/ofxgo?branch=master)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/aclindsa?ofxgo)](https://pkg.go.dev/github.com/aclindsa/ofxgo)
2017-04-08 11:14:25 -04:00
2017-04-10 20:36:47 -04:00
**OFXGo** is a library for querying OFX servers and/or parsing the responses. It
also provides an example command-line client to demonstrate the use of the
library.
2017-03-23 05:48:01 -04:00
## Goals
2017-03-26 20:44:55 -04:00
The main purpose of this project is to provide a library to make it easier to
query financial information with OFX from the comfort of Golang, without having
to marshal/unmarshal to SGML or XML. The library does _not_ intend to abstract
2017-04-10 20:36:47 -04:00
away all of the details of the OFX specification, which would be difficult to do
well. Instead, it exposes the OFX SGML/XML hierarchy as structs which mostly
2017-06-05 21:12:04 -04:00
resemble it. Its primary goal is to enable the creation of other personal
finance software in Go (as it was created to allow me to fetch OFX transactions
for my own project, [MoneyGo](https://github.com/aclindsa/moneygo)).
2017-03-26 20:44:55 -04:00
Because the OFX specification is rather... 'comprehensive,' it can be difficult
for those unfamiliar with it to figure out where to start. To that end, I have
created a sample command-line client which uses the library to do simple tasks
(currently it does little more than list accounts and query for balances and
transactions). My hope is that by studying its code, new users will be able to
figure out how to use the library much faster than staring at the OFX
specification (or this library's [API
documentation](https://pkg.go.dev/github.com/aclindsa/ofxgo)). The command-line client
2017-03-26 20:44:55 -04:00
also serves as an easy way for me to test/debug the library with actual
financial institutions, which frequently have 'quirks' in their implementations.
The command-line client can be found in the [cmd/ofx
directory](https://github.com/aclindsa/ofxgo/tree/master/cmd/ofx) of this
repository.
## Library documentation
2017-03-23 05:48:01 -04:00
2017-03-26 20:44:55 -04:00
Documentation can be found with the `go doc` tool, or at
https://pkg.go.dev/github.com/aclindsa/ofxgo
2017-03-26 20:44:55 -04:00
2017-11-18 19:43:41 -05:00
## Example Usage
The following code snippet demonstrates how to use OFXGo to query and parse
OFX code from a checking account, printing the balance and returned transactions:
```go
client := ofxgo.BasicClient{} // Accept the default Client settings
2017-11-18 19:43:41 -05:00
2018-04-14 09:06:32 -04:00
// These values are specific to your bank
2017-11-18 19:43:41 -05:00
var query ofxgo.Request
query.URL = "https://secu.example.com/ofx"
query.Signon.Org = ofxgo.String("SECU")
query.Signon.Fid = ofxgo.String("1234")
2018-04-14 09:06:32 -04:00
// Set your username/password
2017-11-18 19:43:41 -05:00
query.Signon.UserID = ofxgo.String("username")
query.Signon.UserPass = ofxgo.String("hunter2")
2018-04-14 09:06:32 -04:00
uid, _ := ofxgo.RandomUID() // Handle error in real code
query.Bank = append(query.Bank, &ofxgo.StatementRequest{
2017-11-18 19:43:41 -05:00
TrnUID: *uid,
BankAcctFrom: ofxgo.BankAcct{
2018-04-14 09:06:32 -04:00
BankID: ofxgo.String("123456789"), // Possibly your routing number
AcctID: ofxgo.String("00011122233"), // Possibly your account number
2017-11-18 19:43:41 -05:00
AcctType: ofxgo.AcctTypeChecking,
},
2018-04-14 09:06:32 -04:00
Include: true, // Include transactions (instead of only balance information)
2017-11-18 19:43:41 -05:00
})
2018-04-14 09:06:32 -04:00
response, _ := client.Request(&query) // Handle error in real code
2017-11-18 19:43:41 -05:00
2018-04-14 09:06:32 -04:00
// Was there an OFX error while processing our request?
2017-11-18 19:43:41 -05:00
if response.Signon.Status.Code != 0 {
meaning, _ := response.Signon.Status.CodeMeaning()
fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
os.Exit(1)
}
if len(response.Bank) < 1 {
fmt.Println("No banking messages received")
os.Exit(1)
}
if stmt, ok := response.Bank[0].(*ofxgo.StatementResponse); ok {
fmt.Printf("Balance: %s %s (as of %s)\n", stmt.BalAmt, stmt.CurDef, stmt.DtAsOf)
fmt.Println("Transactions:")
for _, tran := range stmt.BankTranList.Transactions {
2018-04-15 01:28:30 -04:00
currency := stmt.CurDef
2017-11-18 19:43:41 -05:00
if ok, _ := tran.Currency.Valid(); ok {
currency = tran.Currency.CurSym
}
fmt.Printf("%s %-15s %-11s %s%s%s\n", tran.DtPosted, tran.TrnAmt.String()+" "+currency.String(), tran.TrnType, tran.Name, tran.Payee.Name, tran.Memo)
}
}
```
Similarly, if you have an OFX file available locally, you can parse it directly:
```go
func main() {
f, err := os.Open("./transactions.qfx")
if err != nil {
fmt.Printf("can't open file: %v\n", err)
return
}
defer f.Close()
resp, err := ofxgo.ParseResponse(f)
if err != nil {
fmt.Printf("can't parse response: %v\n", err)
return
}
// do something with resp (*ofxgo.Response)
}
```
2017-10-27 09:03:57 -04:00
## Requirements
OFXGo requires go >= 1.12
2017-10-27 09:03:57 -04:00
2017-03-26 20:44:55 -04:00
## Using the command-line client
2017-03-23 05:48:01 -04:00
To install the command-line client and test it out, you may do the following:
$ go get -v github.com/aclindsa/ofxgo/cmd/ofx && go install -v github.com/aclindsa/ofxgo/cmd/ofx
2017-03-26 20:44:55 -04:00
Once installed (at ~/go/bin/ofx by default, if you haven't set $GOPATH), the
command's usage should help you to use it (`./ofx --help` for a listing of the
available subcommands and their purposes, `./ofx subcommand --help` for
individual subcommand usage).