承接 captchala/captchala-php 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

captchala/captchala-php

Composer 安装命令:

composer require captchala/captchala-php

包简介

Captchala Server SDK for PHP - Validate captcha tokens server-side

README 文档

README

Server-side SDK for validating Captcha tokens.

English | 简体中文

Installation

composer require captchala/captchala-php

Quick Start

<?php

use Captchala\Client;

// Create client
$client = new Client('your_app_key', 'your_app_secret');

// Validate token
$result = $client->validate($token);

if ($result->isValid()) {
    // Verification passed
    if ($result->isOffline()) {
        // Offline verification - may need additional risk control
    }
} else {
    // Verification failed
    echo $result->getError();
}

API Reference

Client::__construct(string $appKey, string $appSecret, int $timeout = 5)

Create a client instance.

  • $appKey - App Key (from dashboard)
  • $appSecret - App Secret (from dashboard)
  • $timeout - Request timeout in seconds (default: 5)

Client::validate(string $token, bool $keepToken = false, ?string $clientIp = null): ValidateResult

Validate a token.

  • $token - The pass_token from frontend SDK
  • $keepToken - If true, token won't be consumed (can be validated again)
  • $clientIp - (optional, recommended) The end-user's IP from your inbound request. Used for additional risk checks. Safe to omit.
$result = $client->validate($token, false, $request->ip());
if ($result->isValid()) {
    // ... let the request through ...
}

ValidateResult Methods

Method Return Type Description
isValid() bool Whether validation passed
isOffline() bool Whether this was offline verification
isClientOnly() bool Whether this is a client-only token
getError() ?string Get error message
getWarning() ?string Get warning message
getChallengeId() ?string Get challenge ID
getAction() ?string Get business action
getUid() ?string User ID bound via bind_uid — verify the pass_token belongs to the expected user
getUserIp() ?string End-user IP recorded at solve time (informational).
getCaptchaArgs() array Solve-context echo (platform, user_ip, referer, pkg, solved_at, risk_score). All informational.
toArray() array Convert to array

Solve-context echo (captcha_args)

getCaptchaArgs() returns what the platform recorded at solve time — use it for logging / your own risk scoring, never as a pass/fail gate:

$args = $result->getCaptchaArgs();
// [
//   'platform'   => 'web',          // web / android / ios / flutter / windows / ...
//   'user_ip'    => '1.2.3.4',      // end-user IP at solve time
//   'referer'    => 'https://...',  // web: solve page URL (null on native)
//   'pkg'        => null,           // native: app package id (null on web)
//   'solved_at'  => 1750000000,     // unix seconds
//   'risk_score' => 12,             // 0-100, higher = riskier
// ]

Verifying bind_uid

If you issued the server_token with bind_uid = 'user_42', compare the result against the expected user:

$result = $client->validate($token);
if ($result->isValid() && $result->getUid() !== $expectedUserId) {
    // pass_token was issued for a different user — reject
}

Client::issueServerToken(string $action, ?string $bindingIp = null, ?int $ttl = null, ?int $maxUses = null, ?string $bindUid = null): IssueResult

Mint a one-time sct_ server token. Hand the returned token to the browser SDK via the serverToken prop — single-use, action-scoped, optionally IP/UID-bound.

  • $action - Business scene (login, register, payment, …)
  • $bindingIp - (optional) End-user IP; backend rejects token if a different IP redeems it
  • $ttl - (optional) Lifetime in seconds; server enforces an upper bound (default 300)
  • $maxUses - (optional) SDK retry budget; verification is still single-pass
  • $bindUid - (optional) User ID; pair with ValidateResult::getUid() on verify
$issue = $client->issueServerToken('login', $request->ip(), 300, 5, $user->id);
if (!$issue->isOk()) {
    return ['error' => $issue->getError()];   // rate_limit_exceeded, ...
}
return ['server_token' => $issue->getToken()];   // hand to browser
IssueResult Method Return Description
isOk() bool Issuance succeeded
getToken() ?string The sct_<hex> server token
getExpiresIn() ?int TTL in seconds
getIssuedAt() ?int Unix timestamp (seconds)
getError() ?string Error code
getMessage() ?string Human-readable error message

Client::moderationCheck(array $input, ?string $userId = null): ModerationResult

Multi-modal content moderation. $input is a list of {type, ...} items in OpenAI-compatible format — text and image_url can be mixed in one call.

$result = $client->moderationCheck([
    ['type' => 'text', 'text' => $userComment],
    ['type' => 'image_url', 'image_url' => ['url' => $uploadedImageUrl]],
], $user->id);

if ($result->isFlagged() && $result->hasCategory('violence', 'csam')) {
    // hard block
}

Client::moderationText(string $text, ?string $userId = null): ModerationResult

Convenience wrapper for plain-text moderation.

$result = $client->moderationText('user comment here', $user->id);
ModerationResult Method Return Description
isOk() bool Request succeeded (regardless of flagged)
isFlagged() bool Upstream model verdict
hasCategory(...$names) bool True if any named category tripped
getCategories() array Map of category → bool; categories vary by upstream model
getContentType() ?string 'text' / 'image' / 'mixed'
getRaw() array Full upstream payload for advanced inspection
getError() ?string Error code
getMessage() ?string Human-readable error message

Token Types

Prefix Source Security Level
pt_ Main API High
offline_ Backup Service Medium
client_ Client-only Low (cannot verify server-side)

Complete Example

<?php

use Captchala\Client;

// Validation in login/register scenarios
function handleLogin(array $data): bool
{
    $client = new Client(
        getenv('CAPTCHALA_APP_KEY'),
        getenv('CAPTCHALA_APP_SECRET')
    );

    $result = $client->validate($data['captcha_token']);

    if (!$result->isValid()) {
        throw new Exception('Captcha verification failed: ' . $result->getError());
    }

    // Additional risk control for offline verification
    if ($result->isOffline()) {
        // Log for monitoring
        error_log('Offline captcha verification: ' . json_encode($result->toArray()));

        // Optional: Restrict sensitive operations for client-only tokens
        if ($result->isClientOnly()) {
            // Add extra verification or limit sensitive operations
        }
    }

    // Continue with login logic...
    return true;
}

Laravel Integration

<?php

namespace App\Http\Middleware;

use Closure;
use Captchala\Client;

class ValidateCaptcha
{
    private Client $captcha;

    public function __construct()
    {
        $this->captcha = new Client(
            config('services.captchala.key'),
            config('services.captchala.secret')
        );
    }

    public function handle($request, Closure $next)
    {
        $token = $request->input('captcha_token');

        if (!$token) {
            return response()->json(['error' => 'missing_captcha_token'], 400);
        }

        $result = $this->captcha->validate($token);

        if (!$result->isValid()) {
            return response()->json([
                'error' => 'captcha_failed',
                'message' => $result->getError(),
            ], 400);
        }

        // Store for later use
        $request->attributes->set('captcha_offline', $result->isOffline());
        $request->attributes->set('captcha_client_only', $result->isClientOnly());

        return $next($request);
    }
}

Testing

# Install dependencies
composer install

# Run tests
composer test

# Integration tests (requires real credentials)
CAPTCHALA_APP_KEY=xxx CAPTCHALA_APP_SECRET=xxx composer test

License

MIT

CMS plugin helpers (Captchala\Cms)

Used by CaptchaLa's CMS plugins (WordPress, Joomla, Drupal, Magento, …) — most integrators don't need these directly.

Action constants

use Captchala\Cms\Action;

$server = $client->issueServerToken(Action::LOGIN, $request->ip());

Widget renderer

use Captchala\Cms\Widget;
use Captchala\Cms\Action;

echo Widget::renderHtml($appKey, $serverToken, Action::LOGIN, [
    'product'      => 'bind',
    'lang'         => 'ja',
    'hidden_input' => true,   // also emits <input name="captchala_token">
]);

Error standardizer

use Captchala\Cms\Errors;

$result = $client->validate($_POST['captchala_token']);
if (!$result->isValid()) {
    show_form_error(Errors::standardize($result->getError()));
}

captchala/captchala-php 适用场景与选型建议

captchala/captchala-php 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 06 月 12 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「security」 「validation」 「captcha」 「bot-protection」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 captchala/captchala-php 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 captchala/captchala-php 我们能提供哪些服务?
定制开发 / 二次开发

基于 captchala/captchala-php 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 13
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 47
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-12