Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Google Recaptcha V2 Laravel Package

timehunter/laravel-google-recaptcha-v2

A Laravel package for integrating Google reCAPTCHA v2 into forms and requests. It provides configuration and validation support to help verify reCAPTCHA responses in Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install: composer require timehunter/laravel-google-recaptcha-v2. Because the last release was March 2021, expect a strict illuminate/* constraint — on Laravel 9+ you may need a fork, a replace/path repository, or --ignore-platform-reqs to install at all.
  • Look here first, in this order: the README, config/recaptcha.php (key names and env vars), the package's ServiceProvider (what is bound and auto-discovered), and the validation rule class. The package is small; its entire surface area is the service provider, a config file, the rule, and usually a Blade helper/directive.
  • Publish config: php artisan vendor:publish --tag=recaptcha (or --provider="TimeHunter\LaravelGoogleReCaptchaV2\...ServiceProvider" — check the README for the exact provider/tag). Then add RECAPTCHA_SITE_KEY and RECAPTCHA_SECRET_KEY to .env.
  • Get keys: Google reCAPTCHA admin console, v2 "I'm not a robot" or Invisible. Register localhost as a separate key if you develop locally; otherwise the widget silently fails to render.
  • First use case — a contact form:
    1. Render the widget in Blade (either the package's directive/helper or the raw <div class="g-recaptcha" data-sitekey="{{ config('recaptcha.site_key') }}"> plus https://www.google.com/recaptcha/api.js).
    2. Add 'g-recaptcha-response' => 'required|recaptcha' to your FormRequest rules.
    3. Verify a bad token produces a ValidationException and that a good one passes.
  • Pin the version in composer.json after the first successful install; this package is not actively maintained and a stray composer update is a real risk.

Implementation Patterns

  • FormRequest is the primary pattern. Put the rule on the request class so controllers stay clean:
    public function rules(): array
    {
        return [
            'email'   => 'required|email',
            'message' => 'required',
            'g-recaptcha-response' => 'required|recaptcha',
        ];
    }
    
  • Custom messages / localization: give the rule a readable failure message ('g-recaptcha-response.recaptcha' => __('Please confirm you are not a robot.')) so users don't see the raw rule key. Check whether the package ships translations you can publish; otherwise override in resources/lang.
  • Manual validation (for non-FormRequest flows, API controllers, or Livewire-style handlers): use the rule inside Validator::make(...) and return a JSON error on failure, rather than throwing a full-page redirect.
  • Invisible reCAPTCHA: keep the same server-side rule, but the client flow changes — attach a data-callback and submit the form programmatically after the token resolves. The server never needs to know which variant you used, which makes switching modes a front-end-only change.
  • Multiple forms on one page: don't rely on auto-render (it only binds the first/last widget reliably). Use explicit rendering with grecaptcha.render(element, {...}) per form, keep the returned widget ID, and call grecaptcha.reset(widgetId) after an AJAX submit so the token isn't reused.
  • AJAX/SPA flows: fetch the token client-side, POST it as g-recaptcha-response (Google's expected field name — the rule reads it), validate, and on failure reset the widget client-side. Tokens are single-use, so a failed non-recaptcha validation means the user must re-solve.
  • Testing: never hit Google from CI. Either disable the rule in the test environment, swap the rule's HTTP client via the container, or point the config at Google's test credentials (6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI site / 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe secret), which always pass. In feature tests, assert the redirect/errors rather than the network call.
  • Config hygiene: keep keys in config/recaptcha.php reading from env(), and reference config() everywhere else — env() calls break under config:cache.

Gotchas and Tips

  • Maintenance risk is the headline issue. 13 stars, zero dependents, a 2021 release, and a NOASSERTION license. Verify the actual license text in the repo before commercial use; "no assertion" often means the file is missing or non-standard. If it's unmaintained, you can replicate this package in ~60 lines (one rule, one Blade include, one config) and drop the dependency.
  • Tokens expire (~2 minutes) and are single-use. A user who fills a long form, gets a validation error on another field, and resubmits will likely hit timeout-or-duplicate. Call grecaptcha.reset() client-side on every failed submit.
  • The secret must match the site key's domain. Mismatches surface as invalid-input-response with no hint. Double-check you didn't mix a localhost site key with a production secret.
  • Debugging: log the full siteverify response body (success plus error-codes), not just the boolean. missing-input-secret / invalid-input-secret mean a config or .env/config:cache problem, not a user problem. If the package uses Guzzle directly, you may not get Laravel's Http::fake() for free — check composer.json and bind a mock handler in tests accordingly.
  • Network failures fail closed. Google is unreachable → the rule rejects valid users. Set an explicit Connect/Request timeout on the HTTP client (a slow siteverify call blocks your request thread), and decide whether an outage should hard-fail or be logged and allowed at the call site.
  • config:cache traps: after changing keys in .env, run php artisan config:clear. A cached config with an empty secret is the most common "it worked yesterday" report.
  • remoteip may be wrong behind a load balancer or proxy if the package sends request()->ip() without trusting proxy headers. Verify TrustProxies is configured; a mismatched IP doesn't usually break validation but pollutes Google's risk scoring.
  • CSP: if you ship a Content-Security-Policy, script-src and frame-src must allow https://www.google.com and https://www.gstatic.com, and the widget renders in an iframe — expect it to disappear entirely under a strict policy.
  • Don't re-validate the same token in a middleware and a FormRequest; the second call always returns timeout-or-duplicate. Pick one place to validate.
  • Extension points: the rule class and the config are the seams. Subclass the rule for custom error messages, bind your own HTTP client in the container, and swap the Blade partial for your own markup to control styling — the widget is an iframe, so real styling requires data-size/data-theme attributes, not CSS.
  • Accessibility: the reCAPTCHA iframe handles its own ARIA; don't wrap it in a display:none container or hide it behind tabs that aren't rendered at load time, or you'll break the challenge.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator