Browse Source

Added validation until CdtrAcct

master
Gerdriaan Mulder 6 years ago
parent
commit
ac83bb06dd
  1. 95
      pain.go
  2. 4
      pain_regexp.go

95
pain.go

@ -10,6 +10,7 @@ var (
SEPARegexps = map[string]*regexp.Regexp{ SEPARegexps = map[string]*regexp.Regexp{
"MsgId": RestrictedIdentificationSEPA1, "MsgId": RestrictedIdentificationSEPA1,
"CreDtTm": ISODateTime, "CreDtTm": ISODateTime,
"ReqdColltnDt": ISODateTime,
"NbOfTxs": Max15NumericText, "NbOfTxs": Max15NumericText,
"CtrlSum": RestrictedDecimalNumber, "CtrlSum": RestrictedDecimalNumber,
"Nm": Max70Text, "Nm": Max70Text,
@ -18,6 +19,7 @@ var (
"PmtMetaSvcLvl": ServiceLevelSEPACode, "PmtMetaSvcLvl": ServiceLevelSEPACode,
"PmtMetaLclInstrm": LocalInstrumentSEPACode, "PmtMetaLclInstrm": LocalInstrumentSEPACode,
"SeqTp": SequenceType1Code, "SeqTp": SequenceType1Code,
"IBAN": IBAN2007Identifier,
} }
) )
@ -68,16 +70,10 @@ func (g *GrpHdr) Valid() error {
if !SEPARegexps["CtrlSum"].MatchString(g.Sum) { if !SEPARegexps["CtrlSum"].MatchString(g.Sum) {
err = append(err, "sum did not match expected format") err = append(err, "sum did not match expected format")
} }
// TODO // Note: we assume g.InitiatingParty is initialized.
/*
if g.InitiatingParty == nil {
err = append(err, "no initiating party found")
} else {
if !SEPARegexps["Nm"].MatchString(g.InitiatingParty.Name) { if !SEPARegexps["Nm"].MatchString(g.InitiatingParty.Name) {
err = append(err, "initiating party's name did not match expected format") err = append(err, "initiating party's name did not match expected format")
} }
}
*/
if len(err) > 0 { if len(err) > 0 {
return fmt.Errorf("group header not valid: %v", strings.Join(err, ", ")) return fmt.Errorf("group header not valid: %v", strings.Join(err, ", "))
@ -89,6 +85,9 @@ type PmtInf struct {
Id string `xml:"PmtInfId"` Id string `xml:"PmtInfId"`
Method string `xml:"PmtMtd"` Method string `xml:"PmtMtd"`
PaymentMeta PmtTpInf `xml:"PmtTpInf"` PaymentMeta PmtTpInf `xml:"PmtTpInf"`
CollectionDate string `xml:"ReqdColltnDt"`
Creditor Cdtr `xml:"Cdtr"`
CreditorAccount CdtrAcct `xml:"CdtrAcct"`
} }
func (pmt *PmtInf) Valid() error { func (pmt *PmtInf) Valid() error {
@ -97,11 +96,20 @@ func (pmt *PmtInf) Valid() error {
err = append(err, "payment info id does not match expected format") err = append(err, "payment info id does not match expected format")
} }
if !SEPARegexps["PmtMtd"].MatchString(pmt.Method) { if !SEPARegexps["PmtMtd"].MatchString(pmt.Method) {
err = append(err, "payment info id does not match expected format") err = append(err, "payment method does not match expected format")
} }
if e := pmt.PaymentMeta.Valid(); e != nil { if e := pmt.PaymentMeta.Valid(); e != nil {
err = append(err, fmt.Sprintf("payment meta not valid: %v", e)) err = append(err, fmt.Sprintf("payment meta not valid: %v", e))
} }
if !SEPARegexps["ReqdColltnDt"].MatchString(pmt.CollectionDate) {
err = append(err, "payment collection date does not match expected format")
}
if e := pmt.Creditor.Valid(); e != nil {
err = append(err, fmt.Sprintf("payment creditor not valid: %v", e))
}
if e := pmt.CreditorAccount.Valid(); e != nil {
err = append(err, fmt.Sprintf("payment creditor account not valid: %v", e))
}
if len(err) > 0 { if len(err) > 0 {
return fmt.Errorf("payment info (Id: %q) not valid: %v", pmt.Id, strings.Join(err, ", ")) return fmt.Errorf("payment info (Id: %q) not valid: %v", pmt.Id, strings.Join(err, ", "))
@ -115,6 +123,76 @@ type PmtTpInf struct {
SequenceType string `xml:"SeqTp"` SequenceType string `xml:"SeqTp"`
} }
type Cdtr struct {
Name string `xml:"Nm"`
PostalAddress PstlAddr `xml:"PstlAddr"`
}
func (c *Cdtr) Valid() error {
var err []string
if !SEPARegexps["Nm"].MatchString(c.Name) {
err = append(err, "creditor name does not match format")
}
if e := c.PostalAddress.Valid(); e != nil {
err = append(err, fmt.Sprintf("creditor postal address not valid: %v", e))
}
if len(err) > 0 {
return fmt.Errorf("creditor (Nm: %q) not valid: %v", c.Name, strings.Join(err, ", "))
}
return nil
}
type PstlAddr struct {
Country string `xml:"Ctry"`
AddressLines []AdrLine `xml:"AdrLine"`
}
func (p *PstlAddr) Valid() error {
var err []string
if !SEPARegexps["Ctry"].MatchString(p.Country) {
err = append(err, "country does not match format")
}
if len(p.AddressLines) > 2 {
err = append(err, "expected at most 2 address lines")
}
for i, line := range p.AddressLines {
if !SEPARegexps["AdrLine"].MatchString(string(line)) {
err = append(err, fmt.Sprintf("address line %d (%q) does not match format", i, line))
}
}
if len(err) > 0 {
return fmt.Errorf("address not valid: %v", strings.Join(err, ", "))
}
return nil
}
type AdrLine string
type CdtrAcct struct {
Id IBAN `xml:"Id"`
}
type IBAN struct {
IBAN string `xml:"IBAN"`
}
func (c *CdtrAcct) Valid() error {
if e := c.Id.Valid(); e != nil {
return fmt.Errorf("creditor account id not valid: %v", e)
}
return nil
}
func (i *IBAN) Valid() error {
if !SEPARegexps["IBAN"].MatchString(i.IBAN) {
return fmt.Errorf("IBAN does not match format")
}
return nil
}
type Code struct { type Code struct {
Code string `xml:"Cd"` Code string `xml:"Cd"`
} }
@ -144,4 +222,5 @@ type TxInf struct {
type InitgPty struct { type InitgPty struct {
Name string `xml:"Nm"` Name string `xml:"Nm"`
// We do not implement the "Id" element from "PartyIdentificationSEPA1"
} }

4
pain_regexp.go

@ -9,11 +9,13 @@ var (
RestrictedIdentificationSEPA1 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}`) RestrictedIdentificationSEPA1 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}`)
RestrictedIdentificationSEPA2 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){1,35}`) RestrictedIdentificationSEPA2 = regexp.MustCompile(`([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){1,35}`)
Max15NumericText = regexp.MustCompile(`[0-9]{1,15}`) Max15NumericText = regexp.MustCompile(`[0-9]{1,15}`)
RestrictedDecimalNumber = regexp.MustCompile(`[+-]\d+\.\d\d`) RestrictedDecimalNumber = regexp.MustCompile(`[+-]?\d+\.\d\d`)
Max70Text = regexp.MustCompile(`.{1,70}`) Max70Text = regexp.MustCompile(`.{1,70}`)
ServiceLevelSEPACode = regexp.MustCompile(`SEPA`) ServiceLevelSEPACode = regexp.MustCompile(`SEPA`)
SequenceType1Code = regexp.MustCompile(`FRST|RCUR|FNAL|OOFF`) SequenceType1Code = regexp.MustCompile(`FRST|RCUR|FNAL|OOFF`)
PaymentMethod2Code = regexp.MustCompile(`DD`) PaymentMethod2Code = regexp.MustCompile(`DD`)
LocalInstrumentSEPACode = regexp.MustCompile(`CORE|B2B`) LocalInstrumentSEPACode = regexp.MustCompile(`CORE|B2B`)
IBAN2007Identifier = regexp.MustCompile(`[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}`)
) )

Loading…
Cancel
Save