Yii.Rocks reCAPTCHA

YiiRocks/reCAPTCHA

recaptcha provides Google reCAPTCHA v2 and v3 field + server-side validation for your Yii Framework 3 applications.

Configuration

Set your site keys and secret keys via environment variables or directly in config/params.php:

'yiirocks/recaptcha' => [
    'siteKeyV2' => $_ENV['RECAPTCHA_SITE_KEY_V2'] ?? '',
    'secretV2' => $_ENV['RECAPTCHA_SECRET_V2'] ?? '',
    'siteKeyV3' => $_ENV['RECAPTCHA_SITE_KEY_V3'] ?? '',
    'secretV3' => $_ENV['RECAPTCHA_SECRET_V3'] ?? '',
    'verifyUrl' => 'https://www.google.com/recaptcha/api/siteverify',
    'sendRemoteIp' => false,
    'translation.category' => 'yii3-recaptcha',
],

Once configured, the field pulls the site key from the registry automatically — no need to call withSiteKey() in your view code.

reCAPTCHA v2 Field

use Yiisoft\FormModel\FormModel;
use YiiRocks\Recaptcha\RecaptchaV2Field;
use YiiRocks\Recaptcha\RecaptchaV2Theme;
use YiiRocks\Recaptcha\RecaptchaV2Size;
use YiiRocks\Recaptcha\RecaptchaV2Type;

echo RecaptchaV2Field::field($form, 'captcha')
    ->withTheme(RecaptchaV2Theme::Dark)
    ->withSize(RecaptchaV2Size::Compact)
    ->withType(RecaptchaV2Type::Audio)
    ->withId('my-captcha')
    ->withCallback('onSuccess')
    ->render();

reCAPTCHA v2 Options

  • withSiteKey(string) ( from config ) Explicit site key override. Optional — pulled from config by default
  • withId(string) ( 'g-recaptcha-{uniqid}' ) Widget element ID
  • withTheme(RecaptchaV2Theme) ( Light ) Light or Dark
  • withType(RecaptchaV2Type) ( Image ) Image or Audio
  • withSize(RecaptchaV2Size) ( Normal ) Normal, Compact, or Invisible
  • withJsApiUrl(string) ( Google CDN ) Custom JS API URL
  • withCallback(string) ( — ) JavaScript callback function name on successful verification
  • withExpiredCallback(string) ( — ) JavaScript callback function name when the CAPTCHA expires
  • withErrorCallback(string) ( — ) JavaScript callback function name when an error occurs

Inherited from InputField:

  • ->name(string) — override the hidden input name (default: auto-derived from form model as FormName[attribute])
  • ->inputId(?string) — override the hidden input ID (default: auto-generated unique ID)

Container (inherited from BaseField):

  • ->containerTag(string) ( 'div' ) Wrapper tag
  • ->containerClass(string ...) ( 'mb-3' ) Wrapper CSS class(es)
  • ->useContainer(bool) ( true ) Enable/disable wrapper
  • ->containerAttributes(array) — set all wrapper attributes
  • ->addContainerAttributes(array) — merge additional wrapper attributes

reCAPTCHA v3 Field

The token is fetched on form submit (not on page load), preventing unexpected challenge popups. The form is auto-resolved via closest("form") — no formId needed when the hidden input is inside the form.

use Yiisoft\FormModel\FormModel;
use YiiRocks\Recaptcha\RecaptchaV3Field;
use YiiRocks\Recaptcha\RecaptchaV3Badge;

echo RecaptchaV3Field::field($form, 'captcha')
    ->withAction('login')
    ->withFormId('login-form')
    ->withBadge(RecaptchaV3Badge::Hidden)
    ->render();

reCAPTCHA v3 Options

  • withSiteKey(string) ( from config ) Explicit site key override. Optional — pulled from config by default
  • withAction(string) ( '' ) Action name sent to Google (must match the rule's action if set)
  • withFormId(string) ( — ) Explicit form ID. When omitted the form is auto-resolved via closest("form")
  • withBadge(RecaptchaV3Badge) ( BottomRight ) BottomRight, BottomLeft, or Hidden
  • withJsApiUrl(string) ( Google CDN ) Custom JS API URL
  • withTranslator(?TranslatorInterface) ( from registry ) Translator for the hidden badge legal notice
  • withExecuteTimeout(?int) ( 15000 ms ) Fallback form submission timeout (null = disabled)

Inherited from InputField:

  • ->name(string) — override the hidden input name (default: auto-derived from form model as FormName[attribute])
  • ->inputId(?string) — override the hidden input ID (default: auto-generated unique ID)

Container (inherited from BaseField):

  • ->containerTag(string) ( 'div' ) Wrapper tag
  • ->containerClass(string ...) ( 'mb-3' ) Wrapper CSS class(es)
  • ->useContainer(bool) ( true ) Enable/disable wrapper
  • ->containerAttributes(array) — set all wrapper attributes
  • ->addContainerAttributes(array) — merge additional wrapper attributes

Hidden badge: When Badge::Hidden is selected, the legal notice text ("This site is protected by reCAPTCHA…") is displayed automatically and translated when a translator is available (either via withTranslator() or through RecaptchaRegistry).

Validation

Use attributes on your form model properties:

use YiiRocks\Recaptcha\RecaptchaV2Rule;
use YiiRocks\Recaptcha\RecaptchaV3Rule;

final class LoginForm
{
    #[RecaptchaV2Rule]
    public string $captcha = '';

    #[RecaptchaV3Rule(
        threshold: 0.5,
        action: 'login',
    )]
    public string $captcha = '';
}

Important: If you set ->withAction('...') on the v3 field, you must also set action: '...' on the rule with the same value. If neither is set, no action is sent and the check is skipped entirely.

v3 rule parameters

  • threshold ( 0.5 ) Minimum score (0.0 — 1.0)
  • action ( null ) Expected action name (skipped if null)
  • message ( 'The CAPTCHA verification failed.' ) Error message (translatable)
  • scoreTooLowMessage ( 'The CAPTCHA score is too low.' ) Error when score is below threshold
  • actionMismatchMessage ( 'The CAPTCHA action does not match.' ) Error when action doesn't match
  • secret ( null ) Custom secret (uses config default if null)
  • sendRemoteIp ( false ) Whether to include the user's IP in verification

Server-Side Verification

Use RecaptchaClient for manual verification:

use YiiRocks\Recaptcha\RecaptchaClient;

/** @var RecaptchaClient $client */
$result = $client->verify($token);
$result = $client->verifyV3($token);
$result = $client->verifyWithSecret($token, $secret);

$result->success;     // bool
$result->score;       // ?float (v3 only)
$result->action;      // ?string (v3 only)
$result->errorCodes;  // array
$result->hostname;    // ?string
$result->challengeTs; // ?string

$config = $client->getConfig(); // RecaptchaConfig

Support

GitHub issuesCreate an Issue