Llamar a una API externa cuando el pedido pasa a pago aceptado
Un compañero sin experiencia con hooks preguntó cómo avisar a una API externa cuando un pedido pasa a pago aceptado. Gustavo y Rekire le dieron el camino: un módulo enganchado al cambio de estado y una cola para no perder pedidos si la API falla. Lo contamos con un ejemplo de código.
Tienes que avisar a un sistema externo (un ERP, un almacén, una herramienta de marketing) cada vez que un pedido pasa a «Pago aceptado». Un compañero lo preguntó en enero de 2024 y la respuesta del grupo fue clara: un módulo propio enganchado al cambio de estado del pedido y, muy importante, una forma de reintentar lo que falle.
Qué hook usar
Gustavo, de la comunidad, le propuso primero el hook de validación del pedido y enseguida rectificó: para reaccionar a un estado concreto lo adecuado es el hook que salta después de cada cambio de estado, que en el código de PrestaShop se llama actionOrderStatusPostUpdate. La diferencia:
actionValidateOrderse ejecuta una vez, cuando se crea el pedido, esté en el estado que esté.actionOrderStatusPostUpdatese ejecuta en cada cambio de estado, también cuando el módulo de pago crea el pedido ya pagado. Ahí compruebas si el estado nuevo es el que te interesa.
Gustavo también contó que, para un módulo suyo que añade un estado automático a los pedidos que entran, tuvo que usar actionOrderHistoryAddAfter, porque otros hooks se ejecutaban antes de que el módulo de pago fijara su estado.
Un ejemplo
Para crear el esqueleto del módulo, Gustavo recomendó el generador de módulos de PrestaShop. Dentro, algo así:
public function install()
{
return parent::install()
&& $this->registerHook('actionOrderStatusPostUpdate');
}
public function hookActionOrderStatusPostUpdate(array $params)
{
$estado = $params['newOrderStatus'];
if ((int) $estado->id !== (int) Configuration::get('PS_OS_PAYMENT')) {
return;
}
$pedido = new Order((int) $params['id_order']);
try {
$this->enviarPedido($pedido); // tu llamada, con un timeout corto
} catch (Exception $e) {
PrestaShopLogger::addLog(
'Envío a la API fallido: ' . $e->getMessage(),
3, null, 'Order', (int) $pedido->id
);
// apúntalo en una tabla propia para reintentarlo con un cron
}
}PS_OS_PAYMENT es el estado «Pago aceptado» de la tienda. Si usas pagos a distancia, revisa también PS_OS_WS_PAYMENT y los estados propios que cree tu módulo de pago.
Lo que no puede faltar: la cola
Rekire puso el acento donde suele fallar: si el servidor externo está caído o tarda, perderías ese pedido. Tienes que poder saber qué pedidos no se enviaron y volver a mandarlos:
- Guarda cada envío en una tabla propia con el id del pedido, la fecha, la respuesta y si fue bien.
- Da por bueno el envío solo si la API responde que lo ha recibido.
- Un cron recorre los pendientes y los reintenta. Protégelo con un token.
- Pon un timeout corto a la llamada. El compañero lo pedía expresamente: que un fallo de la API no afecte al pedido. Con la llamada dentro de un
tryy un timeout de pocos segundos, el pedido sigue su curso pase lo que pase fuera.
El orden de los módulos
Todos los módulos enganchados al mismo hook se ejecutan, uno detrás de otro. El orden se cambia en Diseño → Posiciones. Normalmente da igual, dijo Gustavo, salvo que dependas del trabajo de otro módulo: si lo que envías es el número de seguimiento, el tuyo tiene que ir después del módulo del transportista.
Antes de ponerlo en producción
Pruébalo en una copia de la tienda con la API en modo de pruebas, provoca un fallo a propósito (una URL que no existe) y comprueba que el pedido se crea igual y que el envío queda pendiente para el reintento.
Si prefieres que te hagamos la integración con tu ERP o tu almacén, en Rekire las desarrollamos dentro de nuestros bonos de horas.
Esto salió en @PrestashopEsp, la mayor comunidad PrestaShop de España en Telegram. Ver la conversación