183 lines
4.6 KiB
Go
183 lines
4.6 KiB
Go
|
|
package verifactu
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"encoding/xml"
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
type SOAPEnvelope struct {
|
||
|
|
XMLName xml.Name `xml:"soap:Envelope"`
|
||
|
|
XmlnsSOAP string `xml:"xmlns:soap,attr"`
|
||
|
|
XmlnsSUM string `xml:"xmlns:sum,attr"`
|
||
|
|
XmlnsSUM1 string `xml:"xmlns:sum1,attr"`
|
||
|
|
Header SOAPHeader
|
||
|
|
Body SOAPBody
|
||
|
|
}
|
||
|
|
|
||
|
|
type SOAPHeader struct {
|
||
|
|
XMLName xml.Name `xml:"soap:Header"`
|
||
|
|
Security *SecurityHeader
|
||
|
|
Transaction string `xml:"wsa:Action,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type SecurityHeader struct {
|
||
|
|
XMLName xml.Name `xml:"wsse:Security"`
|
||
|
|
XmlnsWSSE string `xml:"xmlns:wsse,attr"`
|
||
|
|
XmlnsWSSEDSIG string `xml:"xmlns:wssedsig,attr"`
|
||
|
|
BinarySecurityToken *BinarySecurityToken
|
||
|
|
Signature *Signature
|
||
|
|
}
|
||
|
|
|
||
|
|
type BinarySecurityToken struct {
|
||
|
|
XMLName xml.Name `xml:"wsse:BinarySecurityToken"`
|
||
|
|
EncodingType string `xml:"wsse:EncodingType,attr"`
|
||
|
|
ValueType string `xml:"wsse:ValueType,attr"`
|
||
|
|
Id string `xml:"wsu:Id,attr"`
|
||
|
|
Content string `xml:",chardata"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type Signature struct {
|
||
|
|
XMLName xml.Name `xml:"ds:Signature"`
|
||
|
|
XmlnsDS string `xml:"xmlns:ds,attr"`
|
||
|
|
Id string `xml:"Id,attr"`
|
||
|
|
SignedInfo SignedInfo
|
||
|
|
SignatureValue string `xml:"ds:SignatureValue"`
|
||
|
|
KeyInfo KeyInfo
|
||
|
|
}
|
||
|
|
|
||
|
|
type SignedInfo struct {
|
||
|
|
XMLName xml.Name `xml:"ds:SignedInfo"`
|
||
|
|
CanonicalizationMethod CanonicalMethod
|
||
|
|
SignatureMethod SignatureMethod
|
||
|
|
References []Reference
|
||
|
|
}
|
||
|
|
|
||
|
|
type CanonicalMethod struct {
|
||
|
|
XMLName xml.Name `xml:"ds:CanonicalizationMethod"`
|
||
|
|
Algorithm string `xml:"Algorithm,attr"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type SignatureMethod struct {
|
||
|
|
XMLName xml.Name `xml:"ds:SignatureMethod"`
|
||
|
|
Algorithm string `xml:"Algorithm,attr"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type Reference struct {
|
||
|
|
XMLName xml.Name `xml:"ds:Reference"`
|
||
|
|
URI string `xml:"URI,attr"`
|
||
|
|
DigestMethod DigestMethod
|
||
|
|
DigestValue string `xml:"ds:DigestValue"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type DigestMethod struct {
|
||
|
|
XMLName xml.Name `xml:"ds:DigestMethod"`
|
||
|
|
Algorithm string `xml:"Algorithm,attr"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type KeyInfo struct {
|
||
|
|
XMLName xml.Name `xml:"ds:KeyInfo"`
|
||
|
|
SecurityTokenRef SecurityTokenRef
|
||
|
|
}
|
||
|
|
|
||
|
|
type SecurityTokenRef struct {
|
||
|
|
XMLName xml.Name `xml:"wsse:SecurityTokenReference"`
|
||
|
|
Id string `xml:"Id,attr"`
|
||
|
|
Reference Reference2
|
||
|
|
}
|
||
|
|
|
||
|
|
type Reference2 struct {
|
||
|
|
XMLName xml.Name `xml:"wsse:Reference"`
|
||
|
|
URI string `xml:"URI,attr"`
|
||
|
|
ValueType string `xml:"ValueType,attr"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type SOAPBody struct {
|
||
|
|
XMLName xml.Name `xml:"soap:Body"`
|
||
|
|
Content interface{} `xml:",any"`
|
||
|
|
Id string `xml:"wsu:Id,attr"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func BuildSOAPEnvelope(payload interface{}) *SOAPEnvelope {
|
||
|
|
return &SOAPEnvelope{
|
||
|
|
XmlnsSOAP: "http://schemas.xmlsoap.org/soap/envelope/",
|
||
|
|
XmlnsSUM: "https://www.agenciatributaria.gob.es/static/files/common/xsd/sum/information.xsd",
|
||
|
|
XmlnsSUM1: "https://www.agenciatributaria.gob.es/static/files/common/xsd/sum/suministroInformacion.xsd",
|
||
|
|
Body: SOAPBody{
|
||
|
|
Content: payload,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (e *SOAPEnvelope) ToXML() (string, error) {
|
||
|
|
var buf bytes.Buffer
|
||
|
|
enc := xml.NewEncoder(&buf)
|
||
|
|
|
||
|
|
err := enc.Encode(e)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("encoding SOAP envelope: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return buf.String(), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (e *SOAPEnvelope) ToBytes() ([]byte, error) {
|
||
|
|
return xml.Marshal(e)
|
||
|
|
}
|
||
|
|
|
||
|
|
type EnviarFacturaRequest struct {
|
||
|
|
AltaReq *AltaRequest
|
||
|
|
}
|
||
|
|
|
||
|
|
type EnviarAnulacionRequest struct {
|
||
|
|
AnulReq *AnulacionRequest
|
||
|
|
}
|
||
|
|
|
||
|
|
func BuildAltaSOAPRequest(data AltaData) (*SOAPEnvelope, error) {
|
||
|
|
altaReq := BuildAltaRequest(data)
|
||
|
|
|
||
|
|
env := BuildSOAPEnvelope(EnviarFacturaRequest{
|
||
|
|
AltaReq: altaReq,
|
||
|
|
})
|
||
|
|
|
||
|
|
return env, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func BuildAnulacionSOAPRequest(data AltaData) (*SOAPEnvelope, error) {
|
||
|
|
anulReq := BuildAnulacionRequest(data)
|
||
|
|
|
||
|
|
env := BuildSOAPEnvelope(EnviarAnulacionRequest{
|
||
|
|
AnulReq: anulReq,
|
||
|
|
})
|
||
|
|
|
||
|
|
return env, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func ParseResponse(data []byte) (*Response, error) {
|
||
|
|
var env Response
|
||
|
|
err := xml.Unmarshal(data, &env)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("unmarshaling response: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return &env, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func FormatDateDDMMYYYY(date time.Time) string {
|
||
|
|
return date.Format("02-01-2006")
|
||
|
|
}
|
||
|
|
|
||
|
|
func FormatDateTimeDDMMYYYYHHMM(date time.Time) string {
|
||
|
|
return date.Format("02-01-2006T15:04:05")
|
||
|
|
}
|
||
|
|
|
||
|
|
func StripXMLNamespace(data []byte) []byte {
|
||
|
|
str := string(data)
|
||
|
|
str = strings.ReplaceAll(str, "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"", "")
|
||
|
|
str = strings.ReplaceAll(str, "xmlns:sum=\"https://www.agenciatributaria.gob.es/static/files/common/xsd/sum/information.xsd\"", "")
|
||
|
|
str = strings.ReplaceAll(str, "xmlns:sum1=\"https://www.agenciatributaria.gob.es/static/files/common/xsd/sum/suministroInformacion.xsd\"", "")
|
||
|
|
return []byte(str)
|
||
|
|
}
|