Browse Source

PAIN structs ready for minimum required XML

master
Gerdriaan Mulder 6 years ago
parent
commit
d7f295d37d
  1. 1
      pain/group_header.go
  2. 25
      pain/pain.go
  3. 8
      pain/pain_regexp.go
  4. 11
      pain/payment_information.go
  5. 130
      pain/payment_information_transactions.go

1
pain/group_header.go

@ -2,6 +2,7 @@ package pain
import ( import (
"fmt" "fmt"
"strings"
) )
type GrpHdr struct { type GrpHdr struct {

25
pain/pain.go

@ -2,7 +2,6 @@ package pain
import ( import (
"fmt" "fmt"
"regexp"
"strings" "strings"
) )
@ -31,30 +30,10 @@ func (p *PainXML) Valid() error {
return nil return nil
} }
type CdtrAgt struct {
InstitutionId FinInstnId `xml:"FinInstId"`
}
type FinInstnId struct {
BIC string `xml:"BIC"`
}
type CdtrSchmeId struct {
Id PartyIdSEPA3 `xml:"Id"`
}
func (c *CdtrSchmeId) Valid() error {
return c.Id.Valid()
}
type CdtrAcct struct { type CdtrAcct struct {
Id IBAN `xml:"Id"` Id IBAN `xml:"Id"`
} }
type IBAN struct {
IBAN string `xml:"IBAN"`
}
func (c *CdtrAcct) Valid() error { func (c *CdtrAcct) Valid() error {
if e := c.Id.Valid(); e != nil { if e := c.Id.Valid(); e != nil {
return fmt.Errorf("creditor account id not valid: %v", e) return fmt.Errorf("creditor account id not valid: %v", e)
@ -62,6 +41,10 @@ func (c *CdtrAcct) Valid() error {
return nil return nil
} }
type IBAN struct {
IBAN string `xml:"IBAN"`
}
func (i *IBAN) Valid() error { func (i *IBAN) Valid() error {
if !SEPARegexps["IBAN"].MatchString(i.IBAN) { if !SEPARegexps["IBAN"].MatchString(i.IBAN) {
return fmt.Errorf("IBAN does not match format") return fmt.Errorf("IBAN does not match format")

8
pain/pain_regexp.go

@ -11,6 +11,7 @@ var (
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}`)
Max140Text = regexp.MustCompile(`.{1,140}`)
ServiceLevelSEPACode = regexp.MustCompile(`SEPA`) ServiceLevelSEPACode = regexp.MustCompile(`SEPA`)
SequenceType1Code = regexp.MustCompile(`FRST|RCUR|FNAL|OOFF`) SequenceType1Code = regexp.MustCompile(`FRST|RCUR|FNAL|OOFF`)
@ -27,11 +28,13 @@ var (
"BIC": BICIdentifier, "BIC": BICIdentifier,
"CreDtTm": ISODateTime, "CreDtTm": ISODateTime,
"CtrlSum": RestrictedDecimalNumber, "CtrlSum": RestrictedDecimalNumber,
"EndToEndId": RestrictionIdentificationSEPA1, "EndToEndId": RestrictedIdentificationSEPA1,
"IBAN": IBAN2007Identifier, "IBAN": IBAN2007Identifier,
"Id": RestrictedPersonIdentifierSEPA, "Id": RestrictedPersonIdentifierSEPA,
"InstrId": RestrictionIdentificationSEPA1, "InstrId": RestrictedIdentificationSEPA1,
"InstdAmt": RestrictedDecimalNumber, // Note: this is for the value
"MsgId": RestrictedIdentificationSEPA1, "MsgId": RestrictedIdentificationSEPA1,
"MndtId": RestrictedIdentificationSEPA2,
"NbOfTxs": Max15NumericText, "NbOfTxs": Max15NumericText,
"Nm": Max70Text, "Nm": Max70Text,
"PmtInfId": RestrictedIdentificationSEPA1, "PmtInfId": RestrictedIdentificationSEPA1,
@ -40,5 +43,6 @@ var (
"PmtMtd": PaymentMethod2Code, "PmtMtd": PaymentMethod2Code,
"ReqdColltnDt": ISODateTime, "ReqdColltnDt": ISODateTime,
"SeqTp": SequenceType1Code, "SeqTp": SequenceType1Code,
"Ustrd": Max140Text,
} }
) )

11
pain/payment_information.go

@ -2,6 +2,7 @@ package pain
import ( import (
"fmt" "fmt"
"strings"
) )
type PmtInf struct { type PmtInf struct {
@ -56,8 +57,8 @@ type PmtTpInf struct {
} }
type Cdtr struct { type Cdtr struct {
Name string `xml:"Nm"` Name string `xml:"Nm"`
PostalAddress PstlAddr `xml:"PstlAddr"` PostalAddress PstlAdr `xml:"PstlAdr"`
} }
func (c *Cdtr) Valid() error { func (c *Cdtr) Valid() error {
@ -76,12 +77,12 @@ func (c *Cdtr) Valid() error {
} }
type AdrLine string type AdrLine string
type PstlAddr struct { type PstlAdr struct {
Country string `xml:"Ctry"` Country string `xml:"Ctry"`
AddressLines []AdrLine `xml:"AdrLine"` AddressLines []AdrLine `xml:"AdrLine"`
} }
func (p *PstlAddr) Valid() error { func (p *PstlAdr) Valid() error {
var err []string var err []string
if !SEPARegexps["Ctry"].MatchString(p.Country) { if !SEPARegexps["Ctry"].MatchString(p.Country) {
err = append(err, "country does not match format") err = append(err, "country does not match format")
@ -107,7 +108,7 @@ type CdtrAgt struct {
} }
func (c *CdtrAgt) Valid() error { func (c *CdtrAgt) Valid() error {
return c.InstituionId.Valid() return c.InstitutionId.Valid()
} }
type FinInstnId struct { type FinInstnId struct {

130
pain/payment_information_transactions.go

@ -6,8 +6,40 @@ import (
) )
type DrctDbtTxInf struct { type DrctDbtTxInf struct {
Id PaymentId `xml:"PmtId"` Id PaymentId `xml:"PmtId"`
Amount CurrencyWithAmount `xml:"InstdAmt"` Amount CurrencyWithAmount `xml:"InstdAmt"`
Transaction DrctDbtTx `xml:"DrctDbtTx"`
Agent DbtrAgt `xml:"DbtrAgt"`
Debtor Dbtr `xml:"Dbtr"`
Account DbtrAcct `xml:"DbtrAcct"`
Info RmtInf `xml:"RmtInf"`
}
func (d *DrctDbtTxInf) Valid() error {
var err []string
if e := d.Id.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if e := d.Amount.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if e := d.Transaction.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if e := d.Agent.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if e := d.Debtor.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if e := d.Account.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if len(err) > 0 {
return fmt.Errorf("direct debit transaction information not valid: %v", strings.Join(err, ", "))
}
return nil
} }
type CurrencyWithAmount struct { type CurrencyWithAmount struct {
@ -15,6 +47,21 @@ type CurrencyWithAmount struct {
Value string `xml:",innerxml"` Value string `xml:",innerxml"`
} }
func (c *CurrencyWithAmount) Valid() error {
var err []string
if c.Currency != "EUR" {
err = append(err, "expected Ccy EUR")
}
if !SEPARegexps["InstdAmnt"].MatchString(c.Value) {
err = append(err, "value does not match format")
}
if len(err) > 0 {
return fmt.Errorf("currency with amount not valid: %v", strings.Join(err, ", "))
}
return nil
}
type PaymentId struct { type PaymentId struct {
InstrumentId string `xml:"InstrId"` InstrumentId string `xml:"InstrId"`
EndToEndId string `xml:"EndToEndId"` EndToEndId string `xml:"EndToEndId"`
@ -34,3 +81,82 @@ func (p *PaymentId) Valid() error {
} }
return nil return nil
} }
type MndtRltdInf struct {
Id string `xml:"MndtId"`
SignatureDate string `xml:"DtOfSgntr"`
IsAmended bool `xml:"AmdmntInd"`
//AmdmntInfDtls is optional
//ElctrncSgntr is optional
}
func (m *MndtRltdInf) Valid() error {
var err []string
if !SEPARegexps["MndtId"].MatchString(m.Id) {
err = append(err, "mandate id does not match format")
}
if !SEPARegexps["DtOfSgntr"].MatchString(m.SignatureDate) {
err = append(err, "date of signature does not match format")
}
if len(err) > 0 {
return fmt.Errorf("mandate related information is not valid: %v", strings.Join(err, ", "))
}
return nil
}
type DrctDbtTx struct {
MandateRelatedInfo MndtRltdInf `xml:"MndtRltdInf"`
//CdtrSchemeId is optional
}
func (d *DrctDbtTx) Valid() error {
return d.MandateRelatedInfo.Valid()
}
type DbtrAgt struct {
InstitutionId FinInstnId `xml:"FinInstId"`
}
func (d *DbtrAgt) Valid() error {
return d.InstitutionId.Valid()
}
type Dbtr struct {
Name string `xml:"Nm"`
Address PstlAdr `xml:"PstlAdr"`
}
func (d *Dbtr) Valid() error {
var err []string
if !SEPARegexps["Nm"].MatchString(d.Name) {
err = append(err, "name does not match format")
}
if e := d.Address.Valid(); e != nil {
err = append(err, fmt.Sprintf("%v", e))
}
if len(err) > 0 {
return fmt.Errorf("dbtr not valid: %v", strings.Join(err, ", "))
}
return nil
}
type DbtrAcct struct {
Id IBAN `xml:"IBAN"`
}
func (d *DbtrAcct) Valid() error {
return d.Id.Valid()
}
type RmtInf struct {
Value string `xml:"Ustrd"`
}
func (r *RmtInf) Valid() error {
if !SEPARegexps["Ustrd"].MatchString(r.Value) {
return fmt.Errorf("remittance information does not match format")
}
return nil
}

Loading…
Cancel
Save