Una llamada de impresión cabe en una petición HTTP, lo que hace que imprimir pedidos parezca la integración más sencilla de la hoja de ruta. Lo sigue siendo hasta la noche en que un cliente recibe dos tickets por un pedido, o hasta la noche en que cuarenta pedidos nunca llegan a la cocina y nadie se entera hasta cerrar.
Respuesta corta: tres decisiones evitan casi todos los incidentes en producción. Responde al webhook antes de imprimir, da a cada trabajo una clave estable para que un duplicado sea detectable, y decide explícitamente qué pasa cuando la impresora está desconectada. Ninguna es difícil, y las tres se añaden con más facilidad ahora que después del primer incidente.
Los tres modos de fallo
| Síntoma | Causa real | Arreglo |
|---|---|---|
| El mismo ticket sale dos veces | La plataforma reintentó un webhook lento, o se reaplicó un estado | Una clave estable por pedido |
| Pedidos nunca impresos y sin aviso | La impresora estaba desconectada y el fallo se tragó | Una política offline explícita más una alerta |
| El checkout va lento, o expira | La llamada de impresión corre dentro de la petición que confirma el pedido | Responder primero, imprimir después |
Los tres están relacionados. Una llamada de impresión lenta provoca el reintento que provoca el duplicado, así que arreglar el primero elimina la mayor parte del segundo.
1. Responde al webhook antes de imprimir
Shopify, WooCommerce, Stripe y cualquier plataforma seria reintentan cuando tu endpoint va lento o devuelve un error. Si tu handler imprime de forma síncrona y la API de impresión tarda dos segundos, has construido un generador de reintentos.
export default async function handler(req, res) {
const order = req.body;
// Confirmar de inmediato: la plataforma deja de reintentar.
res.status(200).end();
// Y después imprimir, fuera de la petición que la plataforma espera.
await printOrder(order).catch((err) => {
logger.error({ err, orderId: order.id }, 'fallo de impresion');
alertOps(order);
});
}
La regla es que el presupuesto de timeout de la plataforma y la latencia de tu impresora nunca deben compartir un plazo. Es la misma razón por la que los conectores de Shopify y WooCommerce no imprimen dentro de la transacción del webhook.
2. Pon clave a cada trabajo
La idempotencia aquí no es un lujo de sistemas distribuidos. Un pedido puede disparar tu handler más de una vez de forma legítima: un callback de pasarela que llega dos veces, un comerciante que reaplica un estado pagado a mano, un reintento de webhook que corrió contra tu confirmación.
Pon un valor estable en origin, y guarda una marca de impreso en tu lado:
async function printOrder(order) {
const key = `pedido-${order.id}`;
if (await alreadyPrinted(key)) return;
await fetch(`https://www.expedy.fr/api/v2/printers/${PRINTER_UID}/print`, {
method: 'POST',
headers: {
Authorization: `${process.env.API_SID}:${process.env.API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ printer_msg: buildTicket(order), origin: key }),
});
await markPrinted(key);
}
Dos cosas se ganan el sitio aquí. La marca local detiene el duplicado antes de que llegue a la red, y origin hace visible en el historial de impresión un duplicado que se coló, lo que convierte "creo que imprimió dos veces" en una pregunta que puedes responder.
Escribe la marca en la misma transacción que el resto del tratamiento del pedido si puedes. Una marca escrita después de una llamada HTTP con éxito deja una ventana pequeña, y esa ventana es exactamente de donde salen los tickets dobles.
3. Elige la política offline a propósito
Pregúntate qué debe pasar cuando la impresora se queda sin papel, está desenchufada o cuelga de un router que se reinició. Solo hay tres respuestas sensatas, y la mala es no elegir:
- Encolar y entregar más tarde. Correcto para etiquetas de envío y documentos de almacén, donde un ticket impreso veinte minutos tarde sigue sirviendo.
- Reintentar brevemente, luego alertar. Correcto para tickets de cocina, donde un ticket impreso veinte minutos tarde es peor que inútil porque el servicio ya ha seguido.
- Alertar de inmediato. Correcto cuando una persona puede actuar, y única opción que convierte una pérdida silenciosa en un problema conocido.
Elijas la que elijas, implementa la alerta. La diferencia entre una molestia menor y una mala noche no es si la impresora falló, es si alguien lo supo.
Lo que no deberías construir
Los equipos reconstruyen con frecuencia maquinaria que la API ya ofrece. Antes de escribir una cola, un planificador y una escalera de reintentos, mira qué garantías de entrega ya tienes: una API push que retiene el trabajo y lo entrega cuando el equipo se reconecta elimina la necesidad de casi todo ese código. Construye las partes que codifican tus reglas de negocio, como qué impresora recibe qué pedido, y deja la fiabilidad del transporte al transporte.
Probarlo antes de producción
Tres pruebas atrapan la mayor parte de lo que llega a producción:
- Reproduce el mismo webhook dos veces. Debe salir exactamente un ticket.
- Desenchufa la impresora y envía un pedido. Tu política elegida debe ocurrir de forma visible, alerta incluida.
- Pide un producto con un emoji en el nombre. Las impresoras térmicas hablan ESC/POS; translitera antes de enviar, o lo descubrirás en el peor momento. La referencia de maquetación documenta qué acepta el formato.
Haz las tres contra una impresora real, no contra un mock. Los fallos interesantes son físicos.
Crea una cuenta gratuita y cablea las tres pruebas en tu rama de integración antes de que pase por ella el primer pedido de cliente.
Lectura relacionada: imprimir pedidos de Shopify y de WooCommerce muestran dónde están estos enganches en cada plataforma.
FAQ
¿Por qué a veces el mismo pedido se imprime dos veces?
Casi siempre porque la plataforma reintentó un webhook al que tu endpoint respondió lento, o porque un estado pagado se aplicó más de una vez. Confirma el webhook antes de imprimir y pon a cada trabajo una clave estable como el id del pedido.
¿Debo imprimir dentro del handler del webhook?
No. Responde 200 de inmediato y luego imprime fuera de esa petición. Compartir un plazo entre el timeout de la plataforma y la latencia de la impresora es lo que genera los reintentos, y los reintentos generan los duplicados.
¿Qué debe pasar cuando la impresora está desconectada?
Elige una política a propósito: encolar y entregar más tarde, reintentar brevemente y luego alertar, o alertar de inmediato. La cola encaja con etiquetas de envío, la alerta con tickets de cocina. La única respuesta mala es dejarlo sin definir.
¿Necesito construir mi propia cola de impresión?
Normalmente no. Una API push que retiene el trabajo y lo entrega cuando el equipo se reconecta ya lo hace. Escribe el código que codifica tus reglas de negocio, como el enrutado a impresora, no una segunda capa de transporte.
¿Cómo pruebo la fiabilidad de la impresión antes de salir a producción?
Reproduce un webhook dos veces y espera un solo ticket, desenchufa la impresora y comprueba que tu política offline y la alerta se disparan, y pide un producto con un emoji en el nombre. Haz las tres contra una impresora real.