Browse Source

pain: finalized-ish Document, createbatch: helper to create/export xml

master
Gerdriaan Mulder 6 years ago
parent
commit
f6b03ab6ef
  1. 2
      cmd/createbatch/.gitignore
  2. 27
      cmd/createbatch/main.go
  3. 91
      pain/api.go
  4. 8
      pain/group_header.go
  5. 47
      pain/pain.go

2
cmd/createbatch/.gitignore

@ -0,0 +1,2 @@
createbatch
config.go

27
cmd/createbatch/main.go

@ -0,0 +1,27 @@
package main
import (
"encoding/xml"
"fmt"
"log"
"time"
"src.wolkict.net/sepa/pain"
)
func main() {
d := pain.NewDocument("PayPro B.V")
d.SetMeta(CREDITOR_NAME, CREDITOR_ADDR1, CREDITOR_ADDR2, CREDITOR_IBAN, CREDITOR_BIC, CREDITOR_ID,
time.Date(2020, time.January, 30, 12, 0, 0, 0, time.UTC), "RCUR")
err := d.Finalize("asdfasdf")
if err != nil {
log.Fatalf("finalizing failed: %v", err)
}
xml, err := xml.Marshal(d)
if err != nil {
log.Fatalf("marshaling failed: %v", err)
}
fmt.Printf("%v", string(xml))
}

91
pain/api.go

@ -0,0 +1,91 @@
package pain
import (
// "fmt"
"time"
)
func NewDocument(initParty string) *Document {
return &Document{
XmlnsXsi: PAIN_XMLNS_XSI,
Namespace: PAIN_XMLNS,
Contents: &PainXML{
GroupHeader: NewGrpHdr(initParty),
PaymentInformation: make([]PmtInf, 0),
TransactionInformation: make([]TxInf, 0),
},
}
}
func (d *Document) SetMeta(creditorName, creditorAddr1, creditorAddr2, creditorIBAN, creditorBIC,
creditorId string, collectionDate time.Time, sequenceType string) {
creditor := Cdtr{
Name: creditorName,
PostalAddress: PstlAdr{
Country: "NL", // XXX: make customizable?
AddressLines: []AdrLine{
AdrLine(creditorAddr1),
AdrLine(creditorAddr2),
},
},
}
creditorAccount := CdtrAcct{
Id: IBAN{
IBAN: creditorIBAN,
},
}
creditorAgent := CdtrAgt{
InstitutionId: FinInstnId{
BIC: creditorBIC,
},
}
creditorSchemeId := CdtrSchmeId{
Id: NewPartyIdSEPA3(creditorId),
}
paymentInfo := PmtInf{
//Id: set in Finalize()
Method: "DD",
PaymentMeta: PmtTpInf{
ServiceLevel: Code{
Code: "SEPA",
},
LocalInstrument: Code{
Code: "CORE",
},
SequenceType: sequenceType,
},
CollectionDate: collectionDate.Format("2006-01-02"),
Creditor: creditor,
CreditorAccount: creditorAccount,
CreditorAgent: creditorAgent,
SchemeId: creditorSchemeId,
Transactions: make([]DrctDbtTxInf, 0),
}
d.Contents.PaymentInformation = append(d.Contents.PaymentInformation, paymentInfo)
}
func (d *Document) Finalize(msgId string) error {
// GroupHeader:
// Calculate CtrlSum
// Set Timestamp
// Set number of transactions
// Set msgId
/*
if len(d.Contents.PaymentInformation) == 0 {
return fmt.Errorf("no payment information, aborting")
}
if len(d.Contents.TransactionInformation) == 0 {
return fmt.Errorf("no transaction information, aborting")
}
*/
//csum := 0.0
return d.Valid()
}
func (d *Document) AddTransaction() {
}

8
pain/group_header.go

@ -13,6 +13,14 @@ type GrpHdr struct {
InitiatingParty PartyIdSEPA1 `xml:"InitgPty"`
}
func NewGrpHdr(initParty string) *GrpHdr {
return &GrpHdr{
InitiatingParty: PartyIdSEPA1{
Name: initParty,
},
}
}
func (g *GrpHdr) Valid() error {
var err []string
if !SEPARegexps["MsgId"].MatchString(g.MessageId) {

47
pain/pain.go

@ -5,16 +5,37 @@ import (
"strings"
)
const (
PAIN_XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance"
PAIN_XMLNS = "urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"
)
type Document struct {
xsi string `xml:"xmlns:xsi,attr"`
namespace string `xml:"xmlns,attr"`
Contents PainXML `xml:"CstmrDrctDbtInitn"`
XmlnsXsi string `xml:"xmlns:xsi,attr"`
Namespace string `xml:"xmlns,attr"`
Contents *PainXML `xml:"CstmrDrctDbtInitn"`
}
// TODO fill in namespace and xsi
func (d *Document) Valid() error {
var err []string
if d.XmlnsXsi != PAIN_XMLNS_XSI {
err = append(err, "xmlns:xsi does not match PAIN_XMLNS_XSI")
}
if d.Namespace != PAIN_XMLNS {
err = append(err, "xmlns does not match PAIN_XMLNS")
}
if e := d.Contents.Valid(); err != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if len(err) > 0 {
return fmt.Errorf("document not valid: %v", strings.Join(err, ", "))
}
return nil
}
type PainXML struct {
GroupHeader GrpHdr `xml:"GrpHdr"`
GroupHeader *GrpHdr `xml:"GrpHdr"`
PaymentInformation []PmtInf `xml:"PmtInf"`
TransactionInformation []TxInf `xml:"DrctDbtTxInf"`
}
@ -85,6 +106,7 @@ func (meta *PmtTpInf) Valid() error {
}
type TxInf struct {
// TODO
}
type PartySEPA2 struct {
@ -104,6 +126,21 @@ type PartyIdSEPA3 struct {
Id PartySEPA2 `xml:"Id"`
}
func NewPartyIdSEPA3(id string) PartyIdSEPA3 {
return PartyIdSEPA3{
Id: PartySEPA2{
PrivateId: PersonIdSEPA2{
Other: RestrictedPersonIdSEPA{
Id: id,
SchemeName: RestrictedPersonIdSchemeNameSEPA{
Party: "SEPA",
},
},
},
},
}
}
func (p *PartyIdSEPA3) Valid() error {
return p.Id.Valid()
}

Loading…
Cancel
Save