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

Yandex Smartcaptcha Php Laravel Package

tigusigalpa/yandex-smartcaptcha-php

PHP client for Yandex SmartCaptcha that handles server-side token validation and helps render the client widget in your forms. A simple, framework-friendly way to block bots and spam without adding friction for real users.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and inspect

composer require tigusigalpa/yandex-smartcaptcha-php

Before writing any code, read, in this order:

  1. README.md (English) — the quick-start block is the canonical wiring.
  2. examples/ — frontend widget markup + a custom validation rule example; this is the fastest path to a working form.
  3. config/ and the Service Provider — confirms which env var names the package actually reads (do not guess these).
  4. src/SmartCaptchaClient.php plus the CaptchaInfo, ValidationResult, SecretKey DTOs — the type hints tell you exactly what you get back.

Configure

Publish the config using the tag printed by php artisan vendor:publish (the release notes don't name it — list tags rather than guessing). Then set two distinct credential groups in .env:

# Server-side token validation (the common case)
YANDEX_SMARTCAPTCHA_SERVER_KEY=ysc1_...

# Management API only (create/read/update/delete captchas, fetch secrets)
YANDEX_SMARTCAPTCHA_OAUTH_TOKEN=...

The client-site key is public and belongs in your Blade template, not .env secret storage — but keep it in config so staging/production widgets differ.

First use case: protect one form

Render the widget, post the token, validate server-side. This is the 20-minute win and covers 90% of real usage.

{{-- resources/views/auth/login.blade.php --}}
<form method="POST" action="/login">
    @csrf
    <div id="captcha-container"></div>
    <script src="https://smartcaptcha.yandexcloud.net/captcha.js" defer></script>
    <script>
        window.addEventListener('load', () => {
            window.smartCaptcha.render('captcha-container', {
                sitekey: @json(config('yandex-smartcaptcha.client_key')),
                hl: 'en',
            });
        });
    </script>
</form>
$result = app(SmartCaptchaClient::class)->validate(
    token: $request->input('smart-token'),
    secret: config('yandex-smartcaptcha.server_key'),
    ip: $request->ip(),
);

if (! $result->isValid()) {
    // $result likely exposes an error/reason — log it, show generic message
}

Note the widget's form field name is smart-token (hyphenated) — it will not appear in $request->validated() unless you account for it.

Implementation Patterns

Wrap validation in a Rule, not a controller

The single highest-leverage pattern: one SmartCaptcha rule object that resolves the client from the container, calls validate(), and returns a human-readable failure. Then every FormRequest in the app gets captcha protection with one line, and you can unit-test the rule with a bound fake.

final class SmartCaptcha implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (! is_string($value) || $value === '') {
            $fail('captcha.required')->translate();
            return;
        }

        $result = app(SmartCaptchaClient::class)->validate(
            token: $value,
            secret: config('yandex-smartcaptcha.server_key'),
            ip: request()->ip(),
        );

        if (! $result->isValid()) {
            $fail('captcha.invalid')->translate();
        }
    }
}

Inject, never new

The release notes show new SmartCaptchaClient($oauthToken) for a bare PHP script. Inside Laravel, bind through the container (the Service Provider should already do this) so the OAuth/IAM token manager, logger, and HTTP client are shared and refresh state isn't duplicated per request.

public function __construct(private SmartCaptchaClient $captcha) {}

Treat the management API as ops, not request-path

CRUD on captchas and secret-key retrieval require IAM/OAuth — a heavier, slower, rate-limited credential. Put that work in an artisan command or deploy hook: create a captcha per environment, rotate secrets, list existing ones to detect drift. Never call it inside a user request. Cache retrieved secrets with a TTL shorter than the 12-hour IAM window so rotation is picked up.

// app/Console/Commands/SyncCaptcha.php
$captchas = $client->list();          // audit what exists
$secret    = $client->getSecretKey($id); // store in your secret manager

Layer defensive middleware for high-risk routes

For login, registration, password reset, and public comment endpoints, apply a middleware in addition to the rule so a missing/broken widget fails closed rather than silently skipping verification.

Test by substituting the client

Bind a stub that returns a ValidationResult fixture. Assert both branches of each FormRequest. Keep a couple of tests hitting a mocked HTTP layer to cover DTO hydration and error mapping — that's where this package will actually surprise you.

Log outcomes, not tokens

Pass a PSR-3 logger into the client via config. Log isValid() plus the failure reason and the route; never log the raw token (it's a bearer-ish artifact) or the server key.

Gotchas and Tips

  • Two credential systems, easily confused. validate() needs the server secret key. The management API needs an OAuth/IAM token from yandex-cloud-client-php. Configuring only one and expecting both to work is the #1 first-day error.
  • Tokens are single-use and short-lived. Validate immediately in the same request as submission. Don't stash the token in the session and retry it, and don't re-validate on a validation-failure redirect — the user needs a fresh widget render. Return the form with a re-mounted widget.
  • Never ship the server key to the browser. Only the client/site key goes in Blade. Grep your compiled views once after the first deploy.
  • Domain registration is required in the Yandex console. The widget silently fails on unregistered hosts, including localhost unless you've added it. If nothing renders, check this before debugging PHP.
  • Pass a trustworthy IP. $request->ip() is only meaningful behind correctly configured TrustProxies. A spoofable X-Forwarded-For weakens the signal; a wrong IP (proxy, load balancer) can cause false negatives.
  • Network calls inside a validation rule. Decide explicitly between fail-open (let the user through on transport error, alert) and fail-closed (block). Set an HTTP timeout — a hanging Yandex endpoint should not hold a PHP-FPM worker. Catch the package's exceptions and convert them; don't let a GuzzleException become a 500 on your login page.
  • Long-running workers (Octane, Horizon). IAM auto-refresh state may live in memory. In queued jobs and Octane requests, re-resolve the client or verify the token's freshness rather than assuming a 12-hour token is still good after a worker has been alive for a day.
  • Initial release = pin it. "tigusigalpa/yandex-smartcaptcha-php": "^1.0" and read the changelog before minor bumps. DTO constructors and error shapes are the most likely thing to shift in a 1.x.
  • Named arguments are load-bearing. The documented examples use token:, secret:, ip:. Keep them — positional order across a validate() signature is exactly what breaks quietly on upgrade.
  • Localization. The widget takes an hl option and the package ships EN/RU docs; match the widget language to your app locale rather than leaving it defaulted.
  • Extension points worth knowing: the Service Provider binding (swap the client for a decorator that adds metrics or a circuit breaker), the PSR-3 logger hook, and the DTOs (map ValidationResult into your own domain object at the boundary so a future package change doesn't leak into controllers).
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console