Chame a API de CAPTCHA a partir do Spring Boot

Por solvethree5 min de leitura

Registre um único bean CaptchaClient no servidor, crie uma tarefa uma única vez e consulte periodicamente o ID salvo. O helper abaixo usa chamadas síncronas do RestClient do Spring e retorna respostas JsonObject do Gson.

Nesta página

Adicione as dependências e registre o helper

O helper fornecido usa Java 21+, Spring Web 7.0.10 e Gson 2.15.0. Em um projeto Spring Boot existente, mantenha a versão compatível do Spring gerenciada pelo Boot em vez de substituir apenas spring-web para corresponder ao exemplo. Adicione Gson como dependência se sua aplicação ainda não o incluir.

Spring · um serviço RestClient no servidor
// 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.

Salve a classe como CaptchaClient.java no pacote da sua aplicação. Em um método de fábrica @Bean no servidor, instancie-a uma única vez usando a variável de ambiente SOLVETHREE_API_KEY. Verifique na inicialização se a chave está configurada. O helper a adiciona como um cabeçalho de autorização Bearer; mantenha-a fora do código do navegador.

Reutilize esse bean por injeção via construtor. O RestClient pode ser reutilizado entre threads, mas cada requisição bloqueia a thread que a chamou. Não invoque esses métodos em um loop de eventos do WebFlux. A documentação de clientes REST do Spring descreve o cliente síncrono.

O transporte usa um tempo limite de conexão de 10 segundos, um tempo limite de leitura de 25 segundos e nenhum redirecionamento. As respostas são lidas como strings e analisadas com Gson, sem mapeamento para objetos de resposta tipados.

Defina o site, a ação e o proxy

Antes de chamar create, configure um perfil ativo para o site de destino no seu workspace. Enviar um nome de host e uma ação não cria esse perfil. Consulte a configuração do perfil de site se o site ainda não estiver configurado.

  • Passe o nome do host como site, não uma URL de página completa. Uma requisição reCAPTCHA não tem os campos url ou type.
  • O helper fixa action como login. Altere esse valor ou transforme-o em um parâmetro do método se a requisição pretendida usar outra ação.
  • Passe uma única URL de proxy. A API exige exatamente um dos campos proxy ou proxyCandidates; este helper implementa a opção de proxy único.
  • O helper omite recaptchaType, então a API usa o padrão enterprise-v3.

Crie uma única vez e consulte periodicamente o ID da tarefa salvo

  1. 1.

    Salve um ID de requisição antes da criação

    Escolha um requestId com 1–64 letras ASCII, números, sublinhados ou hífens. Salve-o com os dados de entrada da tarefa antes de chamar create. Ele permite recuperar a mesma tarefa se a resposta de criação for perdida.

  2. 2.

    Chame create e salve o id retornado

    Chame o método create do bean com o nome do host, o proxy e o ID de requisição salvo. Ele envia um único POST para /v1/tasks com waitMs=0. Salve o id retornado; use esse ID da tarefa, e não o ID de requisição, nas consultas seguintes.

  3. 3.

    Chame get até que a tarefa atinja um status terminal

    Passe o ID da tarefa salvo para get. Cada consulta solicita waitMs=15000 e bloqueia enquanto aguarda a resposta. Continue para pending ou solving, respeitando um prazo definido pela aplicação. Pare para ready ou failed. Os tempos limite de HTTP limitam requisições individuais, não todo o loop de consultas.

  4. 4.

    Leia a solução somente quando estiver pronta

    Para reCAPTCHA, envie solution.token ao destino pretendido, não o ID da tarefa. Use os valores retornados de userAgent e secChUa com o mesmo proxy usado na resolução bem-sucedida. Não os substitua por cabeçalhos de navegador sem relação nem altere a URL de destino. Uma tarefa pronta fornece uma solução; isso não comprova que o destino aceitou sua requisição posterior.

Trate erros HTTP separadamente das falhas de tarefas

A chamada de criação atinge o tempo limite antes de você receber um ID de tarefa.

O servidor pode ter criado a tarefa mesmo que seu cliente não tenha recebido a resposta.

Experimente: Recupere a tarefa repetindo a mesma requisição com o requestId salvo. Dados de entrada correspondentes retornam a tarefa existente. Não gere um novo ID de requisição, a menos que pretenda criar uma nova tarefa lógica.

Uma chamada get falha na camada HTTP.

RestClient.retrieve() lança uma exceção para respostas HTTP sem sucesso. Isso não equivale a uma tarefa com status failed.

Experimente: Trate o erro HTTP antes de tentar ler um payload de sucesso. Mantenha o ID conhecido da tarefa para recuperação em vez de criar outra tarefa. Diagnostique dados de entrada inválidos antes de tentar novamente sem alterá-los.

A resposta da tarefa tem status failed.

Leia errorCode e error; site-unreachable é um dos possíveis códigos de erro da tarefa.

Experimente: Pare de consultar essa tarefa e resolva a causa informada antes de iniciar outra. Resoluções com falha são reembolsadas; não presuma que a falha significa crédito insuficiente.

Reutilizar um ID de requisição gera um conflito.

Compare os novos dados de entrada da tarefa com os que foram salvos para esse ID de requisição.

Experimente: Use os dados de entrada originais para recuperar a tarefa existente. Use um novo ID de requisição para dados de entrada intencionalmente diferentes.

Para interpretar os erros, consulte Erros da API de CAPTCHA.

Execute sua primeira tarefa.

Comece com $5 em créditos no espaço de trabalho.

Criar um espaço de trabalho
Chame a API de CAPTCHA a partir do Spring Boot · solvethree