Use o Guzzle com a API de tarefas de CAPTCHA

Por solvethree4 min de leitura

Use Guzzle 7 para criar uma tarefa e depois consultar seu ID periodicamente até que ela esteja em ready ou failed. Guarde o requestId se algo der errado: um timeout de conexão não prova que a criação da tarefa falhou.

Esta é uma integração REST, não um SDK oficial de PHP.

Nesta página

Prepare a requisição de reCAPTCHA

  • Instale Guzzle 7 com Composer. O comando de instalação aparece no início do exemplo.
  • Defina SOLVETHREE_API_KEY como a chave da API do seu workspace e SOLVETHREE_PROXY como a URL do proxy. Mantenha a chave no servidor.
  • Crie um perfil ativo para seu site de destino no console antes de solicitar uma resolução. Veja a configuração do perfil do site.
  • Substitua accounts.example.com e login pelo hostname e pela ação de destino. O campo site recebe um hostname, não uma URL completa.

O exemplo solicita reCAPTCHA Enterprise v3, o recaptchaType padrão. Não adicione os campos type ou url. Ele fornece um proxy; se você usar proxyCandidates em vez disso, omita proxy por completo.

Crie uma vez e depois consulte periodicamente dentro de um limite fixo de tempo

Guzzle · um POST e consultas periódicas com limites
<?php
// composer require guzzlehttp/guzzle:^7
require __DIR__.'/vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://api.solvethree.com/v1/',
    'headers' => ['Authorization' => 'Bearer '.getenv('SOLVETHREE_API_KEY'), 'Accept' => 'application/json'],
    'allow_redirects' => false,
    'http_errors' => false,
]);
$input = ['site' => 'accounts.example.com', 'action' => 'login',
    'proxy' => getenv('SOLVETHREE_PROXY'), 'requestId' => bin2hex(random_bytes(16))];
$deadline = microtime(true) + 180;
$call = function (string $method, string $path, array $options = []) use ($client, $deadline): array {
    $remaining = $deadline - microtime(true);
    if ($remaining <= 0) throw new RuntimeException('Local deadline reached');
    $response = $client->request($method, $path, $options + ['timeout' => min(25, $remaining), 'connect_timeout' => min(10, $remaining)]);
    if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
        throw new RuntimeException('API HTTP '.$response->getStatusCode());
    }
    return json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
};
$id = null;
try {
    $result = $call('POST', 'tasks?waitMs=0', ['json' => $input]);
    $id = $result['id'];
    while (in_array($result['status'], ['pending', 'solving'], true)) {
        $result = $call('GET', 'tasks/'.rawurlencode($id).'?waitMs=15000');
        if (in_array($result['status'], ['pending', 'solving'], true)) usleep(1000000);
    }
    if ($result['status'] !== 'ready') {
        throw new RuntimeException('Task failed: '.($result['errorCode'] ?? 'unknown'));
    }
    echo 'Ready task: '.$id.PHP_EOL;
    // Submit $result['solution']['token'] with userAgent/secChUa and the same proxy.
} catch (Throwable $error) {
    fwrite(STDERR, 'Recovery requestId='.$input['requestId'].' taskId='.($id ?? 'unknown').PHP_EOL);
    throw $error;
}

O cliente se autentica com uma chave Bearer. Seu base_uri termina em /v1/, e os caminhos das requisições são relativos, preservando esse prefixo da API. A opção json do Guzzle envia a entrada da tarefa como JSON.

O helper faz um único POST de criação. Em seguida, consulta periodicamente o ID da tarefa retornado enquanto o status for pending ou solving. A criação e as consultas compartilham um limite de 180 segundos; cada chamada HTTP é limitada ao tempo restante, com timeouts máximos de requisição e conexão de 25 e 10 segundos, respectivamente. Uma nova consulta não reinicia o limite total de tempo.

Os redirecionamentos estão desativados. Definir http_errors como false permite que o helper verifique explicitamente respostas fora da faixa 2xx antes de decodificar um conteúdo de sucesso; isso não suprime erros de conexão nem timeouts.

  • Uma resposta HTTP fora da faixa 2xx lança um erro HTTP da API. Analise o status e o corpo da resposta em vez de tratá-la como uma resolução que falhou.
  • Uma tarefa no estado terminal failed encerra as consultas. O exemplo lança seu errorCode; examine também o campo error da tarefa para ver a mensagem de diagnóstico. Resoluções que falham são reembolsadas.
  • Somente ready contém uma solução utilizável. A linha “Ready task” impressa informa que a tarefa está pronta, não que foi aceita pelo site de destino.

Recupere uma requisição que excedeu o tempo limite sem pagar por outra tarefa

Guarde o requestId gerado e a entrada exata da tarefa antes de enviar o POST. O bloco catch imprime requestId e, se a criação tiver retornado um, taskId. Essa saída ajuda na recuperação, mas não substitui salvar a requisição antes de enviá-la.

  1. 1.

    Se você tem um ID de tarefa, consulte essa tarefa

    Use GET /v1/tasks/:id para verificar seu status. Atingir o prazo local do helper não comprova que a tarefa remota falhou.

  2. 2.

    Se a criação excedeu o tempo limite sem retornar um ID, recupere-a com requestId

    Envie a mesma requisição de tarefa com o requestId salvo. Entradas correspondentes retornam a tarefa existente; entradas diferentes com esse ID causam conflito.

  3. 3.

    Não execute o script novamente como atalho de recuperação

    Cada execução gera um novo requestId. Não adicione uma nova tentativa automática de POST que gere outro ID e não repita cegamente uma entrada inválida sem alterá-la.

Envie o token pelo mesmo proxy

O exemplo para antes de contatar o destino. Envie solution.token — não o ID da tarefa — e use os valores retornados de solution.userAgent e solution.secChUa como os cabeçalhos User-Agent e Sec-CH-UA da requisição de destino.

O proxy dentro do JSON da tarefa informa ao solvethree qual proxy usar na resolução. Ele não configura a conexão do Guzzle com a API nem sua requisição posterior ao destino. Configure a requisição de destino separadamente para usar esse mesmo proxy.

Use um cliente separado para a requisição de destino, para que o cabeçalho Authorization padrão do cliente da API não seja enviado ao site. Mantenha juntos o token, a identidade de navegador retornada, o proxy e o destino pretendido. Um token pronto ainda pode ser rejeitado se a requisição subsequente não corresponder.

Execute sua primeira tarefa.

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

Criar um espaço de trabalho
Use o Guzzle com a API de tarefas de CAPTCHA · solvethree