jsampedro77 / sermepa-omnipay

sermepa (redsys) omnipay gateway
21 stars 25 forks source link

Añadir completePurchase() #11

Closed nerburish closed 7 years ago

nerburish commented 7 years ago

Buenas de nuevo, Gracias por añadir el anterior cambio.

No soy muy entendido de omnipay pero he pensado que sería interesante hacer el proceso de verificación más compatible con otros gateways. Para ello sería útil añadir el método completePurchase antes que usar checkCallbackResponse() directamente.

De está forma se podría usar de la forma siguiente cuando se reciban los parámetros get de Redsys:

$response = $gateway->completePurchase()->send(); //Se recuperan los parámetros GET de redsys y se comprueban tal y como hace CallbackResponse

if ($response->isSuccessful()) { //Operación realizada correctamente } else { //Operación fallida echo $response->getMessage() }

Además con getMessage() se devuelve la información descriptiva del error usando el repositorio redsys/messages. Solo se lanzaría excepción en caso de que la firma no fuera correcta.

Saludos

jsampedro77 commented 7 years ago

Hola @nerburish, gracias por este nuevo pull request. No lo he podido probar pero creo que hay un problema de base para el uso de complePurchase tal como lo planteas.

A redsys se le envian los datos de compra, y la respuesta es una redireccion para el navegador cliente. Los datos para verificar la compra vienen de forma asincrona mediante una llamada al callback definido por el servidor, y es en esa llamada en la que se pueden comprobar los datos del pago para comprobar que es correcto.

Por lo tanto no es posible en una sola llamada hacer la redireccion al TPV y comprobar si el pago ha sido correcto.

En otras pasarelas si que se realiza la llamada directa al gateway de pago y este devuelve la respuesta de forma sincrona, para esos casos es para los que se puede usar el metodo que propones.

Hace tiempo que no he tenido que tocar temas de redsys, y supongo que seguira funcionando asi. Si no es así comentamelo y podemos hacer pruebas de esta nueva forma.

nerburish commented 7 years ago

Hola @jsampedro77 , No se si te refieres a lo mismo con el callback, pero con redsys con redirección, una vez completado el pago (o fallado), la pasarela te redirige de nuevo al link especificado en el formulario de envío (returnUrl o cancelUrl)

Pues este link, directamente te pasa como parámetros GET el resultado de la operación.

Supongamos que returnUrl es https://mi-url-de-retorno.com. Pues redsys te redirige a este link:

https://mi-url-de-retorno.com?Ds_SignatureVersion=HMAC_SHA256_V1&Ds_MerchantParameters=eyJEc19EYXRlIjoiMDUlMkYwMSUyRjIwMTqiLCJEc19Ib3VyIjoiMTMlM0ExOCIsIkRzX1NlY3VyZVBheW1lbnQiOiIwIiwiRHNfQW1vdW50IjoiMjkwMCIsIkRzX0L1cnJlbmN5I2oiOTc4IiwiRHNaT3JkZXIiOiIxMDAyMDY1IiwiRHffTWVyY2hhbnRDb2RlIjoiMzI3Njc4NTUzIiwiRHNfVGVybWluYWwiOiIwMDMiLCJEc19SZXNwb25zZSI6Ijk5MTUiLCJEc19UcmFuc2FjdGlvblR5cGUiOiIwIiwiRsNfTWVyY2hhbnREYXRhIjoiIiwiRHNfQXV0aG9yaXNhdGlvbkNvZGUiOiIrKysrKysiLCJEc19Db25zdW1lckxhbmd1YWdlIjoiMSJ9&Ds_Signature=qtVgBCEG64hmn7Edkx8HX5dAYG2nnXpRkpZajbKSj2I=

Entonces, si en nuestro código de nuestra web a la que se ha redirigido ponemos lo siguiente: $response = $gateway->completePurchase()->send();

Esta función lo único que hace es pillar los parámetros GET del propio link y procesarlos tal y como haces en CallbackResponse(). Pues en este hipotético "controller" de confirmación ya tienes toda la información para poder procesar la operación de la misma forma que lo harías con otros gateways de omnipay (isSuccessful(), getMessage() etc.)

jsampedro77 commented 7 years ago

@nerburish De acuerdo. En mi implementacion lo que hago es usar el metodo de checkCallbackResponse en la url en la que el TPV directamente envia los datos del pago. No lo hago en la pagina a la que el tpv redirige al usuario.

En este caso veo que tu pull request si que puede ser util. Lo malo es que no puedo hacer ninguna prueba antes del merge. Lo has podido probar?

A ver si en algún momento tengo algo de tiempo y puedo preparar algo de documentación, pero la verdad es que lo veo difícil.

nerburish commented 7 years ago

Vaya, pues entonces no conocía la existencia del Callback de redsys. Sobre las modificaciones del pull request, lo he probado en el proyecto en el cual voy a implementarlo y en principio bien.

Saludos,

jsampedro77 commented 7 years ago

@nerburish creo que puedes configurar en cada tpv como quieres recibir la notificacion real. Yo desconocia el repo de redsys para los mensajes, cuando pueda lo implemento en CallbackResponse, usando la misma clase que has creado.

Hago merge de tu pull request. gracias!

ebisbe commented 7 years ago

@nerburish Hola, Como tienes configurado redsys? Yo en la respuesta no recibo ningun parametro get ni post. Tu solucion no me esta funcionando.

nerburish commented 7 years ago

Hola @ebisbe, Por lo que respecta a la configuración de omnipay sólo uso estos: [ 'amount' => $amount, 'currency' => '978', 'transactionId' => $transactionId, 'consumerLanguage' => '001', 'returnUrl' => $returnUrl, 'cancelUrl' => $cancelUrl, ]

Imagino que el problema es que si el propio TPV en el link de retorno no te devuelve ningún parámetro Get, pues al llamar completePurchase() no se va a poder extraer la información.

Yo esto lo uso con un TPV del Banco Sabadell, es posible que tengas desactivada esa opción porque creo que es opcional según la configuración TPV que te hayan hecho. Haz una prueba en el navegador y si ves que cancelas y no te pasan nada via get, prueba a llamar al TPV de tu banco para que te lo activen.

Saludos

ebisbe commented 7 years ago

@nerburish Muchas gracias, Una llamada me ha solucionado el problema.

jsampedro77 commented 7 years ago

De todas formas, no os da un poco de miedo exponer esos datos en el querysting? Ya se que va protegido por la clave de encriptacion, pero aun asi...

nerburish commented 7 years ago

@ebisbe, ok, perfecto pues.

@jsampedro77 Es cierto que quedan más expuestos. Al menos si pasaran los datos via POST se evitaría que se quedará en el historial (Puede que tengan la opción). Pero realmente con redirección, usar la respuesta de retorno creo que mantiene más la "lógica" que se espera de una pasarela (y omnipay en concreto)

También es verdad que los datos que se pasan y los que te retornan son bastante inocuos (básicamente el tipo de respuesta, la id de operación y la cantidad).

Me faltaría saber eso si, como se hace para usar el callback() de redsys.

jsampedro77 commented 7 years ago

@nerburish Para usar el callback se tiene que configurar el TPV para indicar que quieres recibir notificaciones post. Ahi le indicas la URL en la que quieres recibirlo.

La logica para esa URL es simplemente un controlador que llama a checkCallbackResponse. Te pongo un ejemplo de su uso con un controlador de symfony

        /**
         * @var Gateway $gateway
         */
        $gateway = $this->get('nazka_sermepa_omnipay.gateway');

        try {
            $gateway->checkCallbackResponse($this->getRequest());
            $data = $gateway->decodeCallbackResponse($this->getRequest());
            $order = $this->get('sales.order.manager')->findByTpvCode($data['Ds_Order']);
            //event to change order status to paid, email order, etc...
            $this->get('event_dispatcher')->dispatch(DomainEvents::ORDER_PAID, new GenericEvent($order));
        } catch (BadSignatureException $e) {

            return new Response('Bad Signature');
        } catch (CallbackException $e) {
            //event to change order status to error
            $e->getCode();
            $this->get('event_dispatcher')->dispatch(
                DomainEvents::ORDER_TPV_ERROR,
                new GenericEvent($order)
            );
        }

        return new Response('ok');
ebisbe commented 7 years ago

@jsampedro77 Pero cuanto tiempo se tarda en descifrar estos datos ?? ?Ds_SignatureVersion=HMAC_SHA256_V1&Ds_MerchantParameters=eyJEc19EYXRlIjoiMjMlMkYwMSUyRjIwMTciLCJEc19Ib3VyIjoiMDklM0ExNSIsIkRzX1NlY3VyZVBheW1lbnQiOiIxIiwiRHNfQW1vdW50IjoiMjIyMSIsIkRzX0N1cnJlbmN5IjoiOTc4IiwiRHNfT3JkZXIiOiIxNDg1MTU5MzA0IiwiRHNfTWVyY2hhbnRDb2RlIjoiMzM2MDIyODAxIiwiRHNfVGVybWluYWwiOiIwMDEiLCJEc19SZXNwb25zZSI6IjAwMDAiLCJEc19UcmFuc2FjdGlvblR5cGUiOiIwIiwiRHNfTWVyY2hhbnREYXRhIjoiIiwiRHNfQXV0aG9yaXNhdGlvbkNvZGUiOiI5MTc0NzEiLCJEc19Db25zdW1lckxhbmd1YWdlIjoiMSIsIkRzX0NhcmRfQ291bnRyeSI6IjcyNCJ9&Ds_Signature=gAa7iwY2vXCTBHSHvLMhtho3P_xobA0d5cf3TXqhalw=

?? Quieres decir que luego con los datos que hay se puede hacer algo?

jsampedro77 commented 7 years ago

@ebisbe No estoy muy puesto en criptografia. El tiempo para romprer un sha256 imagino que sera muy alto, pero con el tiempo cada vez sera mas bajo. Los datos que puedan salir de la transaccion pueden ser irrelevantes, o no. El punto que quiero hacer es que algo es siempre mas seguro si no se expone que si se expone, pero si el propio banco acepta enviarlo por querystring, pues ellos sabran mas que yo...

ebisbe commented 7 years ago

@jsampedro77 Pues por eso mismo lo decia. Al final el banco es el que te lo permite. Por post es mas seguro pero tambien más lioso de controlar el proceso. De momento lo dejaré asi.