SDK serveur PHP
SDK officiel côté serveur PHP — publié sous captchala/captchala-php sur Packagist.
Trois rôles que le SDK gère pour vous :
- Valider — vérifier un pass token
pt_issu du SDK navigateur. - Émettre — générer un server token
sct_à usage unique pour lier le prochain challenge à une action / IP / UID donnée. - Modérer — modération de contenu multi-modale (texte + image) via le même pipeline compatible OpenAI utilisé par le tableau de bord.
Installation
composer require captchala/captchala-phpNécessite PHP ≥ 8.0 avec ext-json. Utilise cURL lorsqu'il est disponible, sinon file_get_contents.
Valider (token pt_)
Passez l'IP de l'utilisateur final en troisième argument (depuis CF-Connecting-IP / X-Forwarded-For, avec repli sur REMOTE_ADDR). Facultatif, mais recommandé — utilisée pour des contrôles de risque supplémentaires.
use Captchala\Client;
$client = new Client('your_app_key', 'your_app_secret');
$result = $client->validate($_POST['captcha_token'], false, captchala_client_ip());
if (!$result->isValid()) {
http_response_code(400);
exit($result->getError()); // e.g. "token_expired"
}
// Verification passed; proceed with the request.
// $result->getCaptchaArgs() has platform / user_ip / referer / pkg / solved_at / risk_score
// Real end-user IP behind a CDN / proxy
function captchala_client_ip(): string {
foreach (['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'] as $h) {
if (!empty($_SERVER[$h])) {
$ip = trim(explode(',', $_SERVER[$h])[0]);
if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
}
}
return '';
}Pas d'IP sous la main ? Utilisez $client->validate($_POST['captcha_token']) — la vérification fonctionne toujours, simplement sans le signal de risque supplémentaire basé sur l'IP.
Si vous avez émis le server_token original avec bind_uid, comparez l'uid renvoyé à l'utilisateur réellement attendu :
if ($result->getUid() !== $expectedUserId) {
http_response_code(400);
exit('user mismatch');
}Émettre un server token
Pour les flux à forte valeur (connexion, inscription, paiement), le schéma recommandé est : le backend génère un token sct_ à usage unique, le transmet au navigateur, qui le passe ensuite comme prop serverToken. Chaque token est à usage unique, lié à une action et facultativement lié à une IP / UID au moment de l'émission.
$issue = $client->issueServerToken(
action: 'login',
bindingIp: $request->ip(),
ttl: 300, // seconds; default 300
maxUses: 5, // SDK retry budget
bindUid: $user->id, // pair with ValidateResult::getUid() on verify
);
if (!$issue->isOk()) {
return ['error' => $issue->getError()]; // rate_limit_exceeded, invalid_action, ...
}
return ['server_token' => $issue->getToken()]; // hand to browserModérer du contenu
Multi-modal — accepte un mélange de texte et d'URL d'images au format compatible OpenAI :
$result = $client->moderationCheck([
['type' => 'text', 'text' => $userComment],
['type' => 'image_url', 'image_url' => ['url' => $uploadedImageUrl]],
], userId: $user->id);
if (!$result->isOk()) {
// request error: invalid_credentials, no_content, transport failure, ...
return ['error' => $result->getError()];
}
if ($result->isFlagged()) {
// upstream model flagged; inspect categories for the why
if ($result->hasCategory('violence', 'csam')) {
// hard block
}
}Raccourci texte brut :
$result = $client->moderationText('user comment here', userId: $user->id);Les catégories sont définies par le modèle (par ex. violence, hate, sexual, self-harm) ; itérez sur getCategories() de manière défensive plutôt que de coder en dur un ensemble fixe.
Classes de résultat
| Classe | Méthodes |
|---|---|
ValidateResult | isValid(), getError(), getUid(), getChallengeId(), getAction(), isOffline(), isClientOnly(), getWarning(), toArray() |
IssueResult | isOk(), getToken(), getExpiresIn(), getIssuedAt(), getError(), getMessage(), toArray() |
ModerationResult | isOk(), isFlagged(), hasCategory(...$names), getCategories(), getContentType(), getRaw(), getError(), getMessage(), toArray() |