Error en módulo de Redsys al comprar online

Cada vez que vemos una nueva versión sea cual sea el ámbito del software en seguida los ojos nos hacen chiribitas. Estamos expectantes por ver que buenas nuevas nos trae cada versión, y seguramente sin siquiera ver el log de cambios e intentar adelantarnos a posibles interacciones o cambios funcionales que pudieran impedir el correcto funcionamiento de nuestro sistema, lo instalamos.

Y eso fue exactamente lo que nos ha pasado a muchos de nosotros en cuanto vimos que había una nueva versión de Redsys,>concretamente la 3.0.0, en el que, entre otras cosas, cambiaban el método con el que identificaban cada número de pedido.

El módulo es aparentemente simple y funcional. Pero solo aparentemente.

Para empezar a esbozar los posibles problemas que generaba esta nueva versión, comenzaremos explicando el nuevo sistema. En primer lugar, Redsys en el momento en el que se hace una nueva petición de cobro de un carrito, crea una cookie con nombre $_COOKIE[“P”.$id_cart] cuyo valor, es un valor entre 0 y 9 correspondiente a un número de intento y cuya validez es de 24 horas. Por cada nuevo intento, se suma uno al valor y así hasta que llega a 9, donde ya no suma más. Lo que significa un máximo de 10 intentos por cada carrito. Por lo tanto, el número de pedido que generaríamos para Redsys tiene el siguiente formato:

id_cart intento (contenido en la cookie )
0… 010280 1

Por lo tanto, el número de pedido resultante sería: 000000102801

Este número de pedido es almacenado por Redsys y no se podrá usar nunca más. Esto significa que si por alguna caustica intentáramos usar varias veces el mismo número de pedido, Redsys nos devolverá el siguiente error: Número de pedido duplicado.

Esto es correcto, porque así evitamos que un usuario intente pagar dos veces el mismo pedido, no lo pueda hacer.

Pero los problemas aparecen por querer evitar este hecho, si no por como lo intentan evitar.

Un primer caso de error ocurre si la configuración que tenemos para nuestro Prestashop es de que guarde el carrito, la cookie que guarda el intento de pago, que como ya explicamos antes depende del número de carrito, en todas nuestras visitas como clientes en las que en algún momento hayamos intentado llegar hasta la página de introducir la tarjeta, nos estará contando como un intento y por tanto sumando un 1 al valor almacenado en la cookie. ¿Qué pasa si, en el doceavo intento, después de varios días jugando con el carrito de la compra, elimino uno o dos productos de mi carrito, o modifico la cantidad de alguno de ellos, y decido comprar? Que, al ser siempre el mismo carrito guardado para ese cliente, es posible que ya haya agotado los intentos, y por lo tanto, nos devolverá el error de Nº de pedido duplicado. Porque desde el intento 9 + 1, ya todos serán duplicados. Y perderemos la venta.

El segundo caso y más importante, ocurre cuando el cliente crea un carrito he intenta pagar hoy, pero se retracta en su intento, por lo tanto, deja almacenado el intento de pago 1 guardado en la cookie y ya usado en Redsys. A continuación, días más tarde el cliente intenta pagar de nuevo. ¿Qué ha pasado con la cookie que tenía una caducidad de 24 horas? O ¿Qué pasa si el mismo usuario decidió limpiar sus cookies? Pues que se pierde y el contador de intentos o números de pedidos se reinicia a cero, y por lo tanto en este nuevo intento, coincidirá con el mismo número que ya habíamos hecho días antes, y volveremos a encontrarnos con el error N.º de pedido duplicado. Solo si el usuario tiene la paciencia de seguir intentando hasta rebasar los números de intentos que se habían hecho anteriormente hasta encontrar un número de pedido libre, podrá hacer una compra, pero si no, perderemos la venta.

Estas, por escasas que puedan parecer, no lo son. La mayoría de los usuarios todavía indecisos y desconfiados sobre la tienda, sobre todo si es en la primera compra, meditan mucho pagar o no, llegando a cancelar el pago en la misma pantalla de introducción de datos de tarjeta, intentándolo incluso días más tarde.

Estos son según nuestras propias estadísticas estos casos de segunda oportunidad de compra, muy habituales en el comercio online y más en España, donde el comercio electrónico todavía deambula en paños menores.

La solución es muy simple, es tan fácil como hacer que este aspecto del módulo siguiera funcionando como lo estaba haciendo en las versiones anteriores y es como sigue:

id_cart intento: dos dígitos para minutos (mm) dos dígitos para segundo (ss)
0…010280 25 59

En este caso, el número de pedido resultante sería: 000000102802559

Esta solución también tiene sus pros y contras….Como contra, por ejemplo, cabe una pequeña posibilidad de número de pedido duplicado, si con ese mismo carrito en alguna de las horas siguientes, volvamos a intentar justo en el minuto 25 y el segundo 59 un intento de pago.

Otra contra es que, para cada carrito, está reservando 9999 intentos de pago, que como dicen en IKEA, de nada sirve almacenar aire. Pero, aun así, antes de perder ventas, bien preferible es seguir usando este método.

Para implementar los cambios necesarios para esto solo tendremos que hacer los siguientes cambios en el código:

En el fichero modules/redsys/redsys.php comentamos alrededor de la línea 309 el siguiente código:

//Genera problemas por números duplicados de pedido en Redsys
//cuando:
// – Al expirar la cookie
// – El usuario limpia el historial
// – El usuario hace más de 9 intentos en varios días mientras la cookie sigue activa.
//
$orderId = $params[‘cart’]->id;
if(isset($_COOKIE[“P”.$orderId])) {
$sec_pedido = $_COOKIE[“P”.$orderId];
} else {
$sec_pedido = -1;
}
$logActivo = “si”;
//escribirLog(” – COOKIE: “.$_COOKIE[“P”.$orderId].”($orderId) – secPedido: $sec_pedido”, $logActivo);
if ($sec_pedido < 9) {
setcookie(“P”.$orderId, ++$sec_pedido, time() + 86400); // 24 horas
}
$numpedido = str_pad( $orderId.$sec_pedido, 12, “0”, STR_PAD_LEFT );

Y lo sustituimos por:

//Se cambia el metodo para generar los numeros de pedidos a pasar a redsys
// El num. de pedido -> id_Carrito + el tiempo SS
$numpedido = str_pad($params[‘cart’]->id, 8, ‘0’, STR_PAD_LEFT).date(‘is’);

A continuación en el fichero modules/redsys/validation.php línea 81:

// $pedidoSecuencial = $pedido;
// $pedido = intval(substr($pedidoSecuencial, 0, 11));

Y lo sustituimos por:

//Se cambió el mecanismo de obtención de carrito
//diferente al original basado en intentos almacenados en cookies
//en contra al jactual basado en tiempo $cart_id+date(‘is’)
$pedido = intval(substr($pedido, 0, 8));

Esperamos que todo esto les haya ayudado a entender y solucionar una de las razones por las que es posible que hayan disminuido las ventas desde que actualizaron a esta versión el módulo de Redsys.