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

Vamos a integrar "Invisible reCAPTCHA" de Google en Laravel en menos de 5 minutos.

reCAPTCHA

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:

1<?php
2namespace App\Helpers;
3 
4use GuzzleHttp\Client;
5 
6/**
7 * ReCaptcha
8 */
9class ReCaptcha
10{
11 const CAPTCHA_URL = 'https://www.google.com/recaptcha/api/';
12 const TIMEOUT = 20.0;
13 
14 protected $client;
15 
16 public function __construct()
17 {
18 $this->client = new Client([
19 'base_uri' => self::CAPTCHA_URL,
20 'timeout' => self::TIMEOUT,
21 ]);
22 }
23 
24 /**
25 * validateCaptcha
26 *
27 * @param [type] $recaptcha
28 * @return void
29 */
30 public function validateCaptcha($recaptcha)
31 {
32 $captchaData = [
33 'headers' => [
34 'content-type' => 'application/x-www-form-urlencoded',
35 'accept' => 'application/json',
36 'cache-control' => 'no-cache'
37 ],
38 'form_params' => [
39 'secret' => config('google.recaptcha_secret_key'),
40 'response' => $recaptcha
41 ]
42 ];
43 
44 $request = $this->client->request('POST', 'siteverify', $captchaData);
45 $body = $request->getBody()->getContents();
46 $response = json_decode($body, true);
47 // score over 0.5 human
48 return $response['score'] >= '0.5' ? true : false;
49 }
50}

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

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

Y en el método boot colocamos lo siguiente:

1Blade::directive('rederRecaptchaJs', function ($key, $action = 'contact_form' ) {
2 return '
3 <script src="https://www.google.com/recaptcha/api.js?render='.$key.'"></script>
4 <script>grecaptcha.ready(function() {grecaptcha.execute("'.$key.'", {action: "'.$action.'"}).then(function(token) {if (token) { document.getElementById("recaptcha").value = token }});});</script>';
5});
6 
7Blade::directive('rederRecaptcha', function ($key) {
8 return '<input type="hidden" name="recaptcha" id="recaptcha">
9 <div class="recaptcha_text_render"> This site is protected by reCAPTCHA and the Google
10 <a class="recaptcha_text_link_render" href="https://policies.google.com/privacy" target="_blank">Privacy Policy</a> and
11 <a class="recaptcha_text_link_render" href="https://policies.google.com/terms" target="_blank">Terms of Service</a> apply.
12 </div>';
13});

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

1@rederRecaptchaJs()
2@rederRecaptcha

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

1public $recaptcha;
2 
3public function __construct(ReCaptcha $recaptcha)
4{
5 $this->recaptcha = $recaptcha;
6}
7 
8/**
9 * Handle the incoming request.
10 *
11 * @param \Illuminate\Http\Request $request
12 * @return \Illuminate\Http\Response
13 */
14public function __invoke(ContactFormRequest $request)
15{
16 if ($this->recaptcha->validateCaptcha($request->recaptcha)) {
17 //
18 }
19 //
20}

Acá 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.

Angel Cruz's avatar
Autor
Angel Cruz