laravel-recaptcha
Drop-in Laravel package for embedding and validating Google reCAPTCHA v2 and v3 in your forms.
Repository Health
Technical Analysis
Laravel reCAPTCHA wraps Google’s reCAPTCHA v2 (checkbox and invisible) and v3 APIs behind a single Laravel-native interface: a service-provider-registered singleton, a ReCaptcha facade, global Blade helper functions, and a custom implicit recaptcha validation rule. Instead of hand-rolling cURL calls to Google’s siteverify endpoint and wiring up script tags manually, a developer adds the rule to a form request and drops a helper call into a Blade view.
The package ships version-specific builder classes (ReCaptchaBuilderV2, ReCaptchaBuilderV3, ReCaptchaBuilderInvisible) that share a common base for API URL construction, cURL/file_get_contents fallback validation, and CIDR-aware IP whitelisting via Symfony’s IpUtils. For v3, it auto-registers a validation route and controller so score-based AJAX verification works without any additional routing code. It has shipped since Laravel 5 and is actively tested via CI across PHP 7.3-8.2 and Laravel 7-11.
What You Get
- A
recaptchasingleton bound in the service container, resolved to the correct version builder (V2, V3, or Invisible) based on config - An implicit
recaptchavalidation rule you can attach directly to a form request field - Global Blade helper functions (
htmlScriptTagJsApi(),htmlFormSnippet(),htmlFormButton()) for embedding reCAPTCHA markup without touching PHP classes - A pre-registered route and controller for v3’s AJAX-based token validation flow
- CIDR-aware IP whitelisting (
skip_ipconfig) to bypass verification for trusted/internal traffic - A publishable
config/recaptcha.phpfile covering API keys, timeout, language, and API domain overrides
Common Use Cases
- Blocking bot submissions on public contact or signup forms by adding the
recaptcharule to a form request - Using the invisible variant on checkout flows so shoppers aren’t interrupted by a checkbox challenge
- Fetching a v3 risk score via the built-in AJAX validation route to silently gate likely-bot signups
- Switching the API domain to
www.recaptcha.netfor deployments in regions where Google’s default domain is blocked
Under The Hood
Architecture
A ReCaptchaServiceProvider binds a recaptcha singleton to one of ReCaptchaBuilderV2, ReCaptchaBuilderV3, or ReCaptchaBuilderInvisible based on the recaptcha.version config value, extends Laravel’s Validator with an implicit recaptcha rule, and registers a web-middleware route pointing at ReCaptchaController for v3’s AJAX validation flow. The version-specific builders extend a shared ReCaptchaBuilder base class that owns API URL construction, the actual validate() call (cURL with a file_get_contents fallback), and CIDR-aware IP-skip logic via Symfony’s IpUtils; each subclass mainly overrides htmlScriptTagJsApi() to emit the markup its reCAPTCHA variant needs. A ReCaptcha facade and a set of global helper functions in helpers.php (registered via Composer’s files autoload) expose the bound singleton to Blade views without requiring class imports. This is a compact, conventional layered structure for a Laravel package — provider, then builder hierarchy, then controller/facade/helpers — and changing validation behavior in the shared base class would ripple through all three version builders since they inherit rather than reimplement it.
Tech Stack
PHP 7.3 or 8.0+ targeting Laravel 7 through 11 (illuminate/routing, illuminate/support), with Symfony’s IpUtils component handling IP/CIDR whitelist matching. Tests run on PHPUnit 9/10 through Orchestra Testbench, which boots a minimal Laravel application to exercise the package’s service provider and facade in context. Packaging is plain Composer with PSR-4 autoloading for the Biscolab\ReCaptcha namespace plus a files autoload entry for the global helper functions. No frontend build tooling is involved — the package emits raw <script> tags as PHP strings, and communicates with Google’s reCAPTCHA siteverify REST endpoint directly over cURL.
Code Quality
Ten PHPUnit test files cover all three reCAPTCHA versions, invalid-configuration handling, custom API domains, and language overrides, run through Orchestra Testbench against a real (if minimal) Laravel app container. A GitHub Actions CI workflow runs this suite across a PHP 7.3-8.2 x Laravel 7-11 matrix (with incompatible combinations excluded), so regressions are caught across the package’s full supported range rather than a single environment. Code favors typed properties and return types, fluent setters returning $this, and consistent PHPDoc blocks, but error handling stays minimal — failed validation calls return false or an array rather than throwing, with a single custom InvalidConfigurationException reserved for setup errors. No static analysis or linter configuration is present beyond a PSR-2 convention noted in CONTRIBUTING.md.
API Design Integration is designed to be nearly boilerplate-free: a form request adds one validation rule string, and a Blade view calls one or two global helper functions — no class imports or manual API wiring required for the common path. The facade and helpers mirror each other closely, and the publishable config file centralizes every tunable (keys, timeout, language, API domain, IP skip list) in one place. This is a well-worn pattern for small Laravel integration packages rather than a novel approach, but it executes it cleanly and consistently across all three reCAPTCHA variants.