Llama a solvethree desde un backend de ASP.NET Core

Por solvethree5 min de lectura

Registra un HttpClient tipado, crea la tarea una sola vez y consulta su estado con un plazo límite finito. Mantén la clave de API en el servidor y protege todas las rutas de la aplicación que llamen al cliente.

El siguiente ejemplo es una clase auxiliar REST para reCAPTCHA Enterprise, no un SDK oficial de C#. Mantiene separadas la creación y la consulta de tareas para que tu aplicación no tenga que mantener abierta una solicitud entrante hasta que termine la resolución.

En esta página

Registra el cliente tipado

Primero, activa el perfil del sitio de destino para tu espacio de trabajo en la consola. Enviar un nombre de host y una acción no creará uno. Consulta la configuración del perfil del sitio si el sitio aún no está configurado.

Guarda la clave del espacio de trabajo en la configuración del servidor como SOLVETHREE_API_KEY. Añade la clase del cliente y, después, descomenta el registro que se muestra bajo Program.cs y colócalo antes de builder.Build().

ASP.NET Core · un cliente HTTP tipado
// 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.

El registro establece la dirección base de la API, la autenticación Bearer y un tiempo de espera de transporte de 25 segundos, y desactiva las redirecciones automáticas. Conserva la barra final de la dirección base: las rutas relativas tasks del cliente deben resolverse bajo /v1/.

La clase auxiliar usa las extensiones JSON de HttpClient y devuelve un JsonObject. Ambos métodos comprueban que la respuesta HTTP indique éxito antes de deserializarla. Inyecta CaptchaClient en un controlador o servicio autenticado; la propia clase auxiliar no autentica ni autoriza a quienes llaman a tu aplicación.

Crea una sola vez y guarda la información de recuperación

  1. 1.

    Elige el sitio, la acción y el proxy

    Pasa el nombre de host de destino como site, no una URL completa. Este ejemplo fija action en login; cámbialo por la acción que espera tu destino. Envía un único proxy y usa el modo de reCAPTCHA predeterminado enterprise-v3. No añadas campos type ni url.

  2. 2.

    Guarda un requestId antes de llamar a CreateAsync

    Usa entre 1–64 letras ASCII, números, guiones bajos o guiones. Guárdalo junto con los datos de entrada exactos de la tarea para poder recuperar la misma tarea lógica si se pierde la respuesta.

  3. 3.

    Llama a CreateAsync y guarda el ID de tarea devuelto

    CreateAsync realiza un único POST con waitMs=0. Pasa el CancellationToken de quien realiza la llamada. Una vez que tengas el ID de tarea, usa GetAsync para consultar esa tarea en lugar de crear otra.

Sujeta el permiso para gastar créditos del espacio de trabajo a las comprobaciones de autorización de tu aplicación. Si estos valores provienen de una solicitud entrante, valida el sitio, la acción y el proxy solicitados frente a los que tenga permitido usar quien realiza la llamada.

Consulta periódicamente con un plazo límite global

GetAsync aplica el escape al ID de tarea conocido y solicita waitMs=15000. El tiempo de espera de 25 segundos de HttpClient limita cada solicitud HTTP; no limita el tiempo total que tu aplicación dedica a las consultas periódicas. Define un plazo límite global independiente y propaga la cancelación en cada llamada.

  • pending o solving: continúa solo mientras lo permitan el plazo límite de consulta y la cancelación de quien realiza la llamada.
  • ready: deja de consultar y lee la solución. Es el único estado con una solución utilizable.
  • failed: deja de consultar e inspecciona errorCode y error.

En una aplicación orientada al navegador, mantén la creación y las consultas de estado posteriores como operaciones separadas y protegidas, en lugar de ejecutar un bucle dentro de una única solicitud entrante hasta que termine la tarea. Conserva el ID de tarea cuando venza un plazo límite local para que una solicitud autorizada posterior pueda consultarla.

Al enviar el token a su destino previsto, usa la identidad userAgent y secChUa devuelta en la solución y el mismo proxy utilizado para la resolución. Una tarea lista significa que se ha generado una solución, no que la solicitud de tu aplicación haya tenido éxito.

Recupera la tarea tras agotar el tiempo de espera sin duplicar el trabajo

CreateAsync agota el tiempo de espera o se cancela antes de que recibas un ID.

Es posible que el servidor ya haya creado la tarea. La cancelación local no cancela el trabajo remoto.

Prueba esto: Recupera la tarea volviendo a enviar los mismos datos de entrada con el requestId guardado. El mismo ID y los mismos datos de entrada devuelven la tarea existente; cambiar los datos de entrada y reutilizar ese ID provoca un conflicto.

GetAsync agota el tiempo de espera o vence el plazo límite de consulta.

Ya tienes un ID de tarea, por lo que la ausencia de una respuesta no requiere una tarea de reemplazo.

Prueba esto: Conserva el ID y consulta esa tarea más adelante dentro de una nueva operación con límite de tiempo.

La llamada HTTP devuelve una respuesta que no indica éxito.

EnsureSuccessStatusCode lanza una excepción antes de que la clase auxiliar lea el contenido de una respuesta correcta. Esto es distinto de recibir una tarea cuyo estado sea failed.

Prueba esto: Gestiona el error HTTP por separado. Corrige los datos de entrada no válidos en lugar de reintentarlos sin cambios.

La tarea pasa a failed.

Lee errorCode y error para conocer el fallo de la tarea, como site-unreachable.

Prueba esto: Deja de consultar esa tarea y soluciona la causa indicada antes de iniciar otra resolución.

Usa la guía de errores de la API cuando necesites distinguir una solicitud de API rechazada de un fallo terminal de resolución.

Ejecuta tu primera tarea.

Empieza con $5 de crédito en tu espacio de trabajo.

Crear un espacio de trabajo
Llama a solvethree desde un backend de ASP.NET Core · solvethree