Laravel

Integrando "Invisible reCAPTCHA" de Google de forma fácil en Laravel

Autorangel cruz
Publicado
Lectura1 min de lectura
Integrando "Invisible reCAPTCHA" 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 is 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 CustomGoogleRecaptcha 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);
        // score over 0.5 human
        return $response['score'] >= '0.5' ? true : false;
    }
}

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('rederRecaptchaJs', function ($key, $action = 'contact_form' ) {
    return '
    <script src="https://www.google.com/recaptcha/api.js?render='.$key.'"></script>
    <script>grecaptcha.ready(function() {grecaptcha.execute("'.$key.'", {action: "'.$action.'"}).then(function(token) {if (token) { document.getElementById("recaptcha").value = token }});});</script>';
});
 
Blade::directive('rederRecaptcha', function ($key) {
    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>';
});

Para usarlo en las vistas como una directiva normal de blade, en este caso sería:

@rederRecaptchaJs()
@rederRecaptcha

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.

Espero que les sirva.