Skip to content

Commit

Permalink
Keycaptcha recognition support
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Gladyshev committed Sep 12, 2017
1 parent e32d59b commit b7ff0be
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/advanced.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
$taskIds = [];

$taskIds[] = $rucaptcha->sendCaptcha(file_get_contents(__DIR__.'/data/captcha.png'));
//$taskIds[] = $rucaptcha->sendCaptcha(file_get_contents(__DIR__.'/data/unreadable.png'));
$taskIds[] = $rucaptcha->sendCaptcha(file_get_contents(__DIR__.'/data/yandex.gif'), [
Rucaptcha\Extra::IS_RUSSIAN => 1
]);
Expand Down
Binary file added examples/data/unreadable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
149 changes: 149 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use GuzzleHttp\RequestOptions;
use Rucaptcha\Exception\ErrorResponseException;
use Rucaptcha\Exception\InvalidArgumentException;
use Rucaptcha\Exception\RuntimeException;

/**
Expand All @@ -14,6 +15,11 @@
*/
class Client extends GenericClient
{
/* json status codes */
const STATUS_CODE_CAPCHA_NOT_READY = 0;
const STATUS_CODE_OK = 1;

/* status codes */
const STATUS_OK_REPORT_RECORDED = 'OK_REPORT_RECORDED';

/**
Expand Down Expand Up @@ -278,6 +284,10 @@ public function sendRecapthaV2($googleKey, $pageUrl, $extra = [])
{
$this->getLogger()->info("Try send google key (recaptcha) on {$this->serverBaseUri}/in.php");

if ($this->softId && !isset($extra[Extra::SOFT_ID])) {
$extra[Extra::SOFT_ID] = $this->softId;
}

$response = $this->getHttpClient()->request('POST', "/in.php", [
RequestOptions::QUERY => array_merge($extra, [
'method' => 'userrecaptcha',
Expand All @@ -299,6 +309,8 @@ public function sendRecapthaV2($googleKey, $pageUrl, $extra = [])
}

/**
* Recaptcha V2 recognition.
*
* @param string $googleKey
* @param string $pageUrl
* @param array $extra # Captcha options
Expand Down Expand Up @@ -333,6 +345,143 @@ public function recognizeRecaptchaV2($googleKey, $pageUrl, $extra = [])
throw new RuntimeException('Unknown recognition logic error.');
}

/**
* Keycaptcha recognition.
*
* @param string $SSCUserId
* @param string $SSCSessionId
* @param string $SSCWebServerSign
* @param string $SSCWebServerSign2
* @param string $pageUrl
* @param array $extra
* @return string # Captcha ID
* @throws ErrorResponseException
*/
public function sendKeyCaptcha(
$SSCUserId,
$SSCSessionId,
$SSCWebServerSign,
$SSCWebServerSign2,
$pageUrl,
$extra = []
) {

$this->getLogger()->info("Try send google key (recaptcha) on {$this->serverBaseUri}/in.php");

if ($this->softId && !isset($extra[Extra::SOFT_ID])) {
$extra[Extra::SOFT_ID] = $this->softId;
}

$response = $this->getHttpClient()->request('POST', "/in.php", [
RequestOptions::QUERY => array_merge($extra, [
'method' => 'keycaptcha',
'key' => $this->apiKey,
's_s_c_user_id' => $SSCUserId,
's_s_c_session_id' => $SSCSessionId,
's_s_c_web_server_sign' => $SSCWebServerSign,
's_s_c_web_server_sign2' => $SSCWebServerSign2,
'pageurl' => $pageUrl
])
]);

$responseText = $response->getBody()->__toString();

if (strpos($responseText, 'OK|') !== false) {
$this->lastCaptchaId = explode("|", $responseText)[1];
$this->getLogger()->info("Sending success. Got captcha id `{$this->lastCaptchaId}`.");
return $this->lastCaptchaId;
}

throw new ErrorResponseException($this->getErrorMessage($responseText) ?: "Unknown error: `{$responseText}`.");
}

/**
* Keycaptcha recognition.
*
* @param string $SSCUserId
* @param string $SSCSessionId
* @param string $SSCWebServerSign
* @param string $SSCWebServerSign2
* @param string $pageUrl
* @param array $extra
* @return string # Code to place into id="capcode" input value
* @throws RuntimeException
*/
public function recognizeKeyCaptcha(
$SSCUserId,
$SSCSessionId,
$SSCWebServerSign,
$SSCWebServerSign2,
$pageUrl,
$extra = []
) {
$captchaId = $this
->sendKeyCaptcha($SSCUserId, $SSCSessionId, $SSCWebServerSign, $SSCWebServerSign2, $pageUrl, $extra);

$startTime = time();

while (true) {
$this->getLogger()->info("Waiting {$this->rTimeout} sec.");

sleep($this->recaptchaRTimeout);

if (time() - $startTime >= $this->mTimeout) {
throw new RuntimeException("Captcha waiting timeout.");
}

$result = $this->getCaptchaResult($captchaId);

if ($result === false) {
continue;
}

$this->getLogger()->info("Elapsed " . (time()-$startTime) . " second(s).");

return $result;
}

throw new RuntimeException('Unknown recognition logic error.');
}

/**
* Override generic method for using json response.
*
* @param string $captchaId # Captcha task ID
* @return false|string # Solved captcha text or false if captcha is not ready
* @throws ErrorResponseException
* @throws InvalidArgumentException
*/
public function getCaptchaResult($captchaId)
{
$response = $this
->getHttpClient()
->request('GET', "/res.php?key={$this->apiKey}&action=get&id={$captchaId}&json=1");

$responseData = json_decode($response->getBody()->__toString(), true);

if (JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidArgumentException(
'json_decode error: ' . json_last_error_msg()
);
}

if ($responseData['status'] === self::STATUS_CODE_CAPCHA_NOT_READY) {
return false;
}

if ($responseData['status'] === self::STATUS_CODE_OK) {
$this->getLogger()->info("Got OK response: `{$responseData['request']}`.");
return $responseData['request'];
}

throw new ErrorResponseException(
$this->getErrorMessage(
$responseData['request']
) ?: $responseData['request'],
$responseData['status']
);
}

/**
* Match error code by response.
*
Expand Down

0 comments on commit b7ff0be

Please sign in to comment.