Golang library for querying and parsing OFX
Dosyaya git
Aaron Lindsay e302ce2e6b CI: Update go versions tested 2023-03-14 22:18:43 -04:00
.github/workflows CI: Update go versions tested 2023-03-14 22:18:43 -04:00
cmd/ofx Add missing handling for `-dryrun` flag in command-line client 2023-02-05 19:52:02 -05:00
samples GH-39 relax ofx response parsing to support TYPE1 responses 2021-03-12 10:46:24 -05:00
LICENSE Add license 2017-04-08 11:48:55 -04:00
README.md README: Add inline link to documentation 2021-10-17 21:57:26 -04:00
bank.go Bank transactions: Allow transaction currencies to be empty 2019-03-06 06:00:05 -05:00
bank_test.go Add tests for Payee/Balance Valid() methods 2021-10-17 21:55:45 -04:00
basic_client.go Added Accept http header as Citi now requires it 2021-09-01 09:35:45 -04:00
client.go Support carriage returns on new lines 2019-06-26 06:23:52 -04:00
common.go Support carriage returns on new lines 2019-06-26 06:23:52 -04:00
common_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
constants.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
constants_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
creditcard.go Switch to copy of encoding/xml with only that subdirectory 2017-10-02 09:21:56 -04:00
creditcard_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
discovercard_client.go Fix spelling error 2020-10-06 23:14:42 -04:00
doc.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
generate_constants.py Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
go.mod Replace github.com/howeyc/gopass with golang.org/x/term 2021-10-17 21:20:04 -04:00
go.sum Replace github.com/howeyc/gopass with golang.org/x/term 2021-10-17 21:20:04 -04:00
invstmt.go Add `InvPosition() InvPosition` to `Position` interface. 2023-03-14 22:10:19 -04:00
invstmt_test.go Add `SecurityInfo()` and `InvPosition()` tests. 2023-03-14 22:10:19 -04:00
leaf_elements.go Omit end tags for encoding OFX 100-series requests 2019-07-01 06:11:16 -04:00
profile.go Add the ability to marshal a Response to SGML/XML and test it 2019-03-02 07:03:11 -05:00
profile_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
request.go Omit end tags for encoding OFX 100-series requests 2019-07-01 06:11:16 -04:00
request_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
response.go GH-39 relax ofx response parsing to support TYPE1 responses 2021-03-12 10:46:24 -05:00
response_test.go review changes 2021-01-04 07:24:40 -05:00
seclist.go Add `SecurityInfo() SecInfo` to `Security` interface. 2023-03-14 22:10:19 -04:00
signon.go signon: Add missing GENUSERKEY field 2020-11-17 10:33:48 -05:00
signon_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
signup.go Switch to copy of encoding/xml with only that subdirectory 2017-10-02 09:21:56 -04:00
signup_test.go Rename ofxgo_test package to ofxgo and remove self-imports/references 2020-04-03 08:38:41 -04:00
types.go Switch to copy of encoding/xml with only that subdirectory 2017-10-02 09:21:56 -04:00
types_test.go Add tests for String/Boolean String() methods 2021-10-17 21:55:45 -04:00
util.go Switch to copy of encoding/xml with only that subdirectory 2017-10-02 09:21:56 -04:00
vanguard_client.go Vanguard client: Accept 500 errors on initial response 2020-11-17 10:33:48 -05:00

README.md

OFXGo

Go Report Card Build Status Coverage Status PkgGoDev

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.

Goals

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 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 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).

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). The command-line client 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 of this repository.

Library documentation

Documentation can be found with the go doc tool, or at https://pkg.go.dev/github.com/aclindsa/ofxgo

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:

client := ofxgo.BasicClient{} // Accept the default Client settings

// These values are specific to your bank
var query ofxgo.Request
query.URL = "https://secu.example.com/ofx"
query.Signon.Org = ofxgo.String("SECU")
query.Signon.Fid = ofxgo.String("1234")

// Set your username/password
query.Signon.UserID = ofxgo.String("username")
query.Signon.UserPass = ofxgo.String("hunter2")

uid, _ := ofxgo.RandomUID() // Handle error in real code
query.Bank = append(query.Bank, &ofxgo.StatementRequest{
	TrnUID: *uid,
	BankAcctFrom: ofxgo.BankAcct{
		BankID:   ofxgo.String("123456789"),   // Possibly your routing number
		AcctID:   ofxgo.String("00011122233"), // Possibly your account number
		AcctType: ofxgo.AcctTypeChecking,
	},
	Include: true, // Include transactions (instead of only balance information)
})

response, _ := client.Request(&query) // Handle error in real code

// Was there an OFX error while processing our request?
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 {
		currency := stmt.CurDef
		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:

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)
}

Requirements

OFXGo requires go >= 1.12

Using the command-line client

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

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).