70 lines
2.0 KiB
PHP
70 lines
2.0 KiB
PHP
|
|
<?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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|