Search by

shetabit / captcha

khanzadimahdishetabit

Laravel CAPTCHA Integration Package

Package info

github.com/shetabit/captcha

pkg:composer/shetabit/captcha

Statistics

Installs: 84

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 0

v2.1.0 2026-10-24 19:50 UTC

This package is auto-updated.

Last update: 2026-10-24 19:59:43 UTC


README

Software License Latest Version on Packagist Total Downloads on Packagist Tests Code Style Static Analysis Code Coverage

This is a Laravel Package for captcha Integration. It requires PHP 8.4+ (with the gd extension) and supports Laravel 12 and Laravel 13.

This packages works with multiple drivers, and you can create custom drivers if there are not available in the current drivers list (below list).

List of contents

List of available drivers

  • Simple : a simple image captcha.
  • Recaptcha : Google reCAPTCHA v3, which never asks the user anything and gives every form a score instead.
  • Turnstile : Cloudflare Turnstile, a small widget that most visitors pass without doing anything.
  • Others are under way.

you can create your own custom driver if not exists in the list , read the Create custom drivers section.

Install

Via Composer

$ composer require shetabit/captcha

Configure

The service provider and the Captcha alias are registered by Laravel's package discovery, so there is nothing to add to config/app.php (or to bootstrap/providers.php). The old way still works:

# In your providers array.
'providers' => [
    ...
    Shetabit\Captcha\Provider\CaptchaServiceProvider::class,
],

# In your aliases array.
'aliases' => [
    ...
    'Payment' => Shetabit\Captcha\Facade\Captcha::class,
],

then run php artisan vendor:publish to publish config/captcha.php file in your config directory.

In the config file you can set the default driver to use for all your payments. But you can also change the driver at runtime.

Choose what gateway you would like to use in your application. Then make that as default driver so that you don't have to specify that everywhere. But, you can also use multiple gateways in a project.

// Eg. if you want to use simple. (simple is the driver's name)
'default' => 'simple',

Then see the configs in the drivers array.

'drivers' => [
    'simple' => [
        'middleware' => ['web'], // middleware
        'route' => 'captcha', // route name
        'characters' => 'ABCDEFGHIKJLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789',
        'width'  => 230,
        'height' => 70,
        'foregroundColors' => ['2980b9','2E9FFF','FF1166','000000','22EE99'],
        'backgroundColor' => '#FFF',
        'letterSpacing' => 6,
        'fontFamily' => resource_path('views/vendor/captchaSimpleDriver/assets/fonts/DroidSerif.ttf'),
        'fontSize' => 30,
        'length' => [4, 6],
        'scratches' => [5, 8],
        'sensitive' => false,
        'sessionKey' => 'captcha',
    ],
    ...
]

How to use

you have 2 steps to go

  • add captcha in forms
  • add validation

Add captcha in forms

In your code, use it like the below:

<form>
...

{!! captcha() !!}

...
</form>

if you use simple driver, you can change the styles and UI easily, just have a look on resources/views/vendor/captchaSimpleDriver.blade.php

Validation

in order to validate forms wich use captcha, you can use captcha validation role.

The below example shows every thing you need to know about captcha validation:

...

$request->validate([
    'email' => 'required|email',
    'password' => 'required|string',
    'captcha' => 'required|captcha',
]);

...

Google reCAPTCHA v3

reCAPTCHA v3 doesn't show a challenge. When the form is sent, Google's script gets a token for it, and the captcha validation rule asks Google about that token. Google gives it a score from 0.0 (a bot) to 1.0 (a human). The form passes when the score is at least score and the token was made for the configured action.

Register a site of the Score based (v3) type in the reCAPTCHA admin console, put its keys in your .env file and make recaptcha the default driver:

RECAPTCHA_SITE_KEY=your-site-key
RECAPTCHA_SECRET_KEY=your-secret-key
'default' => 'recaptcha',

'drivers' => [
    'recaptcha' => [
        'siteKey' => env('RECAPTCHA_SITE_KEY', ''),
        'secretKey' => env('RECAPTCHA_SECRET_KEY', ''),
        'action' => 'submit', // what the token is asked for, Google tells it back
        'score' => 0.5, // the lowest score that passes, from 0.0 (a bot) to 1.0 (a human)
        'timeout' => 5, // seconds to wait for Google
        'script' => 'https://www.google.com/recaptcha/api.js',
        'url' => 'https://www.google.com/recaptcha/api/siteverify',
    ],
    ...
]

{!! captcha() !!} adds a hidden captcha input and Google's script to the form, so your forms and the validation rule stay the same. The token is only asked for when the form is sent, because it expires after two minutes.

  • If Google doesn't answer within timeout seconds, the form is refused.
  • Where www.google.com can't be reached, point script and url to www.recaptcha.net instead.
  • If you published config/captcha.php before, add the recaptcha entry to both its drivers and its map arrays.

Cloudflare Turnstile

Turnstile shows a small widget in the form. Most visitors pass it without doing anything, and the widget puts a token in a captcha input. The captcha validation rule then asks Cloudflare about that token.

Add a widget in the Turnstile section of the Cloudflare dashboard, put its keys in your .env file and make turnstile the default driver:

TURNSTILE_SITE_KEY=your-site-key
TURNSTILE_SECRET_KEY=your-secret-key
'default' => 'turnstile',

'drivers' => [
    'turnstile' => [
        'siteKey' => env('TURNSTILE_SITE_KEY', ''),
        'secretKey' => env('TURNSTILE_SECRET_KEY', ''),
        'theme' => 'auto', // auto, light or dark
        'size' => 'normal', // normal, flexible or compact
        'action' => '', // when set, a token made for another action is refused
        'timeout' => 5, // seconds to wait for Cloudflare
        'script' => 'https://challenges.cloudflare.com/turnstile/v0/api.js',
        'url' => 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
    ],
    ...
]

{!! captcha() !!} adds the widget and Cloudflare's script to the form, so your forms and the validation rule stay the same.

  • If Cloudflare doesn't answer within timeout seconds, the form is refused.
  • A token can only be checked once, and it expires after five minutes.
  • For your tests, Cloudflare has dummy keys that always pass or always fail.
  • If you published config/captcha.php before, add the turnstile entry to both its drivers and its map arrays.

Create custom drivers:

First you have to add the name of your driver, in the drivers array and also you can specify any config parameters you want.

'drivers' => [
    'simple' => [...],
    'my_driver' => [
        ... # Your Config Params here.
    ]
]

Now you have to create a Driver Map Class that will be used to pay invoices. In your driver, You just have to extend Shetabit\Captcha\Abstracts\Driver.

Ex. You created a class : App\Packages\CaptchaDriver\MyDriver.

namespace App\Packages\CaptchaDriver;

use Illuminate\Support\ServiceProvider;
use Shetabit\Captcha\Abstracts\Driver;

class MyDriver extends Driver
{
    protected $serviceProvider;

    /**
     * Driver settings.
     *
     * @var object
     */
    protected $settings;

    public function __construct(ServiceProvider $serviceProvider, $settings)
    {
        $this->serviceProvider = $serviceProvider;
        $this->settings = (object) $settings;
    }
    
    /**
        you must write your captcha generation 
        logic in the below method.
    **/
    public function generate()
    {
        ...
    
        // create captcha view and return it
        return View::make('yourCustomDriverView');
    }

    /**
        you must write your captcha verification
        logic in the below method.
    **/
    public function verify($token = null)
    {
        ...
    
        $storedToken = ...

        if (empty($this->settings->sensitive)) {
            $storedToken = mb_strtolower($storedToken);
            $token = mb_strtolower($token);
        }

        return $token == $storedToken;
    }
    
}

Once you create that class you have to specify it in the captcha.php config file map section.

'map' => [
    ...
    'my_driver' => App\Packages\CaptchaDriver\MyDriver::class,
]

Note:- You have to make sure that the key of the map array is identical to the key of the drivers array.

Testing

Every pull request and every push to master is checked by GitHub Actions: the test suite runs on PHP 8.4 and 8.5, against Laravel 12 and 13 and against both the lowest and the highest supported dependencies, the coding style is checked with PHP_CodeSniffer, the sources are analysed with PHPStan (level 7, with larastan) and the code coverage of the test suite is measured and has to stay above 90%.

The suite has two parts: tests/Unit covers the manager, the driver, the provider and the helpers on their own, and tests/Feature runs the flow of this readme end to end — a form is shown, its captcha image is fetched over the route of the driver, and the answer is validated when the form comes back.

You can run the same checks locally. With PHP and Composer installed on your machine:

composer install

composer test           # run the test suite
composer test-coverage  # run the test suite and report code coverage
composer check-style    # check the coding style
composer fix-style      # fix the coding style where possible
composer analyse        # run static analysis
composer ci             # run all of the checks above

If you would rather not install PHP on your machine, the shipped Dockerfile and Makefile run everything inside a container:

make test              # run the test suite
make coverage          # run the test suite and report code coverage
make check-style       # check the coding style
make fix-style         # fix the coding style where possible
make analyse           # run static analysis
make ci                # run all of the checks above
make shell             # open a shell inside the container
make help              # list every available target

Another PHP version can be used with make test PHP_VERSION=8.5, and a single Laravel version with make test-laravel LARAVEL=12.

Change log

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING and CONDUCT for details.

Security

If you discover any security related issues, please email hashemm364@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.