Laravel

Integrando reCAPTCHA v3 de Google de forma fácil en Laravel

Autorangel cruz
Actualizado
Publicado
Lectura2 min de lectura
Integrando reCAPTCHA v3 de Google de forma fácil en Laravel

Ok, lo primero que hay que hacer es crear las llaves que vamos a usar para ello debemos ir a: https://www.google.com/recaptcha/admin/create recuerden que debemos seleccionar reCAPTCHA v3

Bien, ya tenemos las llaves ahora necesitamos hacer es crear una clase que podemos llamar ReCaptcha y tendrá el siguiente namespace App\Helpers (pueden adaptarlo según sus necesidades).

Esta clase va a contener lo siguiente:

<?php
namespace App\Helpers;
 
use GuzzleHttp\Client;
 
/**
 * ReCaptcha
 */
class ReCaptcha
{
    const CAPTCHA_URL = 'https://www.google.com/recaptcha/api/';
    const TIMEOUT = 20.0;
 
    protected $client;
 
    public function __construct()
    {
        $this->client = new Client([
            'base_uri' => self::CAPTCHA_URL,
            'timeout'  => self::TIMEOUT,
        ]);
    }
 
    /**
     * validateCaptcha
     *
     * @param [type] $recaptcha
     * @return void
     */
    public function validateCaptcha($recaptcha)
    {
        $captchaData = [
            'headers'   =>  [
                'content-type'  => 'application/x-www-form-urlencoded',
                'accept'        => 'application/json',
                'cache-control' => 'no-cache'
            ],
            'form_params' => [
                'secret'    => config('google.recaptcha_secret_key'),
                'response'  => $recaptcha
            ]
        ];
 
        $request    = $this->client->request('POST', 'siteverify', $captchaData);
        $body       = $request->getBody()->getContents();
        $response   = json_decode($body, true);
        // a failed check has no score; score 0.5 or more is treated as human
        return ($response['success'] ?? false) && ($response['score'] ?? 0) >= 0.5;
    }
}

Luego en nuestro AppServiceProvider en el método register colocamos esto

$this->app->bind(ReCaptcha::class, function () {
    return new ReCaptcha;
});

Y en el método boot colocamos lo siguiente:

Blade::directive('renderRecaptchaJs', function ($key) {
    return '
    <script src="https://www.google.com/recaptcha/api.js?render=<?php echo e('.$key.'); ?>"></script>
    <script>grecaptcha.ready(function() {grecaptcha.execute("<?php echo e('.$key.'); ?>", {action: "contact_form"}).then(function(token) {if (token) { document.getElementById("recaptcha").value = token }});});</script>';
});
 
Blade::directive('renderRecaptcha', function () {
    return '<input type="hidden" name="recaptcha" id="recaptcha">
    <div class="recaptcha_text_render"> This site is protected by reCAPTCHA and the Google
        <a class="recaptcha_text_link_render" href="https://policies.google.com/privacy" target="_blank">Privacy Policy</a> and
        <a class="recaptcha_text_link_render" href="https://policies.google.com/terms" target="_blank">Terms of Service</a> apply.
    </div>';
});

Blade le pasa al callback el texto de la expresión, no su valor; por eso la llave se imprime con <?php echo e(...); ?> y se resuelve al renderizar la vista. Para usarlo en las vistas como una directiva normal de blade, en este caso sería:

@renderRecaptchaJs(config('google.recaptcha_site_key'))
@renderRecaptcha

Y ya, para finalizar hacemos lo siguiente en el controlador donde se necesite usar este recaptcha:

    public $recaptcha;
 
    public function __construct(ReCaptcha $recaptcha)
    {
        $this->recaptcha = $recaptcha;
    }
 
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function __invoke(ContactFormRequest $request)
    {
        if ($this->recaptcha->validateCaptcha($request->recaptcha)) {
            //
        }
		//
    }

Aquí la validación que se hace es el score del usuario, donde un valor menor a 0.5 es considerado un bot. Ese 0.5 es el umbral por defecto que sugiere la documentación de reCAPTCHA v3, que también avisa que los tokens caducan a los dos minutos.

Espero que les sirva.

Otras integraciones que acaban pidiéndose en casi todos los proyectos, en Laravel en producción.

¿Tienes un proyecto en mente?

Trabajo con Laravel, WordPress, SEO técnico y servidores MCP. El primer paso es una llamada de descubrimiento, sin costo ni compromiso, donde me cuentas qué necesitas y te digo con honestidad si puedo ayudarte.

Hablemos