Private
Public Access
1
0
Files
MineSeeker/src/Service/RecaptchaService.php

70 lines
2.0 KiB
PHP
Raw Normal View History

<?php declare(strict_types=1);
/*
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Service;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* Class RecaptchaService
*
* @package App\Service
* @author Lang <https://www.splendidbear.org>
* @category Class
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 12.
*/
readonly class RecaptchaService
{
private const string SITEVERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
/**
* Minimum score to accept a request (0.0 = bot, 1.0 = human).
* 0.5 is Google's recommended default threshold.
*/
private const float SCORE_THRESHOLD = 0.5;
public function __construct(
private HttpClientInterface $httpClient,
private LoggerInterface $logger,
#[Autowire(env: 'RECAPTCHA_SECRET_KEY')]
private string $secretKey,
) {}
public function verify(string $token, string $remoteIp = ''): bool
{
if ($token === '') {
return false;
}
try {
$body = ['secret' => $this->secretKey, 'response' => $token];
if ($remoteIp !== '') {
$body['remoteip'] = $remoteIp;
}
$data = $this->httpClient
->request('POST', self::SITEVERIFY_URL, ['body' => $body])
->toArray();
return ($data['success'] ?? false) === true
&& ($data['score'] ?? 0.0) >= self::SCORE_THRESHOLD;
} catch (\Throwable $e) {
$this->logger->error('reCAPTCHA verification failed: ' . $e->getMessage());
return false;
}
}
}