From 06ac3c972583582d6b28fbaab995f68f7fea2957 Mon Sep 17 00:00:00 2001 From: Merlin Scholz Date: Wed, 13 May 2026 20:15:33 +0200 Subject: Move to proper XML marshalling --- go.mod | 4 -- go.sum | 4 -- order.go | 183 ++++++++++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 122 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index d05e5cf..b9692b1 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,3 @@ module go.scholz.ruhr/libebics go 1.26.2 - -require github.com/beevik/etree v1.6.0 - -require github.com/terminalstatic/go-xsd-validate v0.1.6 // indirect diff --git a/go.sum b/go.sum index a1c3c90..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +0,0 @@ -github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= -github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= -github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo= -github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= diff --git a/order.go b/order.go index bf90078..eea8d5c 100644 --- a/order.go +++ b/order.go @@ -4,81 +4,142 @@ import ( "bytes" "compress/zlib" "encoding/base64" + "encoding/xml" "fmt" - - "github.com/beevik/etree" ) +type EbicsUnsecuredRequest struct { + XMLName xml.Name `xml:"ebicsUnsecuredRequest"` + Xmlns string `xml:"xmlns,attr"` + Version string `xml:"Version,attr"` + Revision string `xml:"Revision,attr"` + Header EbicsHeader `xml:"header"` + Body EbicsBody `xml:"body"` +} + +type EbicsHeader struct { + XMLName xml.Name `xml:"header"` + Authenticate bool `xml:"authenticate,attr"` + Static EbicsHeaderStatic `xml:"static"` + Mutable EbicsHeaderMutable `xml:"mutable"` +} + +type EbicsHeaderStatic struct { + XMLName xml.Name `xml:"static"` + HostID string `xml:"HostID"` + PartnerID string `xml:"PartnerID"` + UserID string `xml:"UserID"` + Product EbicsProduct `xml:"Product"` + OrderDetails EbicsOrderDetails `xml:"OrderDetails"` + SecurityMedium string `xml:"SecurityMedium"` +} + +type EbicsProduct struct { + XMLName xml.Name `xml:"Product"` + Language string `xml:"Language,attr"` + Name string `xml:",chardata"` +} + +type EbicsOrderDetails struct { + XMLName xml.Name `xml:"OrderDetails"` + AdminOrderType string `xml:"AdminOrderType"` +} + +type EbicsHeaderMutable struct { + XMLName xml.Name `xml:"mutable"` +} + +type EbicsBody struct { + XMLName xml.Name `xml:"body"` + DataTransfer EbicsDataTransfer `xml:"DataTransfer"` +} + +type EbicsDataTransfer struct { + XMLName xml.Name `xml:"DataTransfer"` + OrderData string `xml:"OrderData"` // TODO Properly marshal this +} + +type EbicsSignaturePubKeyOrderData struct { + XMLName xml.Name `xml:"esig:SignaturePubKeyOrderData"` + Esig string `xml:"xmlns:esi,attr"` + Ds string `xml:"xmlns:ds,attr"` + SignaturePubKeyInfo EbicsSignaturePubKeyInfo `xml:"esig:SignaturePubKeyInfo"` + PartnerID string `xml:"esig:PartnerID"` + UserID string `xml:"esig:UserID"` +} + +type EbicsSignaturePubKeyInfo struct { + XMLName xml.Name `xml:"esig:SignaturePubKeyInfo"` + X509Data EbicsX509Data `xml:"ds:X509Data"` + SignatureVersion string `xml:"esig:SignatureVersion"` // TODO Use ENUM +} + +type EbicsX509Data struct { + XMLName xml.Name `xml:"ds:X509Data"` + X509Certificate string `xml:"ds:X509Certificate"` // TODO Properly marshal this +} + func GenerateIniRequest(signatureCertificate EbicsCertificate) (string, error) { + if signatureCertificate.ebicsCertificateType != A005 && signatureCertificate.ebicsCertificateType != A006 { return "", fmt.Errorf("signature certificate has invalid certificate type %s", signatureCertificate.ebicsCertificateType.String()) } + var zlibWriterBuffer bytes.Buffer zlibWriter := zlib.NewWriter(&zlibWriterBuffer) - var orderdata *etree.Element - - ini := etree.NewDocument() - ini.Indent(2) // Not technically efficient but nice for debugging purposes - ini.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`) - ini.CreateChild("ebicsUnsecuredRequest", func(e *etree.Element) { - e.CreateAttr("xmlns", "urn:org:ebics:H005") - e.CreateAttr("Version", "H005") - e.CreateAttr("Revision", "1") - - e.CreateChild("header", func(e *etree.Element) { - e.CreateAttr("authenticate", "true") - e.CreateChild("static", func(e *etree.Element) { - e.CreateElement("HostID").CreateText("MULTIVIA") - e.CreateElement("PartnerID").CreateText("MV008078") - e.CreateElement("UserID").CreateText("SCHOLZ01") - e.CreateChild("Product", func(e *etree.Element) { - e.CreateAttr("Language", "en") - e.CreateText("libebics") - }) - e.CreateElement("OrderDetails").CreateElement("AdminOrderType").CreateText("INI") - e.CreateElement("SecurityMedium").CreateText("0000") - }) - e.CreateElement("mutable") - }) - - e.CreateChild("body", func(e *etree.Element) { - orderdata = e.CreateElement("DataTransfer").CreateElement("OrderData") - }) - }) - - orderdata_content := etree.NewDocument() - orderdata_content.Indent(2) // Not technically efficient but nice for debugging purposes - orderdata_content.CreateChild("esig:SignaturePubKeyOrderData", func(e *etree.Element) { - e.CreateAttr("xmlns:esig", "http://www.ebics.org/S002") - e.CreateAttr("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") - e.CreateChild("esig:SignaturePubKeyInfo", func(e *etree.Element) { - e.CreateChild("ds:X509Data", func(e *etree.Element) { - e.CreateElement("ds:X509Certificate").CreateText( - base64.StdEncoding.EncodeToString( - signatureCertificate.x509Certificate, - ), - ) - }) - e.CreateElement("esig:SignatureVersion").CreateText(signatureCertificate.ebicsCertificateType.String()) - }) - e.CreateElement("esig:PartnerID").CreateText("MV008078") - e.CreateElement("esig:UserID").CreateText("SCHOLZ01") - }) - - orderdata_bytes, err := orderdata_content.WriteToBytes() + orderData := EbicsSignaturePubKeyOrderData{ + SignaturePubKeyInfo: EbicsSignaturePubKeyInfo{ + X509Data: EbicsX509Data{ + X509Certificate: base64.StdEncoding.EncodeToString( + signatureCertificate.x509Certificate, + ), + }, + SignatureVersion: signatureCertificate.ebicsCertificateType.String(), + }, + PartnerID: "MV008078", + UserID: "SCHOLZ01", + } + + orderData_xml, err := xml.Marshal(orderData) if err != nil { - panic(err.Error()) + return "", err } - zlibWriter.Write(orderdata_bytes) + + zlibWriter.Write(orderData_xml) zlibWriter.Close() - orderdata.CreateText( - base64.StdEncoding.EncodeToString( - zlibWriterBuffer.Bytes(), - ), - ) + ini := EbicsUnsecuredRequest{ + Xmlns: "urn:org:ebics:H005", + Version: "H005", + Revision: "1", + Header: EbicsHeader{ + Authenticate: true, + Static: EbicsHeaderStatic{ + HostID: "MULTIVIA", + PartnerID: "MV008078", + UserID: "SCHOLZ01", + Product: EbicsProduct{ + Language: "en", + Name: "libebics", + }, + OrderDetails: EbicsOrderDetails{ + AdminOrderType: "INI", + }, + SecurityMedium: "0000", + }, + }, + Body: EbicsBody{ + DataTransfer: EbicsDataTransfer{ + OrderData: base64.StdEncoding.EncodeToString( + zlibWriterBuffer.Bytes(), + ), + }, + }, + } + + marshal, err := xml.MarshalIndent(ini, "", " ") - return ini.WriteToString() + return (xml.Header + string(marshal)), err } -- cgit