Choisir ton intégration
Sur WordPress, commence par l’extension et ses connecteurs. Ce guide concerne une application PHP personnalisée. Le core nécessite PHP 7.4+ et un navigateur avec JavaScript ; utilise une version PHP maintenue pour ton déploiement.
Installer le core et le client
composer require willybahuaud/gaitcha
npm --prefix vendor/willybahuaud/gaitcha ci
npm --prefix vendor/willybahuaud/gaitcha run build
mkdir -p public/assets
cp vendor/willybahuaud/gaitcha/dist/gaitcha.min.js public/assets/
Le build du client nécessite Node.js et npm. Si ton installation Composer ne contient pas les sources de build, construis le client depuis la même version du dépôt Gaitcha. Garde le client et le serveur sur une version compatible ; héberge le bundle sur ton site.
Configurer le serveur
Crée gaitcha-config.php hors du répertoire public. Fournis un secret aléatoire d’au moins 32 caractères via ton environnement, et un répertoire inscriptible privé pour l’anti-rejeu.
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Gaitcha\Config;
use Gaitcha\FileTokenStore;
$secret = getenv('GAITCHA_SECRET');
if (!$secret || strlen($secret) < 32) {
throw new RuntimeException('GAITCHA_SECRET is missing or too short.');
}
return new Config([
'secret' => $secret,
'pow' => true,
'anti_replay' => true,
'token_store' => new FileTokenStore(__DIR__ . '/var/tokens.json'),
]);
Crée le répertoire var avant la première requête. Le stockage fichier convient à un trafic modéré. Pour plusieurs instances, implémente TokenStoreInterface sur un stockage partagé dont checkAndAdd() est atomique.
Exposer l’initialisation
Exemple public/captcha-init.php, avec le fichier de configuration au niveau parent. La preuve de travail exige de transmettre le JSON décodé à handleInit().
<?php
use Gaitcha\AbstractEndpoint;
$config = require dirname(__DIR__) . '/gaitcha-config.php';
/** Adaptateur JSON pour le serveur de cette application. */
final class SiteCaptchaEndpoint extends AbstractEndpoint {
/**
* Initialize the challenge through the core API.
* @param array $request Decoded JSON body.
* @return array
*/
public function initialize(array $request): array {
return $this->handleInit($request);
}
/**
* Envoie les données du challenge.
* @param array $data Données générées par Gaitcha.
* @return void
*/
protected function sendJsonResponse(array $data): void {
echo json_encode($data);
}
}
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
header('Allow: POST');
exit;
}
$request = json_decode((string) file_get_contents('php://input'), true);
$endpoint = new SiteCaptchaEndpoint($config);
echo json_encode($endpoint->initialize(is_array($request) ? $request : []));
Ne mets pas cet endpoint en cache. Applique une limite de taille de requête et une limitation de débit adaptées à ton hébergement.
Ajouter le widget
<form
data-gaitcha
data-gaitcha-endpoint="/captcha-init.php"
data-gaitcha-label="Je suis humain"
method="post"
action="/submit.php"
>
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Envoyer</button>
</form>
<script src="/assets/gaitcha.min.js" defer></script>
Le client initialise automatiquement les formulaires data-gaitcha. L’endpoint doit être sur la même origine. Pour un placement précis, crée un conteneur et référence son ID via data-gaitcha-container.
Valider avant de traiter
Dans public/submit.php, utilise la même configuration que pour l’initialisation. Ne déclenche aucune action métier avant l’acceptation.
<?php
use Gaitcha\ValidationOrchestrator;
$config = require dirname(__DIR__) . '/gaitcha-config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit;
}
$result = (new ValidationOrchestrator($config))->validate($_POST);
if (!$result->isAccepted()) {
http_response_code(422);
exit('Verification failed. Please retry.');
}
// Valider les champs métier avant d'enregistrer ou d'envoyer un email.
Le captcha ne remplace ni les règles de validation des champs, ni la protection CSRF lorsque ton application en a besoin, ni la limitation de débit.
Styles et thèmes
Deux réglages indépendants permettent d’accorder le widget à ton formulaire :
- Style :
default(classique) utilise des coins arrondis, une ombre légère et des accents colorés.minimalest monochrome, avec des bordures fines et sans ombre. - Thème :
light(par défaut),darkouauto, qui suit la préférence du système du visiteur.
Les six combinaisons fonctionnent avec la même validation. Tu peux comparer les deux styles dans la démo.
<form data-gaitcha data-gaitcha-endpoint="/gaitcha-init.php" data-gaitcha-style="minimal" data-gaitcha-theme="auto">
<!-- Les champs du formulaire -->
</form>
En JavaScript, passe style: 'minimal' et theme: 'auto' dans les options de Gaitcha.init(form, endpoint, options). Dans WordPress, ces réglages se trouvent dans Réglages → Gaitcha et s’appliquent à tous les connecteurs.
Le widget embarque son CSS et limite ses variables à .gaitcha-widget. Le badge devient compact dans les conteneurs étroits. Commence par ces réglages avant de surcharger les styles : le CSS du widget utilise !important pour résister à celui des constructeurs de formulaires.
Formulaires AJAX
Après un rejet AJAX, appelle instance.reset() ou Gaitcha.reset(form). Cela décoche la case, efface le journal et demande un nouveau jeton. Conserve les champs saisis par le visiteur et explique comment réessayer.
Réglages utiles
| Option | Défaut du core | Rôle |
|---|---|---|
secret | Obligatoire | Signature HMAC, 32 caractères minimum |
ttl | 120 | Validité du jeton en secondes |
score_threshold | 0.5 | Seuil du score comportemental |
pow | false | Challenge avant émission du jeton |
pow_difficulty | 18 | Difficulté, de 8 à 26 bits |
pow_challenge_ttl | 90 | Validité du challenge en secondes |
anti_replay | false | Empêche la réutilisation avec un stockage fourni |
no_js_fallback | reject | Traitement d’un jeton absent |
debug | false | Détails de diagnostic ; à désactiver en production |
Les rejets possibles incluent token_absent, token_invalid, token_expired, token_already_used, score_insufficient et log_malformed. N’affiche pas simplement « tu es un robot » : donne un moyen de réessayer.
Référence : README du core, fonctionnement et confidentialité.
Si l’intégration bloque, commence par le guide de dépannage.
Une question ou un cas particulier ?
Ouvrir une discussion sur GitHub