Appeler l’API CAPTCHA depuis Spring Boot

Par solvethree5 min de lecture

Enregistrez un seul bean CaptchaClient côté serveur, créez une seule fois la tâche, puis interrogez son état à l’aide de son ID enregistré. La classe utilitaire ci-dessous utilise des appels Spring RestClient synchrones et renvoie des réponses Gson JsonObject.

Sur cette page

Ajouter les dépendances et enregistrer la classe utilitaire

La classe utilitaire fournie utilise Java 21+, Spring Web 7.0.10 et Gson 2.15.0. Dans un projet Spring Boot existant, conservez la version compatible de Spring gérée par Boot plutôt que de remplacer uniquement celle de spring-web pour correspondre à l’exemple. Ajoutez Gson comme dépendance si votre application ne l’inclut pas déjà.

Spring · un service RestClient côté serveur
// Java 21+, Spring Web 7.0.10 and Gson 2.15.0; use your Boot dependency management.
// Save as CaptchaClient.java in your application's package.
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.http.HttpClient;
import java.time.Duration;
import org.springframework.http.MediaType;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

public final class CaptchaClient {
    private final RestClient api;
    public CaptchaClient(String key) {
        var transport = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10))
            .followRedirects(HttpClient.Redirect.NEVER).build();
        var factory = new JdkClientHttpRequestFactory(transport);
        factory.setReadTimeout(Duration.ofSeconds(25));
        api = RestClient.builder().baseUrl("https://api.solvethree.com/v1")
            .requestFactory(factory).defaultHeader("Authorization", "Bearer " + key).build();
    }
    public JsonObject create(String site, String proxy, String requestId) {
        var input = new JsonObject();
        input.addProperty("site", site);
        input.addProperty("action", "login");
        input.addProperty("proxy", proxy);
        input.addProperty("requestId", requestId); // Save before calling create.
        String body = api.post().uri("/tasks?waitMs=0").contentType(MediaType.APPLICATION_JSON)
            .body(input.toString()).retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
    public JsonObject get(String id) {
        if (!id.matches("[A-Za-z0-9_-]+")) throw new IllegalArgumentException("Invalid task ID");
        String body = api.get().uri("/tasks/{id}?waitMs=15000", id)
            .retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
}
// Construct once with System.getenv("SOLVETHREE_API_KEY") in a server-side @Bean.
// Call create once, save its id, then get(id) until ready/failed or your deadline.
// RestClient throws on HTTP errors; keep the saved requestId and any known task id.

Enregistrez la classe sous le nom CaptchaClient.java dans le package de votre application. Dans une méthode de fabrique @Bean côté serveur, instanciez-la une seule fois à l’aide de la variable d’environnement SOLVETHREE_API_KEY. Vérifiez au démarrage que la clé est configurée. La classe utilitaire l’ajoute dans un en-tête d’autorisation Bearer ; ne l’incluez pas dans le code exécuté dans le navigateur.

Réutilisez ce bean par injection via le constructeur. RestClient peut être réutilisé entre plusieurs threads, mais chaque requête bloque le thread qui l’appelle. N’appelez pas ces méthodes sur une boucle d’événements WebFlux. La documentation du client REST de Spring décrit le client synchrone.

Le transport utilise un délai de connexion de 10 secondes, un délai de lecture de 25 secondes et aucune redirection. Les réponses sont lues sous forme de chaînes et analysées avec Gson, sans être converties en objets de réponse typés.

Définir le site, l’action et le proxy

Avant d’appeler create, configurez un profil actif pour le site cible dans votre espace de travail. L’envoi d’un nom d’hôte et d’une action ne crée pas ce profil. Consultez la configuration du profil de site si le site n’est pas encore configuré.

  • Transmettez le nom d’hôte dans site, et non l’URL complète d’une page. Une requête reCAPTCHA ne comporte aucun champ url ou type.
  • La classe utilitaire fixe action à login. Modifiez cette valeur ou faites-en un paramètre de méthode si la requête prévue utilise une autre action.
  • Transmettez une seule URL de proxy. L’API exige exactement un des deux champs proxy ou proxyCandidates ; cette classe utilitaire implémente l’option à proxy unique.
  • La classe utilitaire omet recaptchaType ; l’API utilise donc sa valeur par défaut enterprise-v3.

Créer une seule fois, puis interroger l’ID de tâche enregistré

  1. 1.

    Enregistrer un ID de requête avant la création

    Choisissez un requestId contenant 1–64 lettres ASCII, chiffres, traits de soulignement ou traits d’union. Enregistrez-le avec les paramètres de la tâche avant d’appeler create. Il vous permet de retrouver la même tâche si la réponse de création est perdue.

  2. 2.

    Appeler create et enregistrer l’id renvoyé

    Appelez la méthode create du bean avec le nom d’hôte, le proxy et l’ID de requête enregistré. Elle envoie un seul POST à /v1/tasks avec waitMs=0. Enregistrez l’id renvoyé ; utilisez cet ID de tâche, et non l’ID de requête, pour les consultations suivantes.

  3. 3.

    Appeler get jusqu’à ce que la tâche atteigne un état terminal

    Transmettez l’ID de tâche enregistré à get. Chaque consultation demande waitMs=15000 et bloque en attendant la réponse. Continuez pour pending ou solving, dans la limite d’une échéance définie au niveau de l’application. Arrêtez pour ready ou failed. Les délais HTTP limitent chaque requête, et non l’ensemble de la boucle d’interrogation.

  4. 4.

    Lire la solution uniquement lorsqu’elle est prête

    Pour reCAPTCHA, soumettez solution.token à la cible prévue, et non l’ID de tâche. Utilisez les valeurs userAgent et secChUa renvoyées avec le même proxy que celui ayant permis la résolution. Ne les remplacez pas par des en-têtes de navigateur sans rapport et ne modifiez pas l’URL cible. Une tâche prête fournit une solution ; elle ne prouve pas que la cible a accepté votre requête ultérieure.

Traiter les erreurs HTTP séparément des échecs de tâche

L’appel de création expire avant que vous ne receviez un ID de tâche.

Le serveur peut avoir créé la tâche même si votre client n’a pas reçu sa réponse.

Essayez ceci : Retrouvez la tâche en répétant la même requête de tâche avec le requestId enregistré. Des paramètres identiques renvoient la tâche existante. Ne générez pas de nouvel ID de requête, sauf si vous souhaitez créer une nouvelle tâche logique.

Un appel à get échoue au niveau HTTP.

RestClient.retrieve() lève une exception pour les réponses HTTP qui n’indiquent pas un succès. Cela ne correspond pas à un état de tâche failed.

Essayez ceci : Traitez l’erreur HTTP avant de tenter de lire un corps de réponse de succès. Conservez l’ID de tâche connu pour retrouver la tâche plutôt que d’en créer une autre. Diagnostiquez les paramètres non valides avant de les renvoyer sans modification.

La réponse de la tâche indique l’état failed.

Lisez ses champs errorCode et error ; site-unreachable est un code d’erreur de tâche possible.

Essayez ceci : Cessez d’interroger cette tâche et corrigez la cause signalée avant d’en lancer une autre. Les résolutions échouées sont remboursées ; ne supposez pas que l’échec signifie que le crédit est insuffisant.

La réutilisation d’un ID de requête provoque un conflit.

Comparez les nouveaux paramètres de tâche à ceux enregistrés pour cet ID de requête.

Essayez ceci : Utilisez les paramètres d’origine pour retrouver la tâche existante. Utilisez un nouvel ID de requête pour des paramètres de tâche volontairement différents.

Pour interpréter les erreurs, consultez les erreurs de l’API CAPTCHA.

Lancez votre première tâche.

Démarrez avec $5 de crédit dans votre espace de travail.

Créer un espace de travail
Appeler l’API CAPTCHA depuis Spring Boot · solvethree