dmishh/recaptcher
Recaptcher is a lightweight PHP library for Google reCAPTCHA, based on the official phplib. It supports the “lang” option and is designed to integrate cleanly with Symfony2 RecaptchaBundle. Includes basic roadmap for timeouts and more translations.
Installation:
composer require dmishh/recaptcher
Add to composer.json if not using autoload:
"autoload": {
"psr-4": {
"App\\": "app/",
"Dmishh\\Recaptcher\\": "vendor/dmishh/recaptcher/src/"
}
}
Run composer dump-autoload.
First Use Case:
Register the service in Laravel (e.g., in AppServiceProvider):
public function register()
{
$this->app->singleton('recaptcher', function ($app) {
return new \Dmishh\Recaptcher\Recaptcher(
config('services.recaptcha.site_key'),
config('services.recaptcha.secret_key')
);
});
}
Configuration:
Add to config/services.php:
'recaptcha' => [
'site_key' => env('RECAPTCHA_SITE_KEY'),
'secret_key' => env('RECAPTCHA_SECRET_KEY'),
'lang' => env('RECAPTCHA_LANG', 'en'), // Optional
],
Basic Usage in a Form Controller:
use Dmishh\Recaptcher\Recaptcher;
public function store(Request $request, Recaptcher $recaptcher)
{
$response = $recaptcher->verify($request->input('g-recaptcha-response'));
if (!$response->success()) {
return back()->withErrors(['recaptcha' => 'Invalid verification']);
}
// Proceed with form submission
}
Blade Integration:
{!! Recaptcha::render() !!}
(Ensure Recaptcha facade is registered in config/app.php.)
$response = $recaptcher->verify($request->input('g-recaptcha-response'));
if (!$response->success()) {
return back()->withErrors(['recaptcha' => 'Invalid']);
}
use Dmishh\Recaptcher\Recaptcher;
use Illuminate\Contracts\Validation\Rule;
class RecaptchaRule implements Rule {
protected $recaptcher;
public function __construct(Recaptcher $recaptcher) {
$this->recaptcher = $recaptcher;
}
public function passes($attribute, $value) {
return $this->recaptcher->verify($value)->success();
}
public function message() {
return 'The :attribute is invalid.';
}
}
Use in validation:
$validator = Validator::make($request->all(), [
'g-recaptcha-response' => ['required', new RecaptchaRule($recaptcher)],
]);
Pass language dynamically:
$recaptcher = new \Dmishh\Recaptcher\Recaptcher($siteKey, $secretKey, ['lang' => $request->input('lang', 'en')]);
For API endpoints, verify and return JSON:
public function apiSubmit(Request $request) {
$response = $recaptcher->verify($request->input('token'));
return response()->json(['valid' => $response->success()]);
}
Mock the Recaptcher class in tests:
$mock = Mockery::mock(\Dmishh\Recaptcher\Recaptcher::class);
$mock->shouldReceive('verify')->andReturn(new \Dmishh\Recaptcher\Response(true));
$this->app->instance(\Dmishh\Recaptcher\Recaptcher::class, $mock);
Register a facade for cleaner usage:
// config/app.php
'aliases' => [
'Recaptcha' => \App\Facades\Recaptcha::class,
],
Create facade:
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Recaptcha extends Facade {
protected static function getFacadeAccessor() {
return 'recaptcher';
}
}
Usage:
Recaptcha::verify($response)->success();
Use Laravel's .env for keys:
RECAPTCHA_SITE_KEY=your_site_key
RECAPTCHA_SECRET_KEY=your_secret_key
Handle errors gracefully:
try {
$response = $recaptcher->verify($token);
if (!$response->success()) {
throw new \Exception('Recaptcha failed: ' . $response->getError());
}
} catch (\Exception $e) {
Log::error($e->getMessage());
return back()->withErrors(['recaptcha' => 'Service unavailable']);
}
Cache responses to reduce API calls (e.g., for high-traffic forms):
$cacheKey = 'recaptcha_' . md5($responseToken);
$cached = Cache::get($cacheKey);
if (!$cached) {
$response = $recaptcher->verify($responseToken);
Cache::put($cacheKey, $response, now()->addMinutes(5));
} else {
$response = $cached;
}
spatie/laravel-recaptcha.g-recaptcha-response<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response">
lang parameter must be a valid reCAPTCHA language code (e.g., en, es). Invalid codes may return false negatives.en if not specified.503 errors gracefully.$response = $recaptcher->verify($token);
dd($response->getRawResponse()); // Inspect Google's JSON response
missing-input-secret: Invalid secret key.invalid-domain: Domain not registered in Google reCAPTCHA admin.timeout-or-duplicate: Token used multiple times or expired.localhost as an allowed domain.03AHJ_Vuu09... (from the console).invalid-token.Extend the Response class to add custom logic:
class CustomResponse extends \Dmishh\Recaptcher\Response {
public function isScoreValid() {
if ($this->success()) {
$score = $this->getRawResponse()['score'] ?? 0;
return $score >= 0.5; // Custom threshold
}
return false;
}
}
Override the factory method in Recaptcher
How can I help you explore Laravel packages today?