Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"homepage": "https://2captcha.com/"
}
],
"scripts": {
"test": "phpunit"
},
"require": {
"php": ">=7.3",
"ext-curl": "*",
Expand Down
6 changes: 4 additions & 2 deletions examples/canvas.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

require(__DIR__ . '/../src/autoloader.php');

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

try {
$result = $solver->canvas([
Expand All @@ -15,4 +16,5 @@
die($e->getMessage());
}

die('Captcha solved: ' . $result->code);
var_dump($result);
// die('Captcha solved: ' . $result->code);
11 changes: 8 additions & 3 deletions examples/coordinates.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

require(__DIR__ . '/../src/autoloader.php');

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

try {
$result = $solver->coordinates(__DIR__ . '/images/grid.jpg');
$result = $solver->coordinates([
'file' => __DIR__ . '/images/grid_2.jpg',
'hintImg' => __DIR__ . '/images/grid_hint.jpg'
]);
} catch (\Exception $e) {
die($e->getMessage());
}

die('Captcha solved: ' . $result->code);
var_dump($result);
// die('Captcha solved: ' . $result->code);
4 changes: 3 additions & 1 deletion examples/coordinates_base64.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
$image = __DIR__ . '/images/grid.jpg';
$base64 = base64_encode(file_get_contents($image));

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

try {
$result = $solver->coordinates(['base64' => $base64]);
} catch (\Exception $e) {
die($e->getMessage());
}

var_dump($result);
die('Captcha solved: ' . $result->code);
14 changes: 8 additions & 6 deletions examples/geetest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@

require(__DIR__ . '/../src/autoloader.php');

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

// To bypass GeeTest first we need to get new challenge value
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mysite.com/captcha_challenge");
curl_setopt($ch, CURLOPT_URL, "https://2captcha.com/api/v1/captcha-demo/gee-test/init-params?t=" . time());
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$resp = curl_exec($ch);
$challenge = explode(";", $resp)[0];
$challenge = json_decode($resp)->challenge;

// Then we are ready to make a call to 2captcha API
try {
$result = $solver->geetest([
'gt' => 'f2ae6cadcf7886856696502e1d55e00c',
'apiServer' => 'api-na.geetest.com',
'gt' => '81388ea1fc187e0c335c0a8907ff2625',
'apiServer' => 'api.geetest.com',
'challenge' => $challenge,
'url' => 'https://mysite.com/captcha.html',
'url' => 'https://2captcha.com/demo/geetest',
]);
} catch (\Exception $e) {
die($e->getMessage());
}

var_dump($result);
die('Captcha solved: ' . $result->code);
13 changes: 11 additions & 2 deletions examples/grid.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@

require(__DIR__ . '/../src/autoloader.php');

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

try {
$result = $solver->grid(__DIR__ . '/images/grid.jpg');
$result = $solver->grid([
'file' => __DIR__ . '/images/grid_2.jpg',
'rows' => 3,
'cols' => 3,
'lang' => 'en',
// 'hintText' => 'Select all images with an Orange',
'hintImg' => __DIR__ . '/images/grid_hint.jpg',
]);
} catch (\Exception $e) {
die($e->getMessage());
}

var_dump($result);
die('Captcha solved: ' . $result->code);
11 changes: 6 additions & 5 deletions examples/hcaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
set_time_limit(130);

require(__DIR__ . '/../src/autoloader.php');

$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
$apikey = getenv("APIKEY");
$solver = new \TwoCaptcha\TwoCaptcha($apikey);

try {
$result = $solver->hcaptcha([
'sitekey' => '10000000-ffff-ffff-ffff-000000000001',
'url' => 'https://www.site.com/page/',
'sitekey' => 'c0421d06-b92e-47fc-ab9a-5caa43c04538',
'url' => 'https://2captcha.com/demo/hcaptcha',
]);
} catch (\Exception $e) {
die($e->getMessage());
}

die('Captcha solved: ' . $result->code);
var_dump($result);
die('Captcha ' . $result->captchaId .' solved! Token: ' . $result->code . ' respKey: ' . $result->respKey . ' useragent: ' . $result->useragent);
6 changes: 3 additions & 3 deletions src/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function in($captcha, $files = [])
if (!$this->curl) $this->curl = curl_init();

foreach ($files as $key => $file) {
$captcha[$key] = $this->curlPrepareFile($file);
$captcha[$key] = $this->curlPrepareFile($file, $key);
}

curl_setopt_array($this->curl, [
Expand Down Expand Up @@ -114,10 +114,10 @@ private function execute()
* @param $file
* @return \CURLFile|string
*/
private function curlPrepareFile($file)
private function curlPrepareFile($file, $key = 'file')
{
if (function_exists('curl_file_create')) { // php 5.5+
return curl_file_create($file, mime_content_type($file), 'file');
return curl_file_create($file, mime_content_type($file), $key);
} else {
return '@' . realpath($file);
}
Expand Down
75 changes: 67 additions & 8 deletions src/TwoCaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,10 @@ public function grid($captcha)
}

$this->requireFileOrBase64($captcha);
$this->requireHintOrHintImg($captcha);

$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
$captcha['recaptcha'] = 1;

return $this->solve($captcha);
}
Expand Down Expand Up @@ -498,7 +500,7 @@ public function canvas($captcha)
$captcha['canvas'] = 1;

if ( empty($captcha['hintText']) && empty($captcha['hintImg']) ) {
throw new ValidationException('At least one of parameters: hintText or hintImg required!');
throw new ValidationException('At least one parameter required: hintText or hintImg');
}

return $this->solve($captcha);
Expand All @@ -523,6 +525,7 @@ public function coordinates($captcha)
}

$this->requireFileOrBase64($captcha);
$this->requireHintOrHintImg($captcha);

$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
$captcha['coordinatescaptcha'] = 1;
Expand Down Expand Up @@ -600,11 +603,50 @@ public function solve($captcha, $waitOptions = [])
{
$result = new \stdClass();

$result->captchaId = $this->send($captcha);
$captchaId = $this->send($captcha);

if ($this->lastCaptchaHasCallback) return $result;

$result->code = $this->waitForResult($result->captchaId, $waitOptions);
$result = $this->waitForResult($captchaId, $waitOptions);

$result->captchaId = $captchaId;

if (is_object($result->request)) {
$result->code = json_encode($result->request);
} elseif (is_array($result->request) && isset($result->request[0])) {
if (is_object($result->request[0])) {

$firstElement = $result->request[0];

if (isset($firstElement->{"0"}) && is_array($firstElement->{"0"})) {
$code = "canvas:";
foreach ($result->request[0] as $key => $value) {
$coordinates = [];
foreach ($value as $coord) {
$coordinates[] = $coord->x . ',' . $coord->y;
}
$code .= implode(',', $coordinates) . ';';
}
$result->canvas = $result->request;
} else {
$coordinates = [];
$code = "coordinates:";
foreach ($result->request as $coord) {
$coordinates[] = 'x=' . $coord->x . ',' . 'y=' . $coord->y;
}
$code .= implode(';', $coordinates);
$result->coordinates = $result->request;
}

$result->code = $code;
unset($result->request);
return $result;
}
} else {
$result->code = $result->request;
unset($result->request);
}
unset($result->status);

return $result;
}
Expand Down Expand Up @@ -686,15 +728,19 @@ public function getResult($id)
'id' => $id,
]);

if ($response == 'CAPCHA_NOT_READY') {
$decoded_response = json_decode($response);

if ($decoded_response->request == 'CAPCHA_NOT_READY') {
return null;
}

if (mb_strpos($response, 'OK|') !== 0) {
if ($decoded_response->status == 0) {
throw new ApiException('Cannot recognise api response (' . $response . ')');
}

return mb_substr($response, 3);
if ($decoded_response->status == 1) {
return $decoded_response;
}
}

/**
Expand All @@ -707,8 +753,8 @@ public function getResult($id)
public function balance()
{
$response = $this->res('getbalance');

return floatval($response);
$decoded_response = json_decode($response);
return floatval($decoded_response->request);
}

/**
Expand Down Expand Up @@ -743,6 +789,7 @@ private function res($query)
}

$query['key'] = $this->apiKey;
$query['json'] = 1;

return $this->apiClient->res($query);
}
Expand Down Expand Up @@ -791,6 +838,18 @@ private function requireFileOrBase64($captcha, $key = 'file')
}
}

/**
* Validates if grid/coordinates parameters are correct
*
* @param $captcha
* @param string $key
* @throws ValidationException
*/
private function requireHintOrHintImg($captcha)
{
if (empty($captcha['hintText']) && empty($captcha['hintImg'])) throw new ValidationException('At least one parameter: hintText or hintImg is required');
}

/**
* Turns `files` parameter into `file_1`, `file_2`, `file_n` parameters
*
Expand Down
23 changes: 21 additions & 2 deletions tests/AbstractWrapperTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,16 @@ protected function checkIfCorrectParamsSendAndResultReturned($data)
)
->willReturn('OK|' . $captchaId);


$resMock = new \stdClass();
$resMock->status = 1;
$resMock->request = $code;

$apiClient
->expects($this->once())
->method('res')
->with($this->equalTo(['action' => 'get', 'id' => $captchaId, 'key' => $apiKey]))
->willReturn('OK|' . $code);
->with($this->equalTo(['action' => 'get', 'id' => $captchaId, 'key' => $apiKey, 'json' => 1]))
->willReturn(json_encode($resMock));

$solver = new TwoCaptcha([
'apiKey' => $apiKey,
Expand Down Expand Up @@ -90,4 +95,18 @@ protected function checkIfExceptionThrownOnTooManyFiles()

$result = $solver->{$this->method}($files);
}

/**
* If required parameters are missing
* should trigger ValidationException
*/
protected function checkIfExceptionThrownOnMissingParameter($data)
{
$this->expectException(ValidationException::class);

$solver = new TwoCaptcha('API_KEY');

$result = $solver->{$this->method}($data['params']);
}

}
20 changes: 13 additions & 7 deletions tests/CoordinatesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,35 @@ class CoordinatesTest extends AbstractWrapperTestCase

private $captchaImg = __DIR__ . '/../examples/images/grid.jpg';

public function testSingleFile()
public function testMissingParameterCase()
{
$this->checkIfCorrectParamsSendAndResultReturned([
$this->checkIfExceptionThrownOnMissingParameter([
'params' => $this->captchaImg,
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1, 'soft_id' => '4585'],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1, 'soft_id' => 4585,],
'sendFiles' => ['file' => $this->captchaImg],
]);
}

public function testSingleFileParameter()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['file' => $this->captchaImg],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1,'soft_id' => '4585'],
'params' => [
'file' => $this->captchaImg,
'hintText' => 'Select all images with an Orange',
],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1,'soft_id' => '4585', 'textinstructions' => 'Select all images with an Orange'],
'sendFiles' => ['file' => $this->captchaImg],
]);
}

public function testBase64()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['base64' => '...'],
'sendParams' => ['method' => 'base64', 'coordinatescaptcha' => 1, 'body' => '...','soft_id' => '4585'],
'params' => [
'base64' => '...',
'hintText' => 'Select all images with an Orange',
],
'sendParams' => ['method' => 'base64', 'coordinatescaptcha' => 1, 'body' => '...','soft_id' => '4585', 'textinstructions' => 'Select all images with an Orange'],
'sendFiles' => [],
]);
}
Expand Down
Loading