Python
Cliente HTTP en Python con requests. Reusa una Session para mantener los headers y el pool de conexiones. Incluye también un receptor de webhook con Flask y verificación HMAC.
Setup
pip install requestsCliente completo
# lxs_client.py
import os, uuid, hmac, hashlib
from typing import Optional
import requests
class LxsClient:
def __init__(self, api_key: str, base_url: str = "https://api.lxsyscr.com"):
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
"X-Api-Key": api_key,
"Content-Type": "application/json",
"Accept": "application/json"
})
self.session.timeout = 30
def emitir(self, data: dict, idempotency_key: Optional[str] = None) -> dict:
key = idempotency_key or str(uuid.uuid4())
r = self.session.post(
f"{self.base_url}/api/v1/facturas",
json=data,
headers={"Idempotency-Key": key}
)
r.raise_for_status()
return r.json()
def consultar(self, clave: str) -> dict:
r = self.session.get(f"{self.base_url}/api/v1/facturas/{clave}")
r.raise_for_status()
return r.json()
def descargar_pdf(self, clave: str) -> bytes:
r = self.session.get(f"{self.base_url}/api/v1/facturas/{clave}/pdf")
r.raise_for_status()
return r.content
def descargar_xml(self, clave: str) -> str:
r = self.session.get(f"{self.base_url}/api/v1/facturas/{clave}/xml")
r.raise_for_status()
return r.text
def reenviar_email(self, clave: str) -> dict:
r = self.session.post(f"{self.base_url}/api/v1/facturas/{clave}/email")
r.raise_for_status()
return r.json()
def anular(self, clave: str) -> None:
r = self.session.delete(f"{self.base_url}/api/v1/facturas/{clave}")
r.raise_for_status()
def proximo_consecutivo(self, tipo: str) -> int:
r = self.session.get(f"{self.base_url}/api/v1/consecutivos/proximo", params={"tipo": tipo})
r.raise_for_status()
return r.json()["proximo"]
# Uso:
client = LxsClient(os.environ["LXS_API_KEY"])
factura = client.emitir({
"tipo": "FacturaElectronica",
"cliente": {"idCliente": 42},
"condicionVenta": "01",
"medioPago": "01",
"moneda": "CRC",
"lineas": [{"idProducto": 100, "cantidad": 2}]
})
print(f"Clave: {factura['clave']}")Receptor de webhook (Flask)
Usá request.get_data() para obtener el body en bytes antes de calcular el HMAC. Si llamás a get_json() primero y después serializás de nuevo, la firma no coincide.
# webhook_server.py
import os, hmac, hashlib, json
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = os.environ["LXS_WEBHOOK_SECRET"]
@app.post("/webhooks/lxs")
def webhook():
signature = (request.headers.get("X-Lxs-Signature") or "").replace("sha256=", "")
expected = hmac.new(WEBHOOK_SECRET.encode(), request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
abort(401)
evento = request.get_json()
procesar_evento(evento)
return "", 200
def procesar_evento(evento: dict):
# Dedup por nonce
# Actualizar BD
pass
if __name__ == "__main__":
app.run(port=3000)