Guzzle로 CAPTCHA 작업 API 사용하기

작성: solvethree읽는 데 3분

Guzzle 7로 작업을 생성한 다음 작업이 ready 또는 failed가 될 때까지 해당 ID를 폴링하세요. 문제가 생기면 requestId를 보관하세요. 연결 시간 초과가 작업 생성 실패를 입증하지는 않습니다.

이는 공식 PHP SDK가 아닌 REST 연동입니다.

이 페이지의 내용

reCAPTCHA 요청 준비

  • Composer로 Guzzle 7을 설치하세요. 설치 명령은 예제 맨 위에 있습니다.
  • SOLVETHREE_API_KEY를 워크스페이스 API 키로, SOLVETHREE_PROXY를 프록시 URL로 설정하세요. 키는 서버에 보관하세요.
  • 풀이를 요청하기 전에 콘솔에서 대상 사이트의 활성 프로필을 생성하세요. 사이트 프로필 설정을 참고하세요.
  • accounts.example.com과 login을 대상 호스트 이름과 액션으로 바꾸세요. site 필드에는 전체 URL이 아닌 호스트 이름을 넣습니다.

예제는 기본 recaptchaType인 reCAPTCHA Enterprise v3를 요청합니다. type 또는 url 필드를 추가하지 마세요. 프록시 하나를 제공하며, 대신 proxyCandidates를 사용한다면 proxy를 완전히 생략하세요.

한 번 생성한 후 정해진 시간 내에서 폴링

Guzzle · POST 1회 및 제한된 폴링
<?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;
}

클라이언트는 Bearer 키로 인증합니다. base_uri는 /v1/로 끝나고 요청 경로는 상대 경로이므로 해당 API 접두사가 유지됩니다. Guzzle의 json 옵션은 작업 입력을 JSON으로 전송합니다.

헬퍼는 생성 POST를 한 번 보냅니다. 그런 다음 상태가 pending 또는 solving인 동안 반환된 작업 ID를 폴링합니다. 생성과 폴링에는 합쳐서 180초가 주어집니다. 각 HTTP 호출은 남은 시간으로 제한되며, 요청 및 연결 시간 제한의 최댓값은 각각 25초와 10초입니다. 새 폴링을 시작해도 전체 제한 시간이 초기화되지 않습니다.

리디렉션은 비활성화되어 있습니다. http_errors를 false로 설정하면 헬퍼가 성공 페이로드를 디코딩하기 전에 2xx가 아닌 응답을 명시적으로 확인할 수 있습니다. 연결 오류나 시간 초과를 억제하는 것은 아닙니다.

  • 2xx가 아닌 HTTP 응답은 API HTTP 오류를 발생시킵니다. 이를 풀이 실패로 취급하지 말고 응답 상태와 본문을 확인해 원인을 진단하세요.
  • 작업이 최종 failed 상태가 되면 폴링을 중단합니다. 예제는 errorCode를 예외로 발생시킵니다. 진단 메시지를 확인하려면 작업의 error 필드도 살펴보세요. 풀이에 실패하면 환불됩니다.
  • 사용 가능한 솔루션은 ready에만 포함됩니다. 출력되는 “Ready task” 줄은 작업이 준비되었음을 나타내며, 대상 웹사이트가 이를 수락했다는 의미는 아닙니다.

추가 작업 비용 없이 시간 초과된 요청 복구하기

POST를 보내기 전에 생성한 requestId와 정확한 작업 입력을 보관하세요. catch 블록은 requestId와, 생성 시 반환되었다면 taskId를 출력합니다. 이 출력은 복구에 도움이 되지만 전송 전에 요청을 저장하는 것을 대신하지는 않습니다.

  1. 1.

    작업 ID가 있다면 해당 작업 조회

    GET /v1/tasks/:id로 상태를 확인하세요. 헬퍼의 로컬 대기 기한에 도달했다고 해서 원격 작업이 실패했다고 단정할 수는 없습니다.

  2. 2.

    ID 반환 없이 생성 요청 시간이 초과되면 requestId로 복구

    저장한 requestId로 같은 작업 요청을 제출하세요. 입력이 일치하면 기존 작업을 반환하며, 같은 ID에 다른 입력을 사용하면 충돌이 발생합니다.

  3. 3.

    간편한 복구 방법으로 스크립트를 다시 실행하지 않기

    실행할 때마다 새 requestId가 생성됩니다. 다른 ID를 생성하는 POST 자동 재시도를 추가하지 말고, 잘못된 입력을 변경 없이 무작정 재시도하지 마세요.

동일한 프록시를 통해 토큰 제출

예제는 대상에 연결하기 전에 종료됩니다. 작업 ID가 아닌 solution.token을 제출하고, 반환된 solution.userAgent와 solution.secChUa를 대상 요청의 User-Agent 및 Sec-CH-UA 헤더로 사용하세요.

작업 JSON의 프록시는 solvethree가 풀이에 사용할 프록시를 지정합니다. Guzzle의 API 연결이나 이후 대상에 보내는 요청을 구성하지는 않습니다. 대상 요청에서도 같은 프록시를 사용하도록 별도로 설정하세요.

API 클라이언트의 기본 Authorization 헤더가 웹사이트에 전송되지 않도록 대상 요청에는 별도 클라이언트를 사용하세요. 토큰, 반환된 브라우저 식별 정보, 프록시, 의도한 대상을 함께 관리하세요. 후속 요청이 일치하지 않으면 준비된 토큰도 거부될 수 있습니다.

첫 작업을 실행하세요.

워크스페이스 크레딧 $5로 시작하세요.

워크스페이스 만들기
Guzzle로 CAPTCHA 작업 API 사용하기 · solvethree