Go library for marshaling and unmarshaling Fedwire Funds Service ISO 20022 messages.
This is a fork of moov-io/fedwire20022 maintained by Mbanq, with the following additions:
- Correct namespace handling — struct tags use local names only, so
xml.Marshalandxml.Unmarshalwork without post-processing string replacements fedwirefunds_incoming/marshal.go—MarshalXMLimplementations for all message types sent from a participant bank to FedWirefedwirefunds_outgoing/unmarshal.go—UnmarshalXMLonFedwireFundsOutgoingcontainer; readsMsgDefIdrfromAppHdrand dispatches to the correct typed struct automatically
The XSD package names reflect FedWire's perspective, not the participant bank's:
| Package | FedWire perspective | Bank perspective |
|---|---|---|
fedwirefunds_incoming |
Messages flowing INTO FedWire | Messages the bank sends |
fedwirefunds_outgoing |
Messages flowing OUT of FedWire | Messages the bank receives |
Build a typed struct from fedwirefunds_incoming, then call xml.Marshal — MarshalXML handles namespace placement automatically:
import (
"encoding/xml"
"github.com/Mbanq/go-fedwire/gen/fedwirefunds_incoming"
"github.com/Mbanq/go-fedwire/gen/head_001_001_03"
"github.com/Mbanq/go-fedwire/gen/pacs_008_001_08"
)
msg := &fedwirefunds_incoming.FedwireFundsCustomerCreditTransfer{
AppHdr: head_001_001_03.BusinessApplicationHeaderV03{ ... },
Document: pacs_008_001_08.Document{ ... },
}
if err := msg.Validate(); err != nil {
return err
}
data, err := xml.MarshalIndent(msg, "", " ")Produces:
<Message xmlns="urn:fedwirefunds:incoming:v001">
<AppHdr xmlns="urn:iso:std:iso:20022:tech:xsd:head.001.001.03">...</AppHdr>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.08">...</Document>
</Message>Unmarshal raw XML into FedwireFundsOutgoing — UnmarshalXML reads MsgDefIdr and sets exactly one typed pointer on the message container:
import "github.com/Mbanq/go-fedwire/gen/fedwirefunds_outgoing"
var envelope fedwirefunds_outgoing.FedwireFundsOutgoing
if err := xml.Unmarshal(data, &envelope); err != nil {
return err
}
m := envelope.FedwireFundsOutgoingMessage
switch {
case m.FedwireFundsPaymentReturn != nil:
// pacs.004 — payment return
case m.FedwireFundsPaymentStatus != nil:
// pacs.002 — payment status report
case m.FedwireFundsCustomerCreditTransfer != nil:
// pacs.008 — incoming credit transfer from another bank
}Pointer fields are optional (minOccurs="0" in XSD), value fields are mandatory (minOccurs="1"):
type CreditTransferTransaction39 struct {
PmtId PaymentIdentification7 // mandatory — value type
IntrBkSttlmAmt ActiveCurrencyAndAmount // mandatory — value type
IntrBkSttlmDt *fedwire.ISODate // optional — pointer
InstdAmt *ActiveOrHistoricCurrencyAndAmount // optional — pointer
}Call msg.Validate() to check all required fields before marshaling.
The gen/ packages are generated from XSD schemas in xsd/. To regenerate:
make generateCustom files (marshal.go, unmarshal.go) are not touched by the generator and survive regeneration. The struct tag fix in model.tgo is baked into the template and applied on every generation run.
This project is a fork of moov-io/fedwire20022, originally developed by Moov Financial, Inc. under the Apache 2.0 License.