Un pedido duplicado en el ERP no es un error inofensivo: genera un albarán de más, descuadra el stock y acaba en una llamada incómoda con el cliente. Casi siempre se debe a lo mismo: la integración da por hecho que cada mensaje llega una sola vez. Así se diseña una integración entre tienda online y ERP que aguante reintentos, caídas y errores sin duplicar nada.
Por qué se duplican los pedidos
- Reintentos automáticos: la tienda o el webhook reenvía el pedido porque el ERP tardó en responder, aunque sí lo había registrado.
- Varios disparadores: el pedido se envía al crearse y otra vez al pagarse, o desde un cron y desde un evento a la vez.
- Procesos en paralelo: dos workers cogen el mismo pedido al mismo tiempo.
- Reenvíos manuales: alguien pulsa "volver a enviar" sin saber si el primer envío llegó.
1. Define qué sistema manda en cada dato
Antes de escribir código, decide quién es la fuente de verdad: normalmente la tienda manda en pedidos y clientes web, y el ERP en stock, precios y estados de envío. Cada dato viaja en una sola dirección. Las integraciones bidireccionales "de todo" son las que más duplicados y conflictos generan.
2. Usa una clave de idempotencia
Cada pedido debe llevar un identificador único y estable, por ejemplo el número de pedido de la tienda. El receptor guarda ese identificador y, si vuelve a llegar, devuelve el resultado anterior en lugar de crear otro pedido. Con una restricción UNIQUE en base de datos, ni dos procesos simultáneos pueden saltársela:
// Tabla de control: integration_orders (external_id UNIQUE, erp_id, status)
$registro = IntegrationOrder::firstOrCreate(
['external_id' => $pedido->numero],
['status' => 'pending']
);
if ($registro->erp_id) {
return $registro->erp_id; // ya enviado: no se duplica
}
$erpId = $erp->crearPedido($pedido);
$registro->update(['erp_id' => $erpId, 'status' => 'sent']);
3. Encola los envíos y reintenta con cabeza
El envío al ERP no debe ocurrir dentro de la petición del cliente. Ponlo en una cola, con reintentos limitados y espera creciente entre intentos. Y separa los errores: un 400 (datos incorrectos) no se arregla reintentando; un 503 o un timeout, sí.
4. Valida el formato antes de enviar
Muchos rechazos vienen de diferencias de formato: una dirección que se envía como objeto cuando el ERP espera campos simples, decimales con coma, códigos de país distintos. Documenta el contrato de datos y valida el pedido antes de mandarlo. Es exactamente lo que resolvimos en el caso de integración de pedidos Magento 2 con una API externa.
5. Registra todo con contexto
Cada envío debe dejar rastro: pedido, payload, respuesta, código de estado y número de intento. Cuando algo falla, la alerta tiene que decir qué pedido y por qué, no solo "error en la integración".
6. Ten un proceso de conciliación
Aunque todo esté bien diseñado, conviene una comprobación diaria: pedidos de la tienda sin ID del ERP, pedidos del ERP sin origen en la tienda y estados que no coinciden. Detectarlo el mismo día es mucho más barato que descubrirlo en el cierre de mes.
Lista de comprobación rápida
- Cada dato tiene un único sistema propietario.
- Cada pedido viaja con una clave de idempotencia y hay restricción única en destino.
- Los envíos van por cola, con reintentos solo para errores temporales.
- El formato se valida antes de enviar.
- Hay logs con contexto y alertas útiles.
- Existe una conciliación periódica.
Si tu tienda y tu ERP no terminan de entenderse, puedo revisar la integración y proponerte un plan por fases. Mira mis servicios de desarrollo e integraciones o cuéntame tu caso.