从 ASP.NET Core 后端调用 solvethree
注册一个强类型 HttpClient,仅创建一次任务,然后在有限的截止时间内查询其状态。将 API 密钥保留在服务端,并保护所有调用该客户端的应用路由。
下面的示例是用于 reCAPTCHA Enterprise 的 REST 辅助类,并非官方 C# SDK。它将任务创建与查询分开,因此应用无需让一个入站请求一直保持连接,直到求解完成。
本页内容
注册强类型客户端
首先,在控制台中为工作区启用目标站点的配置文件。发送主机名和操作不会创建配置文件。如果尚未配置站点,请参阅站点配置文件设置。
在服务端配置中以 SOLVETHREE_API_KEY 保存工作区密钥。添加客户端类,然后取消 Program.cs 下所示注册代码的注释,并将其放在 builder.Build() 之前。
// CaptchaClient.cs; .NET 8+, System.Net.Http.Json and System.Text.Json.Nodes.
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
public sealed class CaptchaClient(HttpClient http)
{
public async Task<JsonObject> CreateAsync(string site, string proxy, string requestId,
CancellationToken cancellationToken)
{
using var response = await http.PostAsJsonAsync("tasks?waitMs=0",
new { site, action = "login", proxy, requestId }, cancellationToken);
response.EnsureSuccessStatusCode();
return (await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken))!;
}
public async Task<JsonObject> GetAsync(string id, CancellationToken cancellationToken)
{
using var response = await http.GetAsync("tasks/" + Uri.EscapeDataString(id) + "?waitMs=15000",
cancellationToken);
response.EnsureSuccessStatusCode();
return (await response.Content.ReadFromJsonAsync<JsonObject>(cancellationToken))!;
}
}
// Program.cs, before builder.Build(), in an existing authenticated ASP.NET app:
// builder.Services.AddHttpClient<CaptchaClient>(http => {
// http.BaseAddress = new Uri("https://api.solvethree.com/v1/");
// http.Timeout = TimeSpan.FromSeconds(25);
// http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
// "Bearer", builder.Configuration["SOLVETHREE_API_KEY"]
// ?? throw new InvalidOperationException("Missing API key"));
// }).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler {
// AllowAutoRedirect = false
// });
// Inject CaptchaClient into your authenticated controller/service. Pass its
// cancellation token, create once, save id and poll GetAsync with a finite deadline.注册代码设置了 API 基地址、Bearer 身份验证和 25 秒传输超时,并禁用自动重定向。保留基地址末尾的斜杠:客户端的相对 tasks 路径必须解析到 /v1/ 下。
辅助类使用 HttpClient 的 JSON 扩展方法并返回 JsonObject。两个方法都会在反序列化前检查 HTTP 请求是否成功。将 CaptchaClient 注入需要身份验证的控制器或服务;辅助类本身不会对应用的调用方进行身份验证或授权。
仅创建一次并保存恢复信息
- 1.
选择站点、操作和代理
将目标主机名作为 site 传入,而不是完整 URL。此示例将 action 固定为 login;请将其改为目标预期的操作。它发送一个 proxy,并使用默认的 enterprise-v3 reCAPTCHA 模式。不要添加 type 或 url 字段。
- 2.
调用 CreateAsync 前保存 requestId
使用 1–64 个 ASCII 字母、数字、下划线或连字符。将其与确切的任务输入一起保存,以便在响应丢失时恢复同一个逻辑任务。
- 3.
调用 CreateAsync 并保存返回的任务 ID
CreateAsync 发送一次 POST 请求,并设置 waitMs=0。传入调用方的 CancellationToken。获得任务 ID 后,使用 GetAsync 查询该任务,而不是再创建一个任务。
消耗工作区额度的权限必须受应用授权检查的保护。如果这些值来自入站请求,请验证所请求的 site、action 和 proxy 是否在该调用方允许使用的范围内。
设置总体截止时间进行轮询
GetAsync 会对已知任务 ID 进行转义,并请求 waitMs=15000。HttpClient 的 25 秒超时限制的是每次 HTTP 请求,而不是应用轮询所花费的总时间。请单独设置总体截止时间,并将取消信号传递给每次调用。
pending或solving:仅在未达到轮询截止时间且调用方未取消时继续。ready:停止轮询并读取求解结果。这是唯一具有可用求解结果的状态。failed:停止轮询并检查errorCode和error。
对于面向浏览器的应用,应将创建任务和后续状态检查设计为独立且受保护的操作,而不是在一个入站请求中循环等待任务完成。本地截止时间到期时保留任务 ID,以便后续经过授权的请求查询该任务。
向令牌的预期目标提交令牌时,请使用求解结果返回的 userAgent 和 secChUa 身份信息,以及求解时使用的同一代理。任务就绪意味着已生成求解结果,并不代表应用请求已成功。
超时后恢复,避免重复创建任务
- CreateAsync 在收到 ID 前超时或被取消。
服务端可能已创建任务。本地取消不会取消远程任务。
试试这样做: 使用已保存的 requestId 重新提交相同的任务输入来恢复。相同的 ID 和输入会返回现有任务;复用该 ID 但更改输入会发生冲突。
- GetAsync 超时或达到轮询截止时间。
既然已有任务 ID,就不必因未收到响应而创建替代任务。
试试这样做: 保留该 ID,稍后在新的有时限操作中查询该任务。
- HTTP 调用返回非成功响应。
EnsureSuccessStatusCode 会在辅助类读取成功响应体前抛出异常。这与收到状态为 failed 的任务不同。
试试这样做: 单独处理 HTTP 错误。修正无效输入,不要原样重试。
- 任务进入 failed 状态。
读取 errorCode 和 error,了解任务失败的原因,例如 site-unreachable。
试试这样做: 停止轮询该任务,并在开始另一次求解前解决所报告的原因。
需要区分 API 请求被拒绝与求解最终失败时,请参阅 API 错误指南。
来源与 API 参考
运行您的第一个任务。
使用 $5 工作区额度开始体验。