Browse Source

Initial structs for PAIN.008.002, preliminary validation functions

master
Gerdriaan Mulder 6 years ago
parent
commit
0e1c4d4be4
  1. 147
      pain.go
  2. 19
      pain_regexp.go

147
pain.go

@ -0,0 +1,147 @@
package sepa
import (
"fmt"
"regexp"
"strings"
)
var (
SEPARegexps = map[string]*regexp.Regexp{
"MsgId": RestrictedIdentificationSEPA1,
"CreDtTm": ISODateTime,
"NbOfTxs": Max15NumericText,
"CtrlSum": RestrictedDecimalNumber,
"Nm": Max70Text,
"PmtInfId": RestrictedIdentificationSEPA1,
"PmtMtd": PaymentMethod2Code,
"PmtMetaSvcLvl": ServiceLevelSEPACode,
"PmtMetaLclInstrm": LocalInstrumentSEPACode,
"SeqTp": SequenceType1Code,
}
)
type PainXML struct {
GroupHeader GrpHdr `xml:"GrpHdr"`
PaymentInformation []PmtInf `xml:"PmtInf"`
TransactionInformation []TxInf `xml:"DrctDbtTxInf"`
}
func (p *PainXML) Valid() error {
var err []string
if e := p.GroupHeader.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if len(p.PaymentInformation) < 1 {
err = append(err, "no payment information")
}
if len(p.TransactionInformation) < 1 {
err = append(err, "no transaction information")
}
if len(err) > 0 {
return fmt.Errorf("pain XML not valid: %v", strings.Join(err, ", "))
}
return nil
}
type GrpHdr struct {
MessageId string `xml:"MsgId"`
Timestamp string `xml:"CreDtTm"`
NumTx string `xml:"NbOfTxs"`
Sum string `xml:"CtrlSum"`
InitiatingParty InitgPty `xml:"InitgPty"`
}
func (g *GrpHdr) Valid() error {
var err []string
if !SEPARegexps["MsgId"].MatchString(g.MessageId) {
err = append(err, "msgId did not match expected format")
}
if !SEPARegexps["CreDtTm"].MatchString(g.Timestamp) {
err = append(err, "timestamp did not match expected format")
}
if !SEPARegexps["NbOfTxs"].MatchString(g.NumTx) {
err = append(err, "numtx did not match expected format")
}
if !SEPARegexps["CtrlSum"].MatchString(g.Sum) {
err = append(err, "sum did not match expected format")
}
// TODO
/*
if g.InitiatingParty == nil {
err = append(err, "no initiating party found")
} else {
if !SEPARegexps["Nm"].MatchString(g.InitiatingParty.Name) {
err = append(err, "initiating party's name did not match expected format")
}
}
*/
if len(err) > 0 {
return fmt.Errorf("group header not valid: %v", strings.Join(err, ", "))
}
return nil
}
type PmtInf struct {
Id string `xml:"PmtInfId"`
Method string `xml:"PmtMtd"`
PaymentMeta PmtTpInf `xml:"PmtTpInf"`
}
func (pmt *PmtInf) Valid() error {
var err []string
if !SEPARegexps["PmtInfId"].MatchString(pmt.Id) {
err = append(err, "payment info id does not match expected format")
}
if !SEPARegexps["PmtMtd"].MatchString(pmt.Method) {
err = append(err, "payment info id does not match expected format")
}
if e := pmt.PaymentMeta.Valid(); e != nil {
err = append(err, fmt.Sprintf("payment meta not valid: %v", e))
}
if len(err) > 0 {
return fmt.Errorf("payment info (Id: %q) not valid: %v", pmt.Id, strings.Join(err, ", "))
}
return nil
}
type PmtTpInf struct {
ServiceLevel Code `xml:"SvcLvl"`
LocalInstrument Code `xml:"LclIntrm"`
SequenceType string `xml:"SeqTp"`
}
type Code struct {
Code string `xml:"Cd"`
}
func (meta *PmtTpInf) Valid() error {
var err []string
// TODO: check meta.ServiceLevel for nil
if !SEPARegexps["PmtMetaSvcLvl"].MatchString(meta.ServiceLevel.Code) {
err = append(err, "incorrect service level present (must be 'SEPA')")
}
// TODO: check meta.LocalInstrument for nil
if !SEPARegexps["PmtMetaLclInstrm"].MatchString(meta.LocalInstrument.Code) {
err = append(err, "incorrect local instrument present")
}
if !SEPARegexps["SeqTp"].MatchString(meta.SequenceType) {
err = append(err, "sequence type has incorrect format")
}
if len(err) > 0 {
return fmt.Errorf("payment meta not valid: %v", strings.Join(err, ", "))
}
return nil
}
type TxInf struct {
}
type InitgPty struct {
Name string `xml:"Nm"`
}

19
pain_regexp.go

@ -0,0 +1,19 @@
package sepa
import (
"regexp"
)
var (
ISODateTime = regexp.MustCompile(`\d{4}(-\d\d){2}T\d\d(:\d\d){2}`)
RestrictedIdentificationSEPA1 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}`)
RestrictedIdentificationSEPA2 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){1,35}`)
Max15NumericText = regexp.MustCompile(`[0-9]{1,15}`)
RestrictedDecimalNumber = regexp.MustCompile(`[+-]\d+\.\d\d`)
Max70Text = regexp.MustCompile(`.{1,70}`)
ServiceLevelSEPACode = regexp.MustCompile(`SEPA`)
SequenceType1Code = regexp.MustCompile(`FRST|RCUR|FNAL|OOFF`)
PaymentMethod2Code = regexp.MustCompile(`DD`)
LocalInstrumentSEPACode = regexp.MustCompile(`CORE|B2B`)
)
Loading…
Cancel
Save