120 lines
3.3 KiB
Go
120 lines
3.3 KiB
Go
package facturacionOperaciones
|
|
|
|
import (
|
|
"api-soap-facturacion/internal/config"
|
|
"api-soap-facturacion/internal/logger"
|
|
mfo "api-soap-facturacion/internal/models/facturacionOperaciones"
|
|
"api-soap-facturacion/pkg/soap"
|
|
"bytes"
|
|
"context"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// Constantes de configuración
|
|
const (
|
|
DefaultTimeout = 30 * time.Second
|
|
ContentType = "text/xml;charset=UTF-8"
|
|
SoapAction = "https://siat.impuestos.gob.bo/registroPuntoVenta"
|
|
SiatEndpoint = "https://pilotosiatservicios.impuestos.gob.bo/v2/FacturacionOperaciones"
|
|
)
|
|
|
|
// NewClient crea una nueva instancia del cliente SOAP
|
|
func NewClient(options *ClientOptions, config config.APIConfig, log logger.Logger) *Client {
|
|
|
|
// Configurar cliente SOAP
|
|
factOperaciones := soap.ClientOptions{
|
|
Endpoint: config.Endpoint,
|
|
Username: config.Username,
|
|
Password: config.Password,
|
|
Timeout: config.Timeout * time.Second,
|
|
Headers: map[string]string{
|
|
"User-Agent": "soap-api-client/1.0",
|
|
},
|
|
}
|
|
|
|
client := &Client{
|
|
endpointURL: SiatEndpoint,
|
|
soapClient: soap.NewClient(factOperaciones),
|
|
logger: log,
|
|
}
|
|
|
|
if options != nil {
|
|
if options.EndpointURL != "" {
|
|
client.endpointURL = options.EndpointURL
|
|
}
|
|
|
|
if options.HTTPClient != nil {
|
|
client.httpClient = options.HTTPClient
|
|
}
|
|
}
|
|
|
|
if client.httpClient == nil {
|
|
timeout := DefaultTimeout
|
|
if options != nil && options.Timeout > 0 {
|
|
timeout = options.Timeout
|
|
}
|
|
|
|
client.httpClient = &http.Client{
|
|
Timeout: timeout,
|
|
}
|
|
}
|
|
|
|
return client
|
|
}
|
|
|
|
// envía una solicitud para registrar un punto de venta en SIAT
|
|
func (c *Client) RegistrarPuntoVenta(ctx context.Context, solicitud mfo.SolicitudRegistroPuntoVenta) (*mfo.RespuestaRegistroPuntoVenta, error) {
|
|
// Preparar la petición SOAP
|
|
request := mfo.RegistroPuntoVentaRequest{
|
|
SoapEnv: "http://schemas.xmlsoap.org/soap/envelope/",
|
|
Siat: "https://siat.impuestos.gob.bo/",
|
|
}
|
|
request.Body.RegistroPuntoVenta.Solicitud = solicitud
|
|
|
|
// Convertir la petición a XML
|
|
requestBody, err := xml.MarshalIndent(request, "", " ")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error al convertir la solicitud a XML: %w", err)
|
|
}
|
|
|
|
// Crear la petición HTTP con el contexto
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpointURL, bytes.NewReader(requestBody))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error al crear la petición HTTP: %w", err)
|
|
}
|
|
|
|
// Configurar encabezados
|
|
req.Header.Set("Content-Type", ContentType)
|
|
req.Header.Set("SOAPAction", SoapAction)
|
|
|
|
// Realizar la petición HTTP
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error al realizar la petición HTTP: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Leer el cuerpo de la respuesta
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error al leer la respuesta: %w", err)
|
|
}
|
|
|
|
// Verificar el código de estado HTTP
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("error en la respuesta HTTP: %s, cuerpo: %s", resp.Status, respBody)
|
|
}
|
|
|
|
// Parsear la respuesta
|
|
var soapResponse mfo.RegistroPuntoVentaResponse
|
|
if err := xml.Unmarshal(respBody, &soapResponse); err != nil {
|
|
return nil, fmt.Errorf("error al parsear la respuesta XML: %w, cuerpo: %s", err, respBody)
|
|
}
|
|
|
|
return &soapResponse.Body.RegistroPuntoVentaResponse.Respuesta, nil
|
|
}
|