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

Recaptcha2 Bundle Laravel Package

beelab/recaptcha2-bundle

BeelabRecaptcha2Bundle integrates Google ReCaptcha v2 into Symfony, adding a ready-to-use form type and server-side verification with configurable API keys. Simple to drop into existing forms for spam protection. Released under the LGPL license.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel Integration

  1. Install via Composer (with Symfony dependencies):

    composer require beelab/recaptcha2-bundle symfony/form symfony/validator symfony/twig-bridge
    

    Note: Requires Symfony components due to bundle design.

  2. Create a Laravel Service Provider (app/Providers/RecaptchaServiceProvider.php):

    use Beelab\Recaptcha2Bundle\BeelabRecaptcha2Bundle;
    use Symfony\Component\HttpKernel\KernelInterface;
    
    class RecaptchaServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(KernelInterface::class, function () {
                return new class implements KernelInterface {
                    public function getProjectDir() { return base_path(); }
                    public function getRootDir() { return base_path(); }
                };
            });
    
            $this->app->register(BeelabRecaptcha2Bundle::class);
        }
    }
    
  3. Configure .env:

    RECAPTCHA_SITE_KEY=your_site_key
    RECAPTCHA_SECRET_KEY=your_secret_key
    
  4. Basic Form Validation (Laravel-style):

    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Validator;
    
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'g-recaptcha-response' => [
                'required',
                function ($attribute, $value, $fail) {
                    $response = Http::post('https://www.google.com/recaptcha/api/siteverify', [
                        'secret' => config('services.recaptcha.secret'),
                        'response' => $value,
                    ])->json();
    
                    if (!$response['success']) {
                        $fail('reCAPTCHA verification failed.');
                    }
                },
            ],
        ]);
    
        if ($validator->fails()) {
            return back()->withErrors($validator);
        }
    }
    
  5. Render the Widget (Blade):

    <div class="g-recaptcha" data-sitekey="{{ config('services.recaptcha.site_key') }}"></div>
    @vite(['resources/js/recaptcha.js']) <!-- Load Google API -->
    

Implementation Patterns

1. Form Integration Workflow

Symfony-Style Form (Partial Adaptation)

// app/Providers/AppServiceProvider.php
use Beelab\Recaptcha2Bundle\Form\Type\RecaptchaType;
use Symfony\Component\Form\FormBuilderInterface;

public function boot()
{
    FormBuilderInterface::addType(RecaptchaType::class);
}

Limitation: Requires Symfony Form Component; not native to Laravel.

Laravel Native Alternative

// Custom Rule (app/Rules/Recaptcha.php)
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Http;

class Recaptcha implements Rule
{
    public function passes($attribute, $value)
    {
        $response = Http::post('https://www.google.com/recaptcha/api/siteverify', [
            'secret' => config('services.recaptcha.secret'),
            'response' => $value,
        ])->json();

        return $response['success'] ?? false;
    }

    public function message()
    {
        return 'The :attribute is invalid.';
    }
}

Usage:

$request->validate([
    'recaptcha' => ['required', new Recaptcha],
]);

2. Configuration Management

Symfony YAML → Laravel .env

Symfony Config (config/packages/beelab_recaptcha2.yaml) Laravel .env Equivalent
site_key: %env(RECAPTCHA_SITE_KEY)% RECAPTCHA_SITE_KEY=...
secret_key: %env(RECAPTCHA_SECRET_KEY)% RECAPTCHA_SECRET_KEY=...
verify_ssl: true RECAPTCHA_VERIFY_SSL=true
error_message: 'Invalid reCAPTCHA.' RECAPTCHA_ERROR_MESSAGE=Invalid reCAPTCHA.

Laravel Config (config/recaptcha.php)

return [
    'site_key' => env('RECAPTCHA_SITE_KEY'),
    'secret_key' => env('RECAPTCHA_SECRET_KEY'),
    'verify_ssl' => env('RECAPTCHA_VERIFY_SSL', true),
    'error_message' => env('RECAPTCHA_ERROR_MESSAGE', 'Invalid reCAPTCHA.'),
    'test_mode' => env('RECAPTCHA_TEST_MODE', false),
];

3. Event Handling (Symfony → Laravel)

Symfony Event (Original)

// src/EventListener/RecaptchaListener.php
use Beelab\Recaptcha2Bundle\Event\RecaptchaFailEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class RecaptchaListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [RecaptchaFailEvent::NAME => 'onRecaptchaFail'];
    }

    public function onRecaptchaFail(RecaptchaFailEvent $event)
    {
        // Custom logic
    }
}

Laravel Event (Adapted)

// app/Listeners/RecaptchaFailListener.php
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class RecaptchaFailListener
{
    public function handle($event)
    {
        // $event->data contains failure details
        logger()->warning('reCAPTCHA failed', $event->data);
    }
}

Register in EventServiceProvider:

protected $listen = [
    'recaptcha.failed' => [
        RecaptchaFailListener::class,
    ],
];

4. Testing Patterns

Symfony Test Mode

# config/packages/test/beelab_recaptcha2.yaml
beelab_recaptcha2:
    test_mode: true

Laravel Test Helper

// tests/TestCase.php
protected function assertRecaptchaPasses($responseToken)
{
    config(['recaptcha.test_mode' => true]);
    $this->assertTrue(
        Http::post('https://www.google.com/recaptcha/api/siteverify', [
            'secret' => config('recaptcha.secret_key'),
            'response' => $responseToken,
        ])->json()['success']
    );
}

Gotchas and Tips

Pitfalls

  1. Symfony Dependency Bloat

    • The bundle pulls in symfony/form, symfony/validator, and symfony/twig-bridge, which may conflict with Laravel’s DI container.
    • Fix: Use composer require symfony/* --ignore-platform-req and manually resolve conflicts.
  2. Twig Integration Issues

    • The bundle assumes Twig for rendering the widget. Blade templates require JavaScript-based solutions:
      <script src="https://www.google.com/recaptcha/api.js" async defer></script>
      <div class="g-recaptcha" data-sitekey="{{ config('recaptcha.site_key') }}"></div>
      
    • Tip: Use @vite(['resources/js/recaptcha.js']) to load the API dynamically.
  3. Validation Timing

    • Symfony’s Recaptcha2 constraint validates after form submission. Laravel’s FormRequest validates before.
    • Workaround: Use a custom rule (as shown above) or defer validation to a FormRequest::withValidator().
  4. Secret Key Exposure

    • The bundle logs secret keys in Symfony’s debug mode. Laravel’s config/cache may expose them.
    • Fix: Sanitize logs in AppServiceProvider::boot():
      \Log::setOutput(function ($level, $message) {
          return preg_replace('/RECAPTCHA_SECRET_KEY=[^&]+/', 'RECAPTCHA_SECRET_KEY=[REDACTED]', $message);
      });
      
  5. Test Mode Conflicts

    • Symfony’s test_mode bypasses validation entirely. Laravel’s testing requires manual mocking:
      Http::fake([
          'https://www.google.com/recaptcha/api/siteverify' => Http::response(['success' => true]),
      ]);
      

Debugging Tips

  1. Verify API Responses

    • Log raw responses to debug failures:
      $response = Http::post('...')->throw()->json();
      logger()->debug('reCAPTCHA response', $response);
      
  2. Check IP/Network Restrictions

    • Google may block requests from certain IPs or data centers. Use a proxy if needed:
      Http::withOptions(['proxy' => 'http://proxy.example.com:8080'])->post('...');
      
  3. Validate Site Key

    • Ensure the data-sitekey matches your Google Console settings. Test with:
      curl "https://www.google.com/recaptcha/api/siteverify?secret=YOUR_SECRET&response=TOK
      
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route