ssheduardo / redsys-laravel

Package Redsys
MIT License
90 stars 31 forks source link

La url de notificación no me funciona #38

Closed aroldos91 closed 6 months ago

aroldos91 commented 4 years ago

Primero un saludo, y darte las gracias por este gran trabajo que has realizado. Tengo laravel 6 y 7 y en ambos proyectos la url de notificación no responde nada, le tengo puesto un simple método de crear un log para ver la respuesta, el redsys lo tengo asincrónico, el pago y todo lo demás funciona bien pero no notifica, está el tpv en modo real pero estoy realizando pruebas porque quiero subir mi versión de larvel tengo php 7.2 en servidor

aroldos91 commented 4 years ago

Ya está solucionado, el problema es que cuando redsys intenta enviar le da 419,

ssheduardo commented 4 years ago

@aroldos91 puedes ser más explicito sobre la solución por si le pasa a otra persona.

aroldos91 commented 4 years ago

Cuando redsys intenta enviar la solicitud por post laravel intenta validar el _token, que debe estar en todas las solicitudes post, dando como respuesta Token Expirado (ERROR 419), por lo que es necesario configurar un paquete de rutas en el $middlewareGroups (app/http/Kernel) donde especifiques que no utilice dicho token, Eje:

'paymennotification'=>[
 'throttle:60,1',
            \App\Http\Middleware\PaymennotificationApi::class
],

en el paquete middelware implementar la clase PaymennotificationApi

 public function handle($request, Closure $next)
    {
        return $next($request);
    }

en el RouteServiceProvider especificar la ruta

protected function paymennotification()
    {
        Route::prefix('paymennotification')
            ->middleware('paymennotification')
            ->namespace($this->namespace)
            ->group(base_path('routes/paymennotification.php'));
    }

Una vez echo todos los cambios, solo tienes que crear el fichero paymennotification.php en las rutas y especificar que debe hacer

Route::post(/', 'PaymennotificationController@paymennotification')->name('paymennotification');
ssheduardo commented 4 years ago

Muy buen aporte, a ver si lo incluyo en el README. Gracias

aroldos91 commented 4 years ago

Y gracias a ti también,

IonAtomico commented 1 year ago

Buenas, entonces en Laravel la url de notificaciones entrega un 419?

ssheduardo commented 1 year ago

Buenas, entonces en Laravel la url de notificaciones entrega un 419?

Si, y el compañero comento como lo soluciono, implementando un middleware para omitir el tema de la comprobación del token.

IonAtomico commented 1 year ago

Implemente el middleware para la omision del token, pero me sigue sin notificar. Gracias

asanzred commented 1 year ago

Cuando redsys intenta enviar la solicitud por post laravel intenta validar el _token, que debe estar en todas las solicitudes post, dando como respuesta Token Expirado (ERROR 419), por lo que es necesario configurar un paquete de rutas en el $middlewareGroups (app/http/Kernel) donde especifiques que no utilice dicho token, Eje:

'paymennotification'=>[
 'throttle:60,1',
            \App\Http\Middleware\PaymennotificationApi::class
],

en el paquete middelware implementar la clase PaymennotificationApi

 public function handle($request, Closure $next)
    {
        return $next($request);
    }

en el RouteServiceProvider especificar la ruta

protected function paymennotification()
    {
        Route::prefix('paymennotification')
            ->middleware('paymennotification')
            ->namespace($this->namespace)
            ->group(base_path('routes/paymennotification.php'));
    }

Una vez echo todos los cambios, solo tienes que crear el fichero paymennotification.php en las rutas y especificar que debe hacer

Route::post(/', 'PaymennotificationController@paymennotification')->name('paymennotification');

No es necesario añadir toda esta lógica extra. Simplemente puedes añadir una excepción en tu VerifyCsrfTokenMiddleware:

/**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */

    protected $except = [
        'path/for/your/response/notification'
    ];
rapcest commented 3 months ago

Hola, he realizado las pruebas correspondientes con el middleware y el except en el VerifyCsrfTokenMiddleware pero me sigue sin funcionar. no se ejecuta la ruta de notificación. Tengo la version de laravel 11 y estoy trabajando con inertia y vue3. Hay algun cambio o nueva configuracion con respecto a este tema?

ssheduardo commented 3 months ago

Has probado con llamar a dicha url desde otro servidor como simulando la llamada del Banco?

aroldos91 commented 3 months ago

Saludos @rapcest estas modificaciones eran con Laravel 6 o 7, y ya existen otras alternativas, por ejemplo lo que comento @asanzred, lo primero, estas realizando las pruebas en un entorno local o ya esta desplegado en el servidor?

en caso de realizar las pruebas en un servidor local, no te funcionara, por lo que deberás realizar otras modificaciones como publicar tu proyecto con ngrok, y en redys deberás configurarlo para autorizar ese dominio,

si ya esta publicado deberías analizar diferentes puntos:

Si estas utilizando Cloudflare o alguna otra herramienta, deberás excluir esa url del firewall ya que los webhook no deben pasar por el.

Analizar si estas trabajando asincrónica webhook.

para poderte ayudar mejor deberías dar mas detalles de como estas haciendo las pruebas. espero que te sea de ayuda esta información

Hola, he realizado las pruebas correspondientes con el middleware y el except en el VerifyCsrfTokenMiddleware pero me sigue sin funcionar. no se ejecuta la ruta de notificación. Tengo la version de laravel 11 y estoy trabajando con inertia y vue3. Hay algun cambio o nueva configuracion con respecto a este tema?

rapcest commented 3 months ago

Hola, si estoy haciendo las pruebas desde mi servidor web, tengo mi sitio web alojado en hostinger. También he realizado las pruebas enviando parámetros a la ruta y si recibe los parametros. Pero los del banco no. Soy nuevo en este tema, apenas llevo unas semanas documentándome pero he encontrado muy poca información que me ayude con mi problema.

este es el codigo de las rutas en mi archivo web.php.


   Route::controller(RedsysController::class)->prefix('redsys')->group(function(){
      Route::post('/comprobar', 'comprobar');
        Route::get('/pago/{order}&{amount}&{des}&{metodo}/', 'index');
        Route::get('/ok', 'ok');
        Route::get('/ko', 'ko');
    });

asi esta el codigo de mi controlador. para acceder a la plataforma


   public static function index(Request $request, $order,$amount,$des=false, $metodo)
    {
        try{
           $order = str_pad($order,12,0,STR_PAD_LEFT);
            $key = config('redsys.key');
            $merchantcode = config('redsys.merchantcode');
            $terminal = config('redsys.terminal');
            $enviroment = config('redsys.enviroment');
            $urlOk = url(config('redsys.url_ok'));
            $urlKo = url(config('redsys.url_ko'));
            $urlNotification= url(config('redsys.url_notification'));
            $tradeName = config('redsys.tradename');
            $description = $des?$des:config('redsys.description');

            Redsys::setAmount($amount);
            Redsys::setOrder($idProducto);
            Redsys::setMerchantcode($merchantcode);

            Redsys::setCurrency('978');
            Redsys::setTransactiontype('0');
            Redsys::setTerminal($terminal);
            Redsys::setMethod($metodo);
            Redsys::setNotification(config('redsys.url_notification'));
            Redsys::setUrlOk(config('redsys.url_ok'));
            Redsys::setUrlKo(config('redsys.url_ko'));
            Redsys::setVersion('HMAC_SHA256_V1');
            Redsys::setTradeName($tradeName);
            Redsys::setTitular($titular);
            Redsys::setProductDescription($description);
            Redsys::setEnviroment('test');
            $signature = Redsys::generateMerchantSignature($key);
            Redsys::setMerchantSignature($signature);
                $formaPago = null;

                        Redsys::setAttributesSubmit('btn_submit', 'btn_id', 'Enviar', 'display:none');
                        $form = Redsys::createForm();

        }
        catch(Exception $e){
            echo $e->getMessage();
        }
            $form = view('redsys', compact('form', 'amount', 'titular', 'description', 'formaPago'));
        return $form;

Por el momento lo he dejado fuera del middleware Auth porque dentro también me daba problemas.

asi la funcion de comprobar:

public function comprobar(Request $request) { try{

        $key = config('redsys.key');
        $parameters = Redsys::getMerchantParameters($request->input('Ds_MerchantParameters'));
        $DsResponse = $parameters["Ds_Response"];
        $DsResponse += 0;

        if (Redsys::check($key, $request->input()) && $DsResponse <=99) {
            // aqui tengo el proceso de guardar en base de datos la información que no logro recibir por $_POST

        } else {

            return to_route('pedidos.cancelado');

        }
    } catch (SermepaTpvTpvException $e) {
        echo $e->getMessage();
    }
}

En el fronted envío la información por medio de inertia:

   if(form.tipo_pago === 'tarjeta'){

            router.get(
              route('redsys/pago', {
                order: 23232335,
               amount: totalConEnvio.value,
               des: 'sin descripción',
               metodo: 'T'
            }), {
            onSuccess: (e)=>{
            }
            })
    }

las rutas que uso:

http://tienda.thegreatcollector.es/redsys/comprobar http://tienda.thegreatcollector.es/redsys/ok http://tienda.thegreatcollector.es/redsys/ko

No se si sea relevante pero mi aplicación esta alojada en un subdominio y tiene una configuración de redirección: del dominio principal (thegreatcollector.es) se redirecciona al subdominio (tienda.thegreatcollector.es) siempre que se intente acceder al primer dominio.

realice pruebas con un archivo .php alojado en la carpeta public_html de mi servidor pero tampoco es capaz de recibir los parametros del banco pero si recibe parametros enviados por mi desde otra ruta.

aroldos91 commented 3 months ago

Verifica que el tpv de redsys este configurado asíncrono, también puedes indicarle al tpv cuál sería la URL de respuesta, me da la ligera impresión que estás trabajando sincrónico, y no asíncrono