Resuelve reCAPTCHA Enterprise con Ruby

Por solvethree4 min de lectura

Usa Net::HTTP de Ruby para crear una tarea de reCAPTCHA Enterprise y consultar su estado hasta que esté lista o falle. El siguiente ejemplo llama directamente a la API REST de solvethree; no requiere un SDK de Ruby.

En esta página

Configura el sitio y el entorno

  1. 1.

    Activa el perfil del sitio

    Configura el nombre de host de destino en la consola de solvethree y asegúrate de que su perfil esté activo en tu espacio de trabajo. Enviar un nombre de host y una acción no crea un perfil. Consulta la configuración del perfil del sitio.

  2. 2.

    Configura las variables de entorno

    Establece SOLVETHREE_API_KEY con la clave de API de tu espacio de trabajo y SOLVETHREE_PROXY con la URL del proxy HTTP o HTTPS que también usarás al enviar el token al destino. Mantén la clave en el servidor.

  3. 3.

    Cambia los datos de entrada del ejemplo

    Sustituye accounts.example.com por el nombre de host de destino —no una URL completa— y sustituye login por la acción que requiere ese destino. La solicitud usa un solo proxy; no añadas también proxyCandidates. Omite type y url. Si omites recaptchaType, se selecciona el valor predeterminado, enterprise-v3.

Guarda el ejemplo como solve.rb y ejecútalo con Ruby después de definir esas variables. Carga net/http, json y securerandom; JSON gestiona el cuerpo de la solicitud y las respuestas de la API.

Crea la tarea una vez y luego consulta su ID

Ruby · una creación y consultas periódicas finitas
require 'net/http'
require 'json'
require 'securerandom'

api = 'https://api.solvethree.com/v1'
input = {site: 'accounts.example.com', action: 'login', proxy: ENV.fetch('SOLVETHREE_PROXY'), requestId: SecureRandom.uuid}
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 180
call = lambda do |method, path, body = nil|
  remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
  raise 'Local deadline reached' if remaining <= 0
  uri = URI(api + path)
  request = method == :post ? Net::HTTP::Post.new(uri) : Net::HTTP::Get.new(uri)
  request['Authorization'] = 'Bearer ' + ENV.fetch('SOLVETHREE_API_KEY')
  request['Accept'] = 'application/json'
  if body
    request['Content-Type'] = 'application/json'
    request.body = JSON.generate(body)
  end
  # Net::HTTP's own proxy configuration is separate from input[:proxy].
  http = Net::HTTP.new(uri.hostname, uri.port, nil)
  http.use_ssl = uri.scheme == 'https'
  http.open_timeout = [10, remaining].min
  http.read_timeout = [25, remaining].min
  http.write_timeout = [25, remaining].min
  http.max_retries = 0
  response = http.request(request)
  raise "API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
  JSON.parse(response.body)
end

task_id = nil
begin
  result = call.call(:post, '/tasks?waitMs=0', input)
  task_id = result.fetch('id')
  while %w[pending solving].include?(result.fetch('status'))
    result = call.call(:get, '/tasks/' + URI.encode_www_form_component(task_id) + '?waitMs=15000')
    sleep(1) if %w[pending solving].include?(result.fetch('status'))
  end
  raise "Task failed: #{result['errorCode']}" unless result['status'] == 'ready'
  puts "Ready task: #{task_id}"
  # Submit result['solution']['token'] with its userAgent/secChUa and original proxy.
rescue StandardError => error
  warn "Recovery requestId=#{input[:requestId]} taskId=#{task_id || 'unknown'}"
  raise error
end

El script envía una sola solicitud de creación, guarda el ID de tarea devuelto y consulta esa tarea mientras su estado sea pending o solving. Solo ready proporciona una solución utilizable. Cada respuesta debe tener un estado HTTP correcto antes de analizar su cuerpo como una respuesta de éxito.

HTTPS se habilita explícitamente. Los reintentos automáticos están deshabilitados y las redirecciones se rechazan mediante la comprobación del estado HTTP en lugar de seguirlas. El proxy del cuerpo de la tarea se usa para la resolución; no configura la conexión de Ruby a la API de solvethree.

El plazo monotónico compartido establece un límite local de 180 segundos para las consultas periódicas. Los tiempos de espera de conexión, lectura y escritura se limitan según el tiempo restante al iniciar cada solicitud. Considera ese límite como un límite de las consultas periódicas, no como un temporizador de cancelación estricto para una solicitud en curso. La documentación de Net::HTTP de Ruby describe cada ajuste de tiempo de espera.

Envía el token con su identidad de navegador

El ejemplo imprime el ID de la tarea lista, no el token. Lee solution.token del resultado listo y colócalo en el campo de token que espera la solicitud al destino. No envíes el ID de tarea en su lugar.

Usa el valor devuelto de solution.userAgent para la cabecera User-Agent y el de solution.secChUa para Sec-CH-UA. Envía la solicitud al destino previsto a través del mismo proxy proporcionado a esta tarea. No sustituyas la identidad devuelta por las cabeceras de un navegador ajeno.

Una tarea lista significa que solvethree ha generado una solución. Comprueba la respuesta del destino por separado para determinar si ha aceptado la solicitud de tu aplicación.

Gestiona los fallos sin crear tareas duplicadas

El script lanza un error HTTP de la API.

Examina la respuesta HTTP no satisfactoria. Se trata de un error de la solicitud, no de un resultado terminal de la tarea.

Prueba esto: Diagnostica esa respuesta antes de reintentar. No envíes repetidamente los mismos datos de entrada no válidos.

La tarea pasa al estado failed.

Examina tanto errorCode como error en el resultado. El mensaje de error que lanza el ejemplo solo incluye errorCode.

Prueba esto: Deja de consultar esa tarea y corrige la causa indicada. Las resoluciones fallidas se reembolsan; un fallo no significa necesariamente que el saldo sea insuficiente.

Se agota el tiempo de espera de la creación antes de recibir un ID de tarea.

Conserva el requestId de recuperación escrito en la salida de error estándar. Que se agote el tiempo de espera no demuestra que la creación haya fallado.

Prueba esto: Recupera la tarea enviando una solicitud idéntica con ese mismo ID de solicitud. No te limites a volver a ejecutar el script: una nueva ejecución genera un ID nuevo y puede crear otra tarea.

Las consultas periódicas alcanzan el plazo local o pierden la conexión.

Conserva el ID de tarea y el ID de solicitud registrados.

Prueba esto: Consulta el ID de tarea conocido antes de crear otra tarea. Una excepción local no es un estado terminal de la tarea.

Para poder recuperar la tarea tras reinicios del proceso, conserva el ID de solicitud y los datos de entrada originales antes de enviar el POST, y después conserva el ID de tarea cuando se devuelva. Reutilizar un ID de solicitud con datos idénticos devuelve la tarea existente; cambiar los datos manteniendo ese ID provoca un conflicto. Consulta la gestión de errores de la API para conocer el siguiente paso de diagnóstico.

Ejecuta tu primera tarea.

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

Crear un espacio de trabajo
Resuelve reCAPTCHA Enterprise con Ruby · solvethree