PHPでreCAPTCHA Enterpriseを解く

著者:solvethree読了時間:1分

PHP から solvethree を直接呼び出せます。以下の例では、reCAPTCHA v3 Enterprise トークンをリクエストし、タスクが完了するまで状態を確認し、解決に失敗した場合は停止します。

このページの内容

実行前の準備

cURL 拡張機能を備えた PHP 8+ を使用してください。cURL 拡張機能を有効にしたサーバー上で実行します。

  • コンソールで、対象ホスト名に対応する有効なサイトプロファイルを作成してください。サイトプロファイルの設定を参照してください。
  • SOLVETHREE_API_KEY にワークスペースの API キーを、SOLVETHREE_PROXY に HTTP(S) プロキシ URL を設定してください。
  • accounts.example.com と login を、使用するホスト名とページで使用されているアクションに置き換えてください。site には、スキームやパスを含めずにホスト名を指定します。

タスクを作成して結果を待つ

コードを solve.php として保存し、php solve.php を実行してください。

PHP 8 · solve.php
<?php
// Requires PHP 8+ with the cURL extension.
$apiKey = getenv('SOLVETHREE_API_KEY');
$proxy = getenv('SOLVETHREE_PROXY');
if (!$apiKey || !$proxy) throw new RuntimeException('Set the API key and proxy');

function api(string $path, ?array $body = null): array {
    global $apiKey, $deadline;
    $remaining = $deadline - microtime(true);
    if ($remaining <= 0) throw new RuntimeException("Keep the task ID and resume polling");
    $curl = curl_init('https://api.solvethree.com/v1' . $path);
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => min(30000, max(1, (int) ceil($remaining * 1000))),
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey, 'Content-Type: application/json'],
    ]);
    if ($body !== null) {
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body, JSON_THROW_ON_ERROR));
    }
    $raw = curl_exec($curl);
    $error = curl_error($curl);
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    if ($raw === false) throw new RuntimeException('Connection failed: ' . $error);
    if ($status < 200 || $status >= 300) throw new RuntimeException('API HTTP ' . $status);
    return json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
}

$requestId = bin2hex(random_bytes(16)); // Save this with the task inputs for recovery.
$deadline = microtime(true) + 180;
$task = api('/tasks?waitMs=0', [
    'site' => 'accounts.example.com', 'action' => 'login',
    'proxy' => $proxy, 'requestId' => $requestId,
]);
while (in_array($task['status'], ['pending', 'solving'], true)) {
    if (microtime(true) >= $deadline) throw new RuntimeException('Keep the task ID and resume polling');
    $task = api('/tasks/' . rawurlencode($task['id']) . '?waitMs=15000');
    if (in_array($task['status'], ['pending', 'solving'], true)) usleep(1000000);
}
if ($task['status'] !== 'ready') throw new RuntimeException(
    ($task['errorCode'] ?? 'Unexpected task state') . ': ' . ($task['error'] ?? '')
);
$solution = $task['solution'];
// Use $solution['token'], ['userAgent'] and ['secChUa'] with the same proxy.
echo 'Ready task: ' . $task['id'] . PHP_EOL;

POST は waitMs=0 を使用してタスクを即座に返します。その後、各 GET は更新を最大 15 秒待機します。ループは pending または solving の間は継続し、ready または failed で停止します。

リクエストのデフォルトは Enterprise v3 です。標準の v3 を使用するには、recaptchaType: v3 を追加してください。reCAPTCHA のタスク本文には type と url を含めないでください。

アプリケーションでトークンを使用する

トークンは $solution['token'] です。プログラムが出力するタスク ID はタスクの取得用です。アプリケーションの CAPTCHA フィールドにはトークンの値を使用してください。

対象へのリクエストでは、$solution['userAgent'] を User-Agent として、$solution['secChUa'] を sec-ch-ua として使用してください。

そのリクエストは、解決に使用したものと同じプロキシ経由で送信してください。その後、アプリケーションのレスポンスを確認します。トークンが生成されても、対象がリクエストを受け入れたことを意味するわけではありません。

リクエストが失敗した場合

失敗したタスクには errorCode と error が含まれます。この例では処理を停止し、それらを報告します。解決に失敗した場合は返金されます。401 や 402 などの HTTP エラーは、これとは別のリクエストの問題です。再試行する前にAPI エラーリファレンスを確認してください。

タイムアウトやプロセスの再起動後に復旧する必要がある場合は、requestId と正確なタスク入力を保存してください。タスク ID がある場合は、そのタスクをポーリングします。ない場合は、同じ requestId で元の入力を再送信します。単にプログラムを再起動すると別の ID が生成され、課金対象の解決処理がもう 1 件作成される可能性があります。

呼び出し元は期限に達すると待機を停止しますが、すでに作成されたタスクはキャンセルされません。手順全体については、ポーリングとタイムアウトからの復旧を参照してください。

最初のタスクを実行しましょう。

$5のワークスペースクレジットで始められます。

ワークスペースを作成
PHPでreCAPTCHA Enterpriseを解く · solvethree