mirror of
https://github.com/aclindsa/ofxgo.git
synced 2024-11-14 01:00:06 -05:00
Aaron Lindsay
119c01f99b
This also makes it possible to call this method for testing without making an HTTP request.
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
package ofxgo
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"github.com/aclindsa/go/src/encoding/xml"
|
|
"time"
|
|
)
|
|
|
|
type Request struct {
|
|
URL string
|
|
Version string // OFX version string, overwritten in Client.Request()
|
|
Signon SignonRequest //<SIGNONMSGSETV1>
|
|
Signup []Message //<SIGNUPMSGSETV1>
|
|
Banking []Message //<BANKMSGSETV1>
|
|
CreditCards []Message //<CREDITCARDMSGSETV1>
|
|
//<LOANMSGSETV1>
|
|
Investments []Message //<INVSTMTMSGSETV1>
|
|
//<INTERXFERMSGSETV1>
|
|
//<WIREXFERMSGSETV1>
|
|
//<BILLPAYMSGSETV1>
|
|
//<EMAILMSGSETV1>
|
|
Securities []Message //<SECLISTMSGSETV1>
|
|
//<PRESDIRMSGSETV1>
|
|
//<PRESDLVMSGSETV1>
|
|
Profile []Message //<PROFMSGSETV1>
|
|
//<IMAGEMSGSETV1>
|
|
|
|
indent bool // Whether to indent the marshaled XML
|
|
}
|
|
|
|
func marshalMessageSet(e *xml.Encoder, requests []Message, setname string) error {
|
|
if len(requests) > 0 {
|
|
messageSetElement := xml.StartElement{Name: xml.Name{Local: setname}}
|
|
if err := e.EncodeToken(messageSetElement); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, request := range requests {
|
|
if ok, err := request.Valid(); !ok {
|
|
return err
|
|
}
|
|
if err := e.Encode(request); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := e.EncodeToken(messageSetElement.End()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Overwrite the fields in this Request object controlled by the Client
|
|
func (oq *Request) SetClientFields(c *Client) {
|
|
oq.Signon.DtClient = Date(time.Now())
|
|
|
|
// Overwrite fields that the client controls
|
|
oq.Version = c.OfxVersion()
|
|
oq.Signon.AppId = c.Id()
|
|
oq.Signon.AppVer = c.Version()
|
|
oq.indent = c.IndentRequests()
|
|
}
|
|
|
|
// Marshal this Request into its SGML/XML representation held in a bytes.Buffer
|
|
//
|
|
// If error is non-nil, this bytes.Buffer is ready to be sent to an OFX server
|
|
func (oq *Request) Marshal() (*bytes.Buffer, error) {
|
|
var b bytes.Buffer
|
|
|
|
// Write the header appropriate to our version
|
|
switch oq.Version {
|
|
case "102", "103", "151", "160":
|
|
b.WriteString(`OFXHEADER:100
|
|
DATA:OFXSGML
|
|
VERSION:` + oq.Version + `
|
|
SECURITY:NONE
|
|
ENCODING:USASCII
|
|
CHARSET:1252
|
|
COMPRESSION:NONE
|
|
OLDFILEUID:NONE
|
|
NEWFILEUID:NONE
|
|
|
|
`)
|
|
case "200", "201", "202", "203", "210", "211", "220":
|
|
b.WriteString(`<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + "\n")
|
|
b.WriteString(`<?OFX OFXHEADER="200" VERSION="` + oq.Version + `" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>` + "\n")
|
|
default:
|
|
return nil, errors.New(oq.Version + " is not a valid OFX version string")
|
|
}
|
|
|
|
encoder := xml.NewEncoder(&b)
|
|
if oq.indent {
|
|
encoder.Indent("", " ")
|
|
}
|
|
|
|
ofxElement := xml.StartElement{Name: xml.Name{Local: "OFX"}}
|
|
|
|
if err := encoder.EncodeToken(ofxElement); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if ok, err := oq.Signon.Valid(); !ok {
|
|
return nil, err
|
|
}
|
|
signonMsgSet := xml.StartElement{Name: xml.Name{Local: "SIGNONMSGSRQV1"}}
|
|
if err := encoder.EncodeToken(signonMsgSet); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := encoder.Encode(&oq.Signon); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := encoder.EncodeToken(signonMsgSet.End()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := marshalMessageSet(encoder, oq.Signup, "SIGNUPMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := marshalMessageSet(encoder, oq.Banking, "BANKMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := marshalMessageSet(encoder, oq.CreditCards, "CREDITCARDMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := marshalMessageSet(encoder, oq.Investments, "INVSTMTMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := marshalMessageSet(encoder, oq.Securities, "SECLISTMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := marshalMessageSet(encoder, oq.Profile, "PROFMSGSRQV1"); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := encoder.EncodeToken(ofxElement.End()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := encoder.Flush(); err != nil {
|
|
return nil, err
|
|
}
|
|
return &b, nil
|
|
}
|