使用 Java 求解 reCAPTCHA Enterprise
使用 Java 的 HttpClient 请求令牌,并使用 Gson 读取 JSON 响应。此示例调用 REST API,等待任务完成,并返回 reCAPTCHA Enterprise 解决方案。
本页内容
设置站点和环境
使用 Java 21 或更高版本。在控制台中为目标创建有效的站点配置文件,然后在启动 Java 的环境中设置 SOLVETHREE_API_KEY 和 SOLVETHREE_PROXY。
将 accounts.example.com 替换为已配置的主机名,将 login 替换为页面使用的操作。site 字段接受主机名,不含协议或路径。
保存并运行 Solve.java
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.UUID;
public class Solve {
static final HttpClient HTTP = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15)).build();
static final String KEY = System.getenv("SOLVETHREE_API_KEY");
static JsonObject api(String path, JsonObject body, long deadline) throws Exception {
long remaining = deadline - System.nanoTime();
if (remaining <= 0) throw new IllegalStateException("Keep the task ID and resume polling");
var builder = HttpRequest.newBuilder(URI.create("https://api.solvethree.com/v1" + path))
.timeout(Duration.ofNanos(Math.min(remaining, Duration.ofSeconds(30).toNanos())))
.header("Authorization", "Bearer " + KEY)
.header("Content-Type", "application/json");
if (body == null) builder.GET();
else builder.POST(HttpRequest.BodyPublishers.ofString(body.toString()));
var response = HTTP.send(builder.build(), HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300)
throw new IllegalStateException("API HTTP " + response.statusCode());
return JsonParser.parseString(response.body()).getAsJsonObject();
}
public static void main(String[] args) throws Exception {
String proxy = System.getenv("SOLVETHREE_PROXY");
if (KEY == null || proxy == null) throw new IllegalArgumentException("Set the API key and proxy");
var input = new JsonObject();
input.addProperty("site", "accounts.example.com");
input.addProperty("action", "login");
input.addProperty("proxy", proxy);
input.addProperty("requestId", UUID.randomUUID().toString());
// Save input before creation if the task must be recovered after restart.
long deadline = System.nanoTime() + Duration.ofSeconds(180).toNanos();
var task = api("/tasks?waitMs=0", input, deadline);
while (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving")) {
String id = URLEncoder.encode(task.get("id").getAsString(), StandardCharsets.UTF_8);
task = api("/tasks/" + id + "?waitMs=15000", null, deadline);
if (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving"))
Thread.sleep(1000);
}
if (!task.get("status").getAsString().equals("ready"))
throw new IllegalStateException("Task failed: " + task.get("errorCode")
+ ": " + task.get("error"));
var solution = task.getAsJsonObject("solution");
// Submit solution.token with userAgent/secChUa and the original proxy.
System.out.println("Ready task: " + task.get("id").getAsString());
}
}在包含 Solve.java 的目录中下载 Gson JAR,然后编译并运行:
curl --fail --location --output gson-2.15.0.jar \
https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.15.0/gson-2.15.0.jar
javac -cp gson-2.15.0.jar Solve.java
java -cp .:gson-2.15.0.jar Solve这些命令使用 macOS/Linux 的类路径分隔符 :。在 Windows 上,请在当前目录和 Gson JAR 之间使用 ;。
从结果中读取令牌
创建时使用 waitMs=0。循环在任务处于 pending 或 solving 状态时获取同一个任务 ID 对应的任务,并在 ready 或 failed 时停止。每次 GET 最多可等待 15 秒;调用方的总时间预算为 180 秒。
使用 solution.get("token").getAsString() 读取令牌。在目标请求中使用返回的 userAgent 和 secChUa,并通过同一代理发送。程序输出的是任务 ID,而不是令牌。
提交后检查目标响应。就绪的任务表示已生成解决方案,但并不代表应用接受了它。
错误与中断的请求
辅助函数会在收到非成功 HTTP 响应时停止。已终止的失败任务会报告 errorCode 和 error,求解失败会退款。请使用 API 错误参考 确定需要修正的问题。
如果需要在重启后恢复,请保存生成的 requestId 和完全一致的输入。如果创建超时,请使用相同 ID 重发这些输入。如果已有任务 ID,就获取该任务。重启此程序会创建另一个 UUID,可能创建另一个计费任务。
运行您的第一个任务。
使用 $5 工作区额度开始体验。