Installation:
composer require snipify-dev/laravel-captcha
php artisan vendor:publish --provider="SnipifyDev\LaravelCaptcha\CaptchaServiceProvider"
This publishes the config file (config/captcha.php) and migration (if needed).
Environment Configuration:
Add your keys to .env:
RECAPTCHA_SITE_KEY=your_site_key
RECAPTCHA_SECRET_KEY=your_secret_key
RECAPTCHA_VERSION=v3 # or v2
First Use Case: Validate a form with reCAPTCHA v3:
use SnipifyDev\LaravelCaptcha\Rules\Recaptcha;
$request->validate([
'g-recaptcha-response' => [new Recaptcha],
]);
config/captcha.php (adjust thresholds, versions, and error messages).Rules/Recaptcha.php (extend or customize behavior).Rules/LivewireRecaptcha.php (for Livewire-specific use).Form Setup:
<!-- Blade -->
<form method="POST" action="/submit">
@csrf
<div class="g-recaptcha" data-sitekey="{{ config('captcha.site_key') }}"></div>
<button type="submit">Submit</button>
</form>
For v3, omit the <div> and handle validation server-side.
Validation:
$request->validate([
'g-recaptcha-response' => ['required', new \SnipifyDev\LaravelCaptcha\Rules\Recaptcha],
]);
Component Setup:
use SnipifyDev\LaravelCaptcha\Rules\LivewireRecaptcha;
public function rules()
{
return [
'recaptcha_token' => [new LivewireRecaptcha],
];
}
Blade Template:
@livewireScripts
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Use the version() helper or config to switch between v2/v3:
use SnipifyDev\LaravelCaptcha\Facades\Captcha;
Captcha::version('v3')->verify($response);
For async verification (e.g., queue jobs):
use SnipifyDev\LaravelCaptcha\Facades\Captcha;
Captcha::verifyAsync($response)
->onSuccess(fn () => Log::info('Captcha passed'))
->onFailure(fn ($errors) => Log::error($errors))
->dispatch();
Testing Environments:
$this->partialMock(Captcha::class, function ($mock) {
$mock->shouldReceive('verify')->andReturn(true);
});
Livewire Caching:
v2 vs. v3 Thresholds:
0.5). Adjust in config/captcha.php:
'v3' => [
'score_threshold' => 0.9, // Stricter threshold
],
Secret Key Exposure:
RECAPTCHA_SECRET_KEY in client-side code. Use server-side validation only.Failed Verification:
config('captcha.debug') to log raw responses:
'debug' => env('RECAPTCHA_DEBUG', false),
.env:
RECAPTCHA_DEBUG=true
Livewire Errors:
recaptcha_token matches the field name in your Livewire component’s rules().Custom Rules: Extend the base rule for custom logic:
use SnipifyDev\LaravelCaptcha\Rules\Recaptcha as BaseRecaptcha;
class CustomRecaptcha extends BaseRecaptcha {
public function passes($attribute, $value) {
// Custom logic
return parent::passes($attribute, $value);
}
}
Event Listeners: Listen for verification events:
use SnipifyDev\LaravelCaptcha\Events\RecaptchaVerified;
RecaptchaVerified::listen(function ($event) {
// Handle success
});
Middleware: Protect routes with captcha:
use SnipifyDev\LaravelCaptcha\Http\Middleware\VerifyRecaptcha;
Route::middleware([VerifyRecaptcha::class])->group(function () {
// Protected routes
});
Local Development: Use a local reCAPTCHA tester (e.g., this tool) to simulate responses.
Performance: For high-traffic forms, cache verification results (e.g., Redis) to reduce API calls.
Multi-Tenant: Store keys per tenant in a database and dynamically load them:
config(['captcha.site_key' => $tenant->recaptcha_site_key]);
How can I help you explore Laravel packages today?