Go
Cliente HTTP idiomático para Go. Define los structs de request y response, genera un Idempotency-Key automático si no se especifica, y propaga los errores HTTP con el body como contexto.
package lxs
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/google/uuid"
)
type Client struct {
BaseURL string
APIKey string
http *http.Client
}
func NewClient(apiKey string) *Client {
return &Client{
BaseURL: "https://api.lxsyscr.com",
APIKey: apiKey,
http: &http.Client{Timeout: 30 * time.Second},
}
}
type FacturaRequest struct {
Tipo string `json:"tipo"`
Cliente *Cliente `json:"cliente,omitempty"`
CondicionVenta string `json:"condicionVenta"`
MedioPago string `json:"medioPago"`
Moneda string `json:"moneda"`
Lineas []Linea `json:"lineas"`
Referencias []Referencia `json:"referencias,omitempty"`
}
type Cliente struct {
IDCliente int `json:"idCliente"`
}
type Linea struct {
IDProducto int `json:"idProducto"`
Cantidad float64 `json:"cantidad"`
PrecioUnitario *float64 `json:"precioUnitario,omitempty"`
}
type Referencia struct {
TipoDocumento string `json:"tipoDocumento"`
Numero string `json:"numero"`
Codigo string `json:"codigo,omitempty"`
Razon string `json:"razon,omitempty"`
}
type FacturaResponse struct {
Clave string `json:"clave"`
NumeroConsecutivo string `json:"numeroConsecutivo"`
TipoDocumento string `json:"tipoDocumento"`
EstadoHacienda string `json:"estadoHacienda"`
TotalComprobante float64 `json:"totalComprobante"`
Moneda string `json:"moneda"`
FechaEmision string `json:"fechaEmision"`
}
func (c *Client) Emitir(req FacturaRequest, idempotencyKey string) (*FacturaResponse, error) {
if idempotencyKey == "" {
idempotencyKey = uuid.New().String()
}
body, _ := json.Marshal(req)
httpReq, _ := http.NewRequest("POST", c.BaseURL+"/api/v1/facturas", bytes.NewReader(body))
httpReq.Header.Set("X-Api-Key", c.APIKey)
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Idempotency-Key", idempotencyKey)
res, err := c.http.Do(httpReq)
if err != nil { return nil, err }
defer res.Body.Close()
if res.StatusCode >= 400 {
b, _ := io.ReadAll(res.Body)
return nil, fmt.Errorf("HTTP %d: %s", res.StatusCode, b)
}
var resp FacturaResponse
if err := json.NewDecoder(res.Body).Decode(&resp); err != nil { return nil, err }
return &resp, nil
}