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
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,20 @@ $solver = new \TwoCaptcha\TwoCaptcha([
'defaultTimeout' => 120,
'recaptchaTimeout' => 600,
'pollingInterval' => 10,
'json' => 1,
]);
```

### TwoCaptcha instance options

| Option | Default value | Description |
| ---------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| softId | 4585 | your software ID obtained after publishing in [2captcha software catalog] |
| softId | 4585 | your software ID obtained after publishing in [2captcha software catalog] |
| callback | - | URL of your web-sever that receives the captcha recognition result. The URl should be first registered in [pingback settings] of your account |
| defaultTimeout | 120 | Polling timeout in seconds for all captcha types except reCAPTCHA. Defines how long the module tries to get the answer from `res.php` API endpoint |
| recaptchaTimeout | 600 | Polling timeout for reCAPTCHA in seconds. Defines how long the module tries to get the answer from `res.php` API endpoint |
| pollingInterval | 10 | Interval in seconds between requests to `res.php` API endpoint, setting values less than 5 seconds is not recommended |
| json | 0 | Json or String format response from `res.php` API endpoint, json = 1 returns JSON format response |

> [!IMPORTANT]
> Once `callback` is defined for `TwoCaptcha` instance, all methods return only the captcha ID and DO NOT poll the API to get the result. The result will be sent to the callback URL.
Expand Down Expand Up @@ -444,6 +446,18 @@ $result = $solver->cybersiara([
]);
```

### hCaptcha

<sup>[API method description.](https://2captcha.com/2captcha-api#hCaptcha)</sup>

Use this method to bypass hCaptcha.

```php
$result = $solver->hcaptcha([
'sitekey' => 'c0421d06-b92e-47fc-ab9a-5caa43c04538',
'url' => 'https://api.solvecaptcha.com/demo/hcaptcha'
]);
```

## Other methods

Expand Down
22 changes: 22 additions & 0 deletions examples/h_captcha.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

set_time_limit(130);

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

$solver = new \TwoCaptcha\TwoCaptcha([
'apiKey' => 'YOUR_API_KEY',
'server' => 'http://2captcha.com',
'json' => 1
]);

try {
$result = $solver->hcaptcha([
'sitekey' => 'c0421d06-b92e-47fc-ab9a-5caa43c04538',
'url' => 'https://api.solvecaptcha.com/demo/hcaptcha'
]);
} catch (\Exception $e) {
die($e->getMessage());
}

die('Captcha solved: ' . $result->code);
5 changes: 3 additions & 2 deletions src/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class ApiClient
* ApiClient constructor.
* @param $options string
*/
public function __construct($options) {
public function __construct($options)
{
if (is_string($options)) {
$this->server = $options;
}
Expand Down Expand Up @@ -101,7 +102,7 @@ private function execute()
throw new NetworkException(curl_error($this->curl));
}

if (mb_strpos($response, 'ERROR_') === 0) {
if (strpos(json_encode($response), 'ERROR_') !== false) {
throw new ApiException($response);
}

Expand Down
84 changes: 73 additions & 11 deletions src/TwoCaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ class TwoCaptcha
*/
private $apiClient;


/**
* JSON response
*/
private $json = 0;

/**
* TwoCaptcha constructor.
* @param $options string|array
Expand All @@ -99,6 +105,7 @@ public function __construct($options)
if (!empty($options['defaultTimeout'])) $this->defaultTimeout = $options['defaultTimeout'];
if (!empty($options['recaptchaTimeout'])) $this->recaptchaTimeout = $options['recaptchaTimeout'];
if (!empty($options['pollingInterval'])) $this->pollingInterval = $options['pollingInterval'];
if (!empty($options['json'])) $this->json = $options['json'];

$this->apiClient = new ApiClient($this->server);
}
Expand Down Expand Up @@ -494,10 +501,10 @@ public function canvas($captcha)
$this->requireFileOrBase64($captcha);

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

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

Expand Down Expand Up @@ -540,7 +547,8 @@ public function coordinates($captcha)
* @throws TimeoutException
* @throws ValidationException
*/
public function audio($captcha){
public function audio($captcha)
{
if (is_string($captcha)) {
if (!file_exists($captcha)) {
throw new ValidationException('File not found (' . $captcha . ')');
Expand Down Expand Up @@ -681,13 +689,48 @@ public function send($captcha)

$response = $this->apiClient->in($captcha, $files);

$jsonObj = json_decode($response, true);

if (json_last_error() === JSON_ERROR_NONE) {
$request = $jsonObj['request'];
$status = $jsonObj['status'];

if ($request == "CAPCHA_NOT_READY") {
return null;
}

if ($status == 1) {
return $request;
}
} else {

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

return mb_substr($response, 3);
}
}

/* victor todo: remove
public function send($captcha)
{
$this->sendAttachDefaultParams($captcha);

$files = $this->extractFiles($captcha);

$this->mapParams($captcha, $captcha['method']);
$this->mapParams($files, $captcha['method']);

$response = $this->apiClient->in($captcha, $files);

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

return mb_substr($response, 3);
}

*/
/**
* Returns result of captcha if it was solved or `null`, if result is not ready
*
Expand All @@ -701,17 +744,35 @@ public function getResult($id)
$response = $this->res([
'action' => 'get',
'id' => $id,
'json' => $this->json,
]);

if ($response == 'CAPCHA_NOT_READY') {
return null;
}
$jsonObj = json_decode($response, true);

if (mb_strpos($response, 'OK|') !== 0) {
throw new ApiException('Cannot recognise api response (' . $response . ')');
}
if (json_last_error() === JSON_ERROR_NONE) {
$request = $jsonObj['request'];
$status = $jsonObj['status'];

return mb_substr($response, 3);

if ($request == "CAPCHA_NOT_READY") {
return null;
}

if ($status == 1) {
return $response;
}
} else {

if ($response == 'CAPCHA_NOT_READY') {
return null;
}

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

return mb_substr($response, 3);
}
}

/**
Expand Down Expand Up @@ -772,6 +833,7 @@ private function res($query)
private function sendAttachDefaultParams(&$captcha)
{
$captcha['key'] = $this->apiKey;
$captcha['json'] = $this->json;

if ($this->callback) {
if (!isset($captcha['callback'])) {
Expand Down
3 changes: 2 additions & 1 deletion tests/AbstractWrapperTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protected function checkIfCorrectParamsSendAndResultReturned($data)
$apiKey = 'API_KEY';
$captchaId = '123';
$code = '2763';
$json = '0';

$apiClient = $this->createMock(ApiClient::class);

Expand All @@ -40,7 +41,7 @@ protected function checkIfCorrectParamsSendAndResultReturned($data)
$apiClient
->expects($this->once())
->method('res')
->with($this->equalTo(['action' => 'get', 'id' => $captchaId, 'key' => $apiKey]))
->with($this->equalTo(['action' => 'get', 'id' => $captchaId, 'key' => $apiKey, 'json' => $json]))
->willReturn('OK|' . $code);

$solver = new TwoCaptcha([
Expand Down
1 change: 1 addition & 0 deletions tests/AmazonWafTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/AtbCaptchaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
2 changes: 2 additions & 0 deletions tests/AudioTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function test()
'method' => 'audio',
'body' => base64_encode(file_get_contents($audio)),
'soft_id' => '4585',
'json' => '0'
];


Expand All @@ -47,6 +48,7 @@ public function testAllParameters()
'body' => base64_encode(file_get_contents($audio)),
'lang' => 'ru',
'soft_id' => '4585',
'json' => '0'
];


Expand Down
5 changes: 3 additions & 2 deletions tests/CanvasTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function testSingleFileParameter()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['file' => $this->captchaImg, 'hintText' => $this->hintText],
'sendParams' => ['method' => 'post', 'canvas' => 1, 'recaptcha' => 1, 'textinstructions' => $this->hintText, 'soft_id' => '4585'],
'sendParams' => ['method' => 'post', 'canvas' => 1, 'recaptcha' => 1, 'textinstructions' => $this->hintText, 'soft_id' => '4585', 'json' => '0'],
'sendFiles' => ['file' => $this->captchaImg],
]);
}
Expand All @@ -31,7 +31,7 @@ public function testBase64()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['base64' => '...', 'hintText' => $this->hintText],
'sendParams' => ['method' => 'base64', 'canvas' => 1, 'body' => '...', 'recaptcha' => 1, 'textinstructions' => $this->hintText, 'soft_id' => '4585'],
'sendParams' => ['method' => 'base64', 'canvas' => 1, 'body' => '...', 'recaptcha' => 1, 'textinstructions' => $this->hintText, 'soft_id' => '4585', 'json' => '0'],
'sendFiles' => [],
]);
}
Expand All @@ -58,6 +58,7 @@ public function testAllParameters()
'recaptcha' => 1,
'textinstructions' => $this->hintText,
'soft_id' => '4585',
'json' => '0'
];

$sendFiles = [
Expand Down
1 change: 1 addition & 0 deletions tests/CapyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function testAllOptions()
'captchakey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
'pageurl' => 'http://mysite.com/',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
7 changes: 4 additions & 3 deletions tests/CoordinatesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function testSingleFile()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => $this->captchaImg,
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1, 'soft_id' => '4585'],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1, 'soft_id' => '4585', 'json' => '0'],
'sendFiles' => ['file' => $this->captchaImg],
]);
}
Expand All @@ -21,7 +21,7 @@ public function testSingleFileParameter()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['file' => $this->captchaImg],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1,'soft_id' => '4585'],
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1,'soft_id' => '4585', 'json' => '0'],
'sendFiles' => ['file' => $this->captchaImg],
]);
}
Expand All @@ -30,7 +30,7 @@ public function testBase64()
{
$this->checkIfCorrectParamsSendAndResultReturned([
'params' => ['base64' => '...'],
'sendParams' => ['method' => 'base64', 'coordinatescaptcha' => 1, 'body' => '...','soft_id' => '4585'],
'sendParams' => ['method' => 'base64', 'coordinatescaptcha' => 1, 'body' => '...','soft_id' => '4585', 'json' => '0'],
'sendFiles' => [],
]);
}
Expand All @@ -52,6 +52,7 @@ public function testAllParameters()
'lang' => 'en',
'textinstructions' => 'Select all images with an Orange',
'soft_id' => '4585',
'json' => '0'
];

$sendFiles = [
Expand Down
1 change: 1 addition & 0 deletions tests/CutcaptchaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/CyberSiaraTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/DatadomeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/FriendlyCaptchaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/FunCaptchaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
1 change: 1 addition & 0 deletions tests/GeeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function testAllOptions()
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
'proxytype' => 'HTTPS',
'soft_id' => '4585',
'json' => '0'
];

$this->checkIfCorrectParamsSendAndResultReturned([
Expand Down
Loading