verifactu: add client and XML structures for AEAT communication
This commit is contained in:
parent
fa59c984bc
commit
fbd5e72774
|
|
@ -0,0 +1,87 @@
|
|||
package verifactu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Environment string
|
||||
CertPath string
|
||||
CertPass string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
cfg Config
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func NewClient(cfg Config) *Client {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
return &Client{
|
||||
cfg: cfg,
|
||||
httpClient: &http.Client{Transport: tr},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetEndpoint() string {
|
||||
if c.cfg.Environment == "production" {
|
||||
return "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tikeV1.0/cont/ws/SistemaFacturacion.wsdl"
|
||||
}
|
||||
return "https://prewww2.aeat.es/static_files/common/internet/dep/aplicaciones/es/aeat/tikeV1.0/cont/ws/SistemaFacturacion.wsdl"
|
||||
}
|
||||
|
||||
type XMLRequest struct {
|
||||
XMLName xml.Name `xml:"soapenv:Envelope"`
|
||||
Xmlns string `xml:"xmlns:soapenv,attr"`
|
||||
XmlnsXsi string `xml:"xmlns:xsi,attr"`
|
||||
XmlnsSum string `xml:"xmlns:sum,attr"`
|
||||
XmlnsSum1 string `xml:"xmlns:sum1,attr"`
|
||||
XmlnsXd string `xml:"xmlns:xd,attr"`
|
||||
Header interface{} `xml:"soapenv:Header"`
|
||||
Body XMLBody `xml:"soapenv:Body"`
|
||||
}
|
||||
|
||||
type XMLBody struct {
|
||||
Content interface{} `xml:",any"`
|
||||
}
|
||||
|
||||
func (c *Client) Send(xmlPayload interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := xml.NewEncoder(&buf)
|
||||
err := enc.Encode(xmlPayload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode XML: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", c.GetEndpoint(), &buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "text/xml; charset=utf-8")
|
||||
req.Header.Set("SOAPAction", "")
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
package verifactu
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AltaRequest struct {
|
||||
Cabecera Cabecera `xml:"sum:RegFactuSistemaFacturacion>sum:Cabecera"`
|
||||
RegistroAlta RegistroAlta `xml:"sum:RegFactuSistemaFacturacion>sum:RegistroFactura>sum1:RegistroAlta"`
|
||||
}
|
||||
|
||||
type Cabecera struct {
|
||||
ObligadoEmision ObligadoEmision `xml:"sum1:ObligadoEmision"`
|
||||
}
|
||||
|
||||
type ObligadoEmision struct {
|
||||
NombreRazon string `xml:"sum1:NombreRazon"`
|
||||
NIF string `xml:"sum1:NIF"`
|
||||
}
|
||||
|
||||
type RegistroAlta struct {
|
||||
IDVersion string `xml:"sum1:IDVersion"`
|
||||
IDFactura IDFactura `xml:"sum1:IDFactura"`
|
||||
NombreRazonEmisor string `xml:"sum1:NombreRazonEmisor"`
|
||||
TipoFactura string `xml:"sum1:TipoFactura"`
|
||||
DescripcionOperacion string `xml:"sum1:DescripcionOperacion"`
|
||||
Destinatarios *Destinatarios `xml:"sum1:Desglose>sum1:DetalleDesglose"`
|
||||
Desglose Desglose `xml:"sum1:Desglose"`
|
||||
CuotaTotal string `xml:"sum1:CuotaTotal"`
|
||||
ImporteTotal string `xml:"sum1:ImporteTotal"`
|
||||
Encadenamiento Encadenamiento `xml:"sum1:Encadenamiento"`
|
||||
SistemaInformatico SistemaInformatico `xml:"sum1:SistemaInformatico"`
|
||||
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
|
||||
TipoHuella string `xml:"sum1:TipoHuella"`
|
||||
Huella string `xml:"sum1:Huella"`
|
||||
}
|
||||
|
||||
type IDFactura struct {
|
||||
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
|
||||
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
|
||||
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
|
||||
}
|
||||
|
||||
type Destinatarios struct {
|
||||
IDDestinatario []IDDestinatario `xml:"sum1:IDDestinatario"`
|
||||
}
|
||||
|
||||
type IDDestinatario struct {
|
||||
NombreRazon string `xml:"sum1:NombreRazon"`
|
||||
NIF string `xml:"sum1:NIF"`
|
||||
}
|
||||
|
||||
type Desglose struct {
|
||||
DetalleDesglose []DetalleDesglose `xml:"sum1:DetalleDesglose"`
|
||||
}
|
||||
|
||||
type DetalleDesglose struct {
|
||||
ClaveRegimen string `xml:"sum1:ClaveRegimen"`
|
||||
CalificacionOperacion string `xml:"sum1:CalificacionOperacion"`
|
||||
TipoImpositivo string `xml:"sum1:TipoImpositivo"`
|
||||
BaseImponibleOimporteNoSujeto string `xml:"sum1:BaseImponibleOimporteNoSujeto"`
|
||||
CuotaRepercutida string `xml:"sum1:CuotaRepercutida"`
|
||||
}
|
||||
|
||||
type Encadenamiento struct {
|
||||
PrimerRegistro string `xml:"sum1:PrimerRegistro,omitempty"`
|
||||
RegistroAnterior *RegistroAnterior `xml:"sum1:RegistroAnterior,omitempty"`
|
||||
}
|
||||
|
||||
type RegistroAnterior struct {
|
||||
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
|
||||
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
|
||||
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
|
||||
Huella string `xml:"sum1:Huella"`
|
||||
}
|
||||
|
||||
type SistemaInformatico struct {
|
||||
NombreRazon string `xml:"sum1:NombreRazon"`
|
||||
NIF string `xml:"sum1:NIF"`
|
||||
NombreSistemaInformatico string `xml:"sum1:NombreSistemaInformatico"`
|
||||
IdSistemaInformatico string `xml:"sum1:IdSistemaInformatico"`
|
||||
Version string `xml:"sum1:Version"`
|
||||
NumeroInstalacion string `xml:"sum1:NumeroInstalacion"`
|
||||
TipoUsoPosibleSoloVerifactu string `xml:"sum1:TipoUsoPosibleSoloVerifactu"`
|
||||
TipoUsoPosibleMultiOT string `xml:"sum1:TipoUsoPosibleMultiOT"`
|
||||
IndicadorMultiplesOT string `xml:"sum1:IndicadorMultiplesOT"`
|
||||
}
|
||||
|
||||
type AnulacionRequest struct {
|
||||
Cabecera Cabecera `xml:"sum:RegFactuSistemaFacturacion>sum:Cabecera"`
|
||||
RegistroAnulacion RegistroAnulacion `xml:"sum:RegFactuSistemaFacturacion>sum:RegistroFactura>sum1:RegistroAnulacion"`
|
||||
}
|
||||
|
||||
type RegistroAnulacion struct {
|
||||
IDVersion string `xml:"sum1:IDVersion"`
|
||||
IDFacturaAnulada IDFacturaAnulada `xml:"sum1:IDFacturaAnulada"`
|
||||
Encadenamiento Encadenamiento `xml:"sum1:Encadenamiento"`
|
||||
SistemaInformatico SistemaInformatico `xml:"sum1:SistemaInformatico"`
|
||||
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
|
||||
TipoHuella string `xml:"sum1:TipoHuella"`
|
||||
Huella string `xml:"sum1:Huella"`
|
||||
}
|
||||
|
||||
type IDFacturaAnulada struct {
|
||||
IDEmisorFacturaAnulada string `xml:"sum1:IDEmisorFacturaAnulada"`
|
||||
NumSerieFacturaAnulada string `xml:"sum1:NumSerieFacturaAnulada"`
|
||||
FechaExpedicionFacturaAnulada string `xml:"sum1:FechaExpedicionFacturaAnulada"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Body ResponseBody
|
||||
}
|
||||
|
||||
type ResponseBody struct {
|
||||
XMLName xml.Name `xml:"Body"`
|
||||
Fault *Fault `xml:"Fault,omitempty"`
|
||||
RegistroRespuesta *RegistroRespuesta `xml:"RegistroRespuesta,omitempty"`
|
||||
}
|
||||
|
||||
type Fault struct {
|
||||
FaultCode string `xml:"faultcode"`
|
||||
FaultString string `xml:"faultstring"`
|
||||
}
|
||||
|
||||
type RegistroRespuesta struct {
|
||||
CSV string `xml:"CSV"`
|
||||
Estado string `xml:"Estado"`
|
||||
}
|
||||
|
||||
func BuildAltaRequest(emisorNombre string, data interface{}) (*AltaRequest, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func BuildAnulacionRequest(emisorNombre string, data interface{}) (*AnulacionRequest, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
Loading…
Reference in New Issue