Weave Code
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

Re Captcha Library Laravel Package

dario_swain/re-captcha-library

PHP backend client for Google reCAPTCHA v2. Validate the user’s g-recaptcha-response token against Google using your secret key (optionally passing the client IP) to confirm form submissions and block bots. Composer-installable and lightweight.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer:

composer require dario_swain/re-captcha-library:2.0.*

Minimal Setup

  1. Configure .env:

    RECAPTCHA_SECRET_KEY=your_private_key_here
    RECAPTCHA_SITE_KEY=your_site_key_here
    
  2. Bind the service in AppServiceProvider:

    use DS\Library\ReCaptcha\Client;
    use DS\Library\ReCaptcha\Http\Client\Guzzle\GuzzleClient;
    
    public function register()
    {
        $this->app->singleton(Client::class, function ($app) {
            $guzzleClient = new GuzzleClient();
            return new Client(config('services.recaptcha.key'), $guzzleClient);
        });
    }
    
  3. First use case: Validate a form submission in a controller:

    use DS\Library\ReCaptcha\Client;
    use DS\Library\ReCaptcha\ValidationException;
    
    public function store(Request $request, Client $reCaptcha)
    {
        try {
            $valid = $reCaptcha->validate($request->input('g-recaptcha-response'), $request->ip());
            if (!$valid) {
                return back()->withErrors(['captcha' => 'CAPTCHA verification failed']);
            }
            // Proceed with form submission
        } catch (ValidationException $e) {
            return back()->withErrors(['captcha' => $e->getMessage()]);
        }
    }
    
  4. Frontend: Include the ReCAPTCHA widget in your Blade template:

    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <div class="g-recaptcha" data-sitekey="{{ config('services.recaptcha.site_key') }}"></div>
    

Implementation Patterns

Workflow: Form Validation

  1. Frontend: Render the ReCAPTCHA widget in your form.
  2. Backend: Capture the g-recaptcha-response token in your form request.
  3. Validation: Use the package to validate the token in a controller or Form Request.

Example: Form Request Validation

use Illuminate\Foundation\Http\FormRequest;
use DS\Library\ReCaptcha\Client;
use DS\Library\ReCaptcha\ValidationException;

class ContactFormRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'g-recaptcha-response' => 'required|recaptcha',
        ];
    }

    public function validateRecaptcha()
    {
        $reCaptcha = app(Client::class);
        try {
            $valid = $reCaptcha->validate($this->input('g-recaptcha-response'), $this->ip());
            if (!$valid) {
                $this->addError('g-recaptcha-response', 'CAPTCHA verification failed');
            }
        } catch (ValidationException $e) {
            $this->addError('g-recaptcha-response', $e->getMessage());
        }
    }
}

Workflow: Middleware for Route Protection

Create middleware to validate ReCAPTCHA for specific routes:

php artisan make:middleware ValidateRecaptcha
// app/Http/Middleware/ValidateRecaptcha.php
public function handle($request, Closure $next)
{
    $reCaptcha = app(Client::class);
    try {
        $valid = $reCaptcha->validate($request->input('g-recaptcha-response'), $request->ip());
        if (!$valid) {
            return redirect()->back()->withErrors(['captcha' => 'CAPTCHA verification failed']);
        }
    } catch (ValidationException $e) {
        return redirect()->back()->withErrors(['captcha' => $e->getMessage()]);
    }
    return $next($request);
}

Register the middleware in app/Http/Kernel.php:

protected $routeMiddleware = [
    'recaptcha' => \App\Http\Middleware\ValidateRecaptcha::class,
];

Apply it to routes:

Route::post('/contact', [ContactController::class, 'store'])->middleware('recaptcha');

Workflow: Custom HTTP Client

Extend the package’s ClientInterface for custom HTTP logic (e.g., logging, retries):

use DS\Library\ReCaptcha\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Client as GuzzleClient;

class CustomReCaptchaClient implements ClientInterface
{
    protected $client;

    public function __construct()
    {
        $this->client = new GuzzleClient([
            'timeout' => 5.0,
            'headers' => [
                'User-Agent' => 'MyApp/1.0',
            ],
        ]);
    }

    public function send(RequestInterface $request)
    {
        $response = $this->client->send(
            $request,
            ['http_errors' => false]
        );
        return new CustomResponse($response);
    }
}

Bind the custom client in AppServiceProvider:

$this->app->singleton(Client::class, function ($app) {
    $customClient = new CustomReCaptchaClient();
    return new Client(config('services.recaptcha.key'), $customClient);
});

Gotchas and Tips

Pitfalls

  1. Deprecated PHP Features:

    • The package may use deprecated PHP functions (e.g., error_reporting). Test with PHP 8.x and update if needed.
    • Fix: Use a compatibility layer like php-compat or fork the package.
  2. Guzzle Version Conflicts:

    • The package supports Guzzle 3–6, but Laravel may use Guzzle 7+. Ensure no version conflicts.
    • Fix: Use a custom Guzzle client or alias the package’s Guzzle dependency in composer.json:
      "replace": {
          "guzzlehttp/guzzle": "6.*"
      }
      
  3. IP Address Issues:

    • REMOTE_ADDR may not reflect the user’s actual IP if behind a proxy (e.g., Cloudflare, Nginx).
    • Fix: Use Laravel’s trusted proxies config:
      'trust_proxies' => true,
      
      Then use $request->ip() instead of $_SERVER['REMOTE_ADDR'].
  4. Rate Limiting:

    • Google’s ReCAPTCHA API has rate limits (e.g., 1000 requests/minute for free tier).
    • Fix: Implement caching for repeated submissions from the same IP:
      $cacheKey = "recaptcha:{$ip}:{$response}";
      if (Cache::has($cacheKey)) {
          return Cache::get($cacheKey);
      }
      $valid = $reCaptcha->validate($response, $ip);
      Cache::put($cacheKey, $valid, now()->addMinutes(5));
      
  5. Frontend Token Submission:

    • Ensure the g-recaptcha-response token is included in the form submission.
    • Fix: Add hidden input to your form:
      <input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response">
      
      Use JavaScript to populate it:
      document.getElementById('g-recaptcha-response').value = grecaptcha.getResponse();
      
  6. Error Handling:

    • The package throws ValidationException for failed validations. Ensure your error handling is robust.
    • Tip: Log exceptions for debugging:
      catch (ValidationException $e) {
          \Log::error('ReCAPTCHA validation failed: ' . $e->getMessage());
          return back()->withErrors(['captcha' => 'CAPTCHA verification failed']);
      }
      

Debugging Tips

  1. Enable Guzzle Debugging: Add middleware to log HTTP requests/responses:

    $reCaptchaClient = new Client($privateKey, new GuzzleClient([
        'on_stats' => function (GuzzleHttp\Message\RequestInterface $request, GuzzleHttp\Message\ResponseInterface $response) {
            \Log::debug('ReCAPTCHA Request:', [$request->getUri(), $response->getBody()->getContents()]);
        }
    ]));
    
  2. Test with Google’s Test Keys: Use Google’s test keys (6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI) to simulate valid/invalid responses during development.

  3. Validate the Response Manually: Use Google’s test form to verify your sitekey and secretkey are correct.

Extension Points

  1. Custom Validation Logic: Extend the Client class to add custom validation rules (e.g., score thresholds for v3):
    class ExtendedReCaptchaClient extends Client
    {
        public function validateWithScore($response, $ip, $minScore = 0.5)
        {
            $result = parent::validate($response, $ip);
            if (
    
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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony