.
72
2captcha-php/.gitignore
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#PHP and development related
|
||||||
|
.idea
|
||||||
|
/vendor
|
||||||
|
|
||||||
|
# Mac OS General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# Linux possible garbage
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
228
2captcha-php/README.md
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
# PHP Module for 2Captcha API
|
||||||
|
The easiest way to quickly integrate [2Captcha] captcha solving service into your code to automate solving of any types of captcha.
|
||||||
|
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Composer](#composer)
|
||||||
|
- [Manual](#manual)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [Solve captcha](#solve-captcha)
|
||||||
|
- [Normal Captcha](#normal-captcha)
|
||||||
|
- [Text](#text-captcha)
|
||||||
|
- [ReCaptcha v2](#recaptcha-v2)
|
||||||
|
- [ReCaptcha v3](#recaptcha-v3)
|
||||||
|
- [FunCaptcha](#funcaptcha)
|
||||||
|
- [GeeTest](#geetest)
|
||||||
|
- [hCaptcha](#hcaptcha)
|
||||||
|
- [KeyCaptcha](#keycaptcha)
|
||||||
|
- [Capy](#capy)
|
||||||
|
- [Grid (ReCaptcha V2 Old Method)](#grid)
|
||||||
|
- [Canvas](#canvas)
|
||||||
|
- [ClickCaptcha](#clickcaptcha)
|
||||||
|
- [Rotate](#rotate)
|
||||||
|
- [Other methods](#other-methods)
|
||||||
|
- [send / getResult](#send--getresult)
|
||||||
|
- [balance](#balance)
|
||||||
|
- [report](#report)
|
||||||
|
- [Error handling](#error-handling)
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
This package can be installed via composer or manually
|
||||||
|
|
||||||
|
### Composer
|
||||||
|
```
|
||||||
|
composer require 2captcha/2captcha
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
Copy `src` directory to your project and then `require` autoloader (`src/autoloader.php`) where needed:
|
||||||
|
```php
|
||||||
|
require 'path/to/autoloader.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
`TwoCaptcha` instance can be created like this:
|
||||||
|
```php
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
```
|
||||||
|
Also there are few options that can be configured:
|
||||||
|
```php
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha([
|
||||||
|
'server' => 'http://rucaptcha.com',
|
||||||
|
'apiKey' => 'YOUR_API_KEY',
|
||||||
|
'softId' => 123,
|
||||||
|
'callback' => 'https://your.site/result-receiver',
|
||||||
|
'defaultTimeout' => 120,
|
||||||
|
'recaptchaTimeout' => 600,
|
||||||
|
'pollingInterval' => 10,
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### TwoCaptcha instance options
|
||||||
|
|
||||||
|
|Option|Default value|Description|
|
||||||
|
|---|---|---|
|
||||||
|
|softId|-|your software ID obtained after publishing in [2captcha sofware 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|
|
||||||
|
|
||||||
|
> **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.
|
||||||
|
To get the answer manually use [getResult method](#send--getresult)
|
||||||
|
|
||||||
|
## Solve captcha
|
||||||
|
When you submit any image-based captcha use can provide additional options to help 2captcha workers to solve it properly.
|
||||||
|
|
||||||
|
### Captcha options
|
||||||
|
|Option|Default Value|Description|
|
||||||
|
|---|---|---|
|
||||||
|
|numeric|0|Defines if captcha contains numeric or other symbols [see more info in the API docs][post options]|
|
||||||
|
|minLength|0|minimal answer lenght|
|
||||||
|
|maxLength|0|maximum answer length|
|
||||||
|
|phrase|0|defines if the answer contains multiple words or not|
|
||||||
|
|caseSensitive|0|defines if the answer is case sensitive|
|
||||||
|
|calc|0|defines captcha requires calculation|
|
||||||
|
|lang|-|defines the captcha language, see the [list of supported languages] |
|
||||||
|
|hintImg|-|an image with hint shown to workers with the captcha|
|
||||||
|
|hintText|-|hint or task text shown to workers with the captcha|
|
||||||
|
|
||||||
|
Below you can find basic examples for every captcha type. Check out [examples directory] to find more examples with all available options.
|
||||||
|
|
||||||
|
### Normal Captcha
|
||||||
|
To bypass a normal captcha (distorted text on image) use the following method. This method also can be used to recognize any text on the image.
|
||||||
|
```php
|
||||||
|
$result = $solver->normal('path/to/captcha.jpg');
|
||||||
|
```
|
||||||
|
### Text Captcha
|
||||||
|
This method can be used to bypass a captcha that requires to answer a question provided in clear text.
|
||||||
|
```php
|
||||||
|
$result = $solver->text('If tomorrow is Saturday, what day is today?');
|
||||||
|
```
|
||||||
|
### ReCaptcha v2
|
||||||
|
Use this method to solve ReCaptcha V2 and obtain a token to bypass the protection.
|
||||||
|
```php
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### ReCaptcha v3
|
||||||
|
This method provides ReCaptcha V3 solver and returns a token.
|
||||||
|
```php
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'version' => 'v3',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### FunCaptcha
|
||||||
|
FunCaptcha (Arkoselabs) solving method. Returns a token.
|
||||||
|
```php
|
||||||
|
$result = $solver->funcaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/funcaptcha',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### GeeTest
|
||||||
|
Method to solve GeeTest puzzle captcha. Returns a set of tokens as JSON.
|
||||||
|
```php
|
||||||
|
$result = $solver->geetest([
|
||||||
|
'gt' => 'f1ab2cdefa3456789012345b6c78d90e',
|
||||||
|
'challenge' => '12345678abc90123d45678ef90123a456b',
|
||||||
|
'url' => 'https://www.site.com/page/',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### hCaptcha
|
||||||
|
Use this method to solve hCaptcha challenge. Returns a token to bypass captcha.
|
||||||
|
```php
|
||||||
|
$result = $solver->hcaptcha([
|
||||||
|
'sitekey' => '10000000-ffff-ffff-ffff-000000000001',
|
||||||
|
'url' => 'https://www.site.com/page/',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### KeyCaptcha
|
||||||
|
Token-based method to solve KeyCaptcha.
|
||||||
|
```php
|
||||||
|
$result = $solver->keycaptcha([
|
||||||
|
's_s_c_user_id' => 10,
|
||||||
|
's_s_c_session_id' => '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
||||||
|
's_s_c_web_server_sign' => '9006dc725760858e4c0715b835472f22-pz-',
|
||||||
|
's_s_c_web_server_sign2' => '2ca3abe86d90c6142d5571db98af6714',
|
||||||
|
'url' => 'https://www.keycaptcha.ru/demo-magnetic/',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### Capy
|
||||||
|
Token-based method to bypass Capy puzzle captcha.
|
||||||
|
```php
|
||||||
|
$result = $solver->capy([
|
||||||
|
'sitekey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
||||||
|
'url' => 'http://mysite.com/',
|
||||||
|
'api_server' => 'https://jp.api.capy.me/',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
### Grid
|
||||||
|
Grid method is originally called Old ReCaptcha V2 method. The method can be used to bypass any type of captcha where you can apply a grid on image and need to click specific grid boxes. Returns numbers of boxes.
|
||||||
|
```php
|
||||||
|
$result = $solver->grid('path/to/captcha.jpg');
|
||||||
|
```
|
||||||
|
### Canvas
|
||||||
|
Canvas method can be used when you need to draw a line around an object on image. Returns a set of points' coordinates to draw a polygon.
|
||||||
|
```php
|
||||||
|
$result = $solver->canvas('path/to/captcha.jpg');
|
||||||
|
```
|
||||||
|
### ClickCaptcha
|
||||||
|
ClickCaptcha method returns coordinates of points on captcha image. Can be used if you need to click on particular points on the image.
|
||||||
|
```php
|
||||||
|
$result = $solver->coordinates('path/to/captcha.jpg');
|
||||||
|
```
|
||||||
|
### Rotate
|
||||||
|
This method can be used to solve a captcha that asks to rotate an object. Mostly used to bypass FunCaptcha. Returns the rotation angle.
|
||||||
|
```php
|
||||||
|
$result = $solver->rotate('path/to/captcha.jpg');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Other methods
|
||||||
|
|
||||||
|
### send / getResult
|
||||||
|
These methods can be used for manual captcha submission and answer polling.
|
||||||
|
```php
|
||||||
|
$id = $solver->send(['file' => 'path/to/captcha.jpg', ...]);
|
||||||
|
|
||||||
|
sleep(20);
|
||||||
|
|
||||||
|
$code = $solver->getResult($id);
|
||||||
|
```
|
||||||
|
### balance
|
||||||
|
Use this method to get your account's balance
|
||||||
|
```php
|
||||||
|
$balance = $solver->balance();
|
||||||
|
```
|
||||||
|
### report
|
||||||
|
Use this method to report good or bad captcha answer.
|
||||||
|
```php
|
||||||
|
$solver->report($id, true); // captcha solved correctly
|
||||||
|
$solver->report($id, false); // captcha solved incorrectly
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
If case of an error captch solver throws an exception. It's important to properly handle these cases. We recommend to use `try catch` to handle exceptions.
|
||||||
|
```php
|
||||||
|
try {
|
||||||
|
$result = $solver->text('If tomorrow is Saturday, what day is today?');
|
||||||
|
} catch (\TwoCaptcha\Exception\ValidationException $e) {
|
||||||
|
// invalid parameters passed
|
||||||
|
} catch (\TwoCaptcha\Exception\NetworkException $e) {
|
||||||
|
// network error occurred
|
||||||
|
} catch (\TwoCaptcha\Exception\ApiException $e) {
|
||||||
|
// api respond with error
|
||||||
|
} catch (\TwoCaptcha\Exception\TimeoutException $e) {
|
||||||
|
// captcha is not solved so far
|
||||||
|
}
|
||||||
|
```
|
||||||
|
[2Captcha]: https://2captcha.com/
|
||||||
|
[2captcha sofware catalog]: https://2captcha.com/software
|
||||||
|
[pingback settings]: https://2captcha.com/setting/pingback
|
||||||
|
[post options]: https://2captcha.com/2captcha-api#normal_post
|
||||||
|
[list of supported languages]: https://2captcha.com/2captcha-api#language
|
||||||
|
[examples directory]: /examples
|
48
2captcha-php/composer.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "2captcha/2captcha",
|
||||||
|
"description": "PHP package for easy integration with 2captcha API",
|
||||||
|
"keywords": [
|
||||||
|
"2captcha",
|
||||||
|
"captcha",
|
||||||
|
"recaptcha",
|
||||||
|
"funcaptcha",
|
||||||
|
"keycaptcha",
|
||||||
|
"geetest",
|
||||||
|
"anticaptcha",
|
||||||
|
"hcaptcha",
|
||||||
|
"recaptcha v2",
|
||||||
|
"recaptcha v3",
|
||||||
|
"bypass captcha",
|
||||||
|
"solve captcha",
|
||||||
|
"captcha solver",
|
||||||
|
"decaptcha",
|
||||||
|
"2captcha.com"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "2captcha",
|
||||||
|
"email": "info@2captcha.com",
|
||||||
|
"homepage": "https://2captcha.com/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6",
|
||||||
|
"ext-curl": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-fileinfo": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "8.5.*"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"TwoCaptcha\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"TwoCaptcha\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1561
2captcha-php/composer.lock
generated
Normal file
18
2captcha-php/examples/canvas.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->canvas([
|
||||||
|
'file' => __DIR__ . '/images/canvas.jpg',
|
||||||
|
'hintText' => 'Draw around apple',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/canvas_base64.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$image = __DIR__ . '/images/canvas.jpg';
|
||||||
|
$base64 = base64_encode(file_get_contents($image));
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->canvas(['base64' => $base64, 'hintText' => 'Draw around apple']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
22
2captcha-php/examples/canvas_options.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->canvas([
|
||||||
|
'file' => __DIR__ . '/images/canvas.jpg',
|
||||||
|
'previousId' => 0,
|
||||||
|
'canSkip' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => __DIR__ . '/images/canvas_hint.jpg',
|
||||||
|
'hintText' => 'Draw around apple',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
19
2captcha-php/examples/capy.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->capy([
|
||||||
|
'sitekey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
||||||
|
'url' => 'https://www.mysite.com/captcha/',
|
||||||
|
'api_server' => 'https://jp.api.capy.me/'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
23
2captcha-php/examples/capy_options.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->capy([
|
||||||
|
'sitekey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
||||||
|
'url' => 'http://mysite.com/',
|
||||||
|
'api_server' => 'https://jp.api.capy.me/',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
15
2captcha-php/examples/coordinates.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->coordinates(__DIR__ . '/images/grid.jpg');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/coordinates_base64.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$image = __DIR__ . '/images/grid.jpg';
|
||||||
|
$base64 = base64_encode(file_get_contents($image));
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->coordinates(['base64' => $base64]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
20
2captcha-php/examples/coordinates_options.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->coordinates([
|
||||||
|
'file' => __DIR__ . '/images/grid_2.jpg',
|
||||||
|
'lang' => 'en',
|
||||||
|
// 'hintImg' => __DIR__ . '/images/grid_hint.jpg'
|
||||||
|
'hintText' => 'Select all images with an Orange',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/funcaptcha.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->funcaptcha([
|
||||||
|
'sitekey' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'url' => 'https://mysite.com/page/with/funcaptcha',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
27
2captcha-php/examples/funcaptcha_options.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->funcaptcha([
|
||||||
|
'sitekey' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'url' => 'https://mysite.com/page/with/funcaptcha',
|
||||||
|
'surl' => 'https://client-api.arkoselabs.com',
|
||||||
|
'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
|
||||||
|
'data' => [
|
||||||
|
'anyKey' => 'anyStringValue',
|
||||||
|
],
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
28
2captcha-php/examples/geetest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
// 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_RETURNTRANSFER, 1);
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
$challenge = explode(";", $resp)[0];
|
||||||
|
|
||||||
|
// Then we are ready to make a call to 2captcha API
|
||||||
|
try {
|
||||||
|
$result = $solver->geetest([
|
||||||
|
'gt' => 'f2ae6cadcf7886856696502e1d55e00c',
|
||||||
|
'apiServer' => 'api-na.geetest.com',
|
||||||
|
'challenge' => $challenge,
|
||||||
|
'url' => 'https://mysite.com/captcha.html',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
30
2captcha-php/examples/geetest_options.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, "https://launches.endclothing.com/distil_r_captcha_challenge");
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
$challenge = explode(";", $resp)[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->geetest([
|
||||||
|
'gt' => 'f2ae6cadcf7886856696502e1d55e00c',
|
||||||
|
'apiServer' => 'api-na.geetest.com',
|
||||||
|
'challenge' => $challenge,
|
||||||
|
'url' => 'https://launches.endclothing.com/distil_r_captcha.html',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
15
2captcha-php/examples/grid.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->grid(__DIR__ . '/images/grid.jpg');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/grid_base64.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$image = __DIR__ . '/images/grid.jpg';
|
||||||
|
$base64 = base64_encode(file_get_contents($image));
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->grid(['base64' => $base64]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
24
2captcha-php/examples/grid_options.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->grid([
|
||||||
|
'file' => __DIR__ . '/images/grid_2.jpg',
|
||||||
|
'rows' => 3,
|
||||||
|
'cols' => 3,
|
||||||
|
'previousId' => 0,
|
||||||
|
'canSkip' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
// 'hintImg' => __DIR__ . '/images/grid_hint.jpg',
|
||||||
|
'hintText' => 'Select all images with an Orange',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/hcaptcha.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->hcaptcha([
|
||||||
|
'sitekey' => '10000000-ffff-ffff-ffff-000000000001',
|
||||||
|
'url' => 'https://www.site.com/page/',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
22
2captcha-php/examples/hcaptcha_options.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->hcaptcha([
|
||||||
|
'sitekey' => '10000000-ffff-ffff-ffff-000000000001',
|
||||||
|
'url' => 'https://www.site.com/page/',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
BIN
2captcha-php/examples/images/canvas.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
2captcha-php/examples/images/canvas_hint.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
2captcha-php/examples/images/grid.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
2captcha-php/examples/images/grid_2.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
2captcha-php/examples/images/grid_hint.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
2captcha-php/examples/images/normal.jpg
Normal file
After Width: | Height: | Size: 825 B |
BIN
2captcha-php/examples/images/normal_2.jpg
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
2captcha-php/examples/images/rotate.jpg
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
2captcha-php/examples/images/rotate_2.jpg
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
2captcha-php/examples/images/rotate_3.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
21
2captcha-php/examples/keycaptcha.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->keycaptcha([
|
||||||
|
's_s_c_user_id' => 10,
|
||||||
|
's_s_c_session_id' => '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
||||||
|
's_s_c_web_server_sign' => '9006dc725760858e4c0715b835472f22-pz-',
|
||||||
|
's_s_c_web_server_sign2' => '2ca3abe86d90c6142d5571db98af6714',
|
||||||
|
'url' => 'https://www.keycaptcha.ru/demo-magnetic/',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
25
2captcha-php/examples/keycaptcha_options.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result->code = $solver->keycaptcha([
|
||||||
|
's_s_c_user_id' => 10,
|
||||||
|
's_s_c_session_id' => '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
||||||
|
's_s_c_web_server_sign' => '9006dc725760858e4c0715b835472f22-pz-',
|
||||||
|
's_s_c_web_server_sign2' => '2ca3abe86d90c6142d5571db98af6714',
|
||||||
|
'url' => 'https://www.keycaptcha.ru/demo-magnetic/',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
15
2captcha-php/examples/normal.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->normal(__DIR__ . '/images/normal.jpg');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/normal_base64.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$image = __DIR__ . '/images/normal.jpg';
|
||||||
|
$base64 = base64_encode(file_get_contents($image));
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->normal(['base64' => $base64]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
26
2captcha-php/examples/normal_options.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->normal([
|
||||||
|
'file' => __DIR__ . '/images/normal_2.jpg',
|
||||||
|
'numeric' => 4,
|
||||||
|
'minLen' => 4,
|
||||||
|
'maxLen' => 20,
|
||||||
|
'phrase' => 1,
|
||||||
|
'caseSensitive' => 1,
|
||||||
|
'calc' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
// 'hintImg' => __DIR__ . '/images/normal_hint.jpg',
|
||||||
|
// 'hintText' => 'Type red symbols only',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/recaptcha_v2.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(610);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
27
2captcha-php/examples/recaptcha_v2_options.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(610);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha([
|
||||||
|
'apiKey' => 'YOUR_API_KEY',
|
||||||
|
'server' => 'http://rucaptcha.com'
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'invisible' => 1,
|
||||||
|
'action' => 'verify',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
19
2captcha-php/examples/recaptcha_v3.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(610);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'version' => 'v3',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
28
2captcha-php/examples/recaptcha_v3_options.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(610);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha([
|
||||||
|
'apiKey' => 'YOUR_API_KEY',
|
||||||
|
'server' => 'http://2captcha.com'
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->recaptcha([
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'version' => 'v3',
|
||||||
|
'action' => 'verify',
|
||||||
|
'score' => 0.3,
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'login:password@IP_address:PORT',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
15
2captcha-php/examples/rotate.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->rotate(__DIR__ . '/images/rotate.jpg');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
19
2captcha-php/examples/rotate_many.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->rotate([
|
||||||
|
__DIR__ . '/images/rotate.jpg',
|
||||||
|
__DIR__ . '/images/rotate_2.jpg',
|
||||||
|
__DIR__ . '/images/rotate_3.jpg',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
25
2captcha-php/examples/rotate_options.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->rotate([
|
||||||
|
'files' => [
|
||||||
|
__DIR__ . '/images/rotate.jpg',
|
||||||
|
__DIR__ . '/images/rotate_2.jpg',
|
||||||
|
__DIR__ . '/images/rotate_3.jpg',
|
||||||
|
],
|
||||||
|
'angle' => 40,
|
||||||
|
'lang' => 'en',
|
||||||
|
// 'hintImg' => __DIR__ . '/images/rotate_hint.jpg'
|
||||||
|
'hintText' => 'Put the images in the correct way up',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
15
2captcha-php/examples/text.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->text('If tomorrow is Saturday, what day is today?');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
18
2captcha-php/examples/text_options.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
set_time_limit(130);
|
||||||
|
|
||||||
|
require(__DIR__ . '/../src/autoloader.php');
|
||||||
|
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha('YOUR_API_KEY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->text([
|
||||||
|
'text' => 'If tomorrow is Saturday, what day is today?',
|
||||||
|
'lang' => 'en',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Captcha solved: ' . $result->code);
|
8
2captcha-php/phpunit.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<phpunit bootstrap="tests/autoloader.php">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="TwoCaptcha">
|
||||||
|
<directory>tests</directory>
|
||||||
|
<exclude>tests/autoloader.php</exclude>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
135
2captcha-php/src/ApiClient.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha;
|
||||||
|
|
||||||
|
use TwoCaptcha\Exception\ApiException;
|
||||||
|
use TwoCaptcha\Exception\NetworkException;
|
||||||
|
|
||||||
|
class ApiClient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* API server
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApiClient constructor.
|
||||||
|
* @param $options string
|
||||||
|
*/
|
||||||
|
public function __construct($options) {
|
||||||
|
if (is_string($options)) {
|
||||||
|
$this->server = $options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network client
|
||||||
|
*
|
||||||
|
* @resource
|
||||||
|
*/
|
||||||
|
private $curl;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends captcha to /in.php
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @param array $files
|
||||||
|
* @return bool|string
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
public function in($captcha, $files = [])
|
||||||
|
{
|
||||||
|
if (!$this->curl) $this->curl = curl_init();
|
||||||
|
|
||||||
|
foreach ($files as $key => $file) {
|
||||||
|
$captcha[$key] = $this->curlPrepareFile($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt_array($this->curl, [
|
||||||
|
CURLOPT_URL => $this->server . '/in.php',
|
||||||
|
CURLOPT_RETURNTRANSFER => 1,
|
||||||
|
CURLOPT_TIMEOUT => 60,
|
||||||
|
CURLOPT_POST => 1,
|
||||||
|
CURLOPT_POSTFIELDS => $captcha,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does request to /res.php
|
||||||
|
*
|
||||||
|
* @param $query
|
||||||
|
* @return bool|string
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
public function res($query)
|
||||||
|
{
|
||||||
|
if (!$this->curl) $this->curl = curl_init();
|
||||||
|
|
||||||
|
$url = $this->server . '/res.php';
|
||||||
|
|
||||||
|
if ($query) $url .= '?' . http_build_query($query);
|
||||||
|
|
||||||
|
curl_setopt_array($this->curl, [
|
||||||
|
CURLOPT_URL => $url,
|
||||||
|
CURLOPT_RETURNTRANSFER => 1,
|
||||||
|
CURLOPT_TIMEOUT => 60,
|
||||||
|
CURLOPT_POST => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes http request to api
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
private function execute()
|
||||||
|
{
|
||||||
|
$response = curl_exec($this->curl);
|
||||||
|
|
||||||
|
if (curl_errno($this->curl)) {
|
||||||
|
throw new NetworkException(curl_error($this->curl));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb_strpos($response, 'ERROR_') === 0) {
|
||||||
|
throw new ApiException($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different php versions have different approaches of sending files via CURL
|
||||||
|
*
|
||||||
|
* @param $file
|
||||||
|
* @return \CURLFile|string
|
||||||
|
*/
|
||||||
|
private function curlPrepareFile($file)
|
||||||
|
{
|
||||||
|
if (function_exists('curl_file_create')) { // php 5.5+
|
||||||
|
return curl_file_create($file, mime_content_type($file), 'file');
|
||||||
|
} else {
|
||||||
|
return '@' . realpath($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes active CURL resource if it was created
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this->curl) {
|
||||||
|
curl_close($this->curl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
2captcha-php/src/Exception/ApiException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ApiException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
10
2captcha-php/src/Exception/NetworkException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class NetworkException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
10
2captcha-php/src/Exception/TimeoutException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class TimeoutException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
10
2captcha-php/src/Exception/ValidationException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ValidationException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
718
2captcha-php/src/TwoCaptcha.php
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use TwoCaptcha\Exception\ApiException;
|
||||||
|
use TwoCaptcha\Exception\NetworkException;
|
||||||
|
use TwoCaptcha\Exception\TimeoutException;
|
||||||
|
use TwoCaptcha\Exception\ValidationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TwoCaptcha
|
||||||
|
* @package TwoCaptcha
|
||||||
|
*/
|
||||||
|
class TwoCaptcha
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* API KEY
|
||||||
|
*
|
||||||
|
* @string
|
||||||
|
*/
|
||||||
|
private $apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API server URL: http://2captcha.com (default) or http://rucaptcha.com
|
||||||
|
*
|
||||||
|
* @string
|
||||||
|
*/
|
||||||
|
private $server = 'http://2captcha.com';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of software developer. Developers who integrated their software
|
||||||
|
* with our service get reward: 10% of spendings of their software users.
|
||||||
|
*
|
||||||
|
* @integer
|
||||||
|
*/
|
||||||
|
private $softId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL to which the result will be sent
|
||||||
|
*
|
||||||
|
* @string
|
||||||
|
*/
|
||||||
|
private $callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long should wait for captcha result (in seconds)
|
||||||
|
*
|
||||||
|
* @integer
|
||||||
|
*/
|
||||||
|
private $defaultTimeout = 120;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long should wait for recaptcha result (in seconds)
|
||||||
|
*
|
||||||
|
* @integer
|
||||||
|
*/
|
||||||
|
private $recaptchaTimeout = 600;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How often do requests to `/res.php` should be made
|
||||||
|
* in order to check if a result is ready (in seconds)
|
||||||
|
*
|
||||||
|
* @integer
|
||||||
|
*/
|
||||||
|
private $pollingInterval = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helps to understand if there is need of waiting
|
||||||
|
* for result or not (because callback was used)
|
||||||
|
*
|
||||||
|
* @integer
|
||||||
|
*/
|
||||||
|
private $lastCaptchaHasCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network client
|
||||||
|
*
|
||||||
|
* @resource
|
||||||
|
*/
|
||||||
|
private $apiClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TwoCaptcha constructor.
|
||||||
|
* @param $options string|array
|
||||||
|
*/
|
||||||
|
public function __construct($options)
|
||||||
|
{
|
||||||
|
if (is_string($options)) {
|
||||||
|
$options = [
|
||||||
|
'apiKey' => $options,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($options['server'])) $this->server = $options['server'];
|
||||||
|
if (!empty($options['apiKey'])) $this->apiKey = $options['apiKey'];
|
||||||
|
if (!empty($options['softId'])) $this->softId = $options['softId'];
|
||||||
|
if (!empty($options['callback'])) $this->callback = $options['callback'];
|
||||||
|
if (!empty($options['defaultTimeout'])) $this->defaultTimeout = $options['defaultTimeout'];
|
||||||
|
if (!empty($options['recaptchaTimeout'])) $this->recaptchaTimeout = $options['recaptchaTimeout'];
|
||||||
|
if (!empty($options['pollingInterval'])) $this->pollingInterval = $options['pollingInterval'];
|
||||||
|
|
||||||
|
$this->apiClient = new ApiClient($this->server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHttpClient($apiClient)
|
||||||
|
{
|
||||||
|
$this->apiClient = $apiClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving normal captcha (image)
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function normal($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'file' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->requireFileOrBase64($captcha);
|
||||||
|
|
||||||
|
$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving text captcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function text($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'text' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$captcha['method'] = 'post';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving ReCaptcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function recaptcha($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'userrecaptcha';
|
||||||
|
|
||||||
|
return $this->solve($captcha, ['timeout' => $this->recaptchaTimeout]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving FunCaptcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function funcaptcha($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'funcaptcha';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving GeeTest
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function geetest($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'geetest';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving hCaptcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function hcaptcha($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'hcaptcha';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving KeyCaptcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function keycaptcha($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'keycaptcha';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving Capy captcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function capy($captcha)
|
||||||
|
{
|
||||||
|
$captcha['method'] = 'capy';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving grid captcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function grid($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'file' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->requireFileOrBase64($captcha);
|
||||||
|
|
||||||
|
$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving canvas captcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function canvas($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'file' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->requireFileOrBase64($captcha);
|
||||||
|
|
||||||
|
$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
|
||||||
|
$captcha['recaptcha']=1;
|
||||||
|
$captcha['canvas'] = 1;
|
||||||
|
|
||||||
|
if ( empty($captcha['hintText']) && empty($captcha['hintImg']) ) {
|
||||||
|
throw new ValidationException('At least one of parameters: hintText or hintImg required!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving coordinates captcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function coordinates($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'file' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->requireFileOrBase64($captcha);
|
||||||
|
|
||||||
|
$captcha['method'] = empty($captcha['base64']) ? 'post' : 'base64';
|
||||||
|
$captcha['coordinatescaptcha'] = 1;
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for solving RotateCaptcha
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function rotate($captcha)
|
||||||
|
{
|
||||||
|
if (is_string($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'file' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isArrayAssoc($captcha)) {
|
||||||
|
$captcha = [
|
||||||
|
'files' => $captcha,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($captcha['file'])) {
|
||||||
|
$captcha['files'] = [$captcha['file']];
|
||||||
|
unset($captcha['file']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->prepareFilesList($captcha);
|
||||||
|
|
||||||
|
$captcha['method'] = 'rotatecaptcha';
|
||||||
|
|
||||||
|
return $this->solve($captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends captcha to `/in.php` and waits for it's result.
|
||||||
|
* This helper can be used insted of manual using of `send` and `getResult` functions.
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @param array $waitOptions
|
||||||
|
* @return \stdClass
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function solve($captcha, $waitOptions = [])
|
||||||
|
{
|
||||||
|
$result = new \stdClass();
|
||||||
|
|
||||||
|
$result->captchaId = $this->send($captcha);
|
||||||
|
|
||||||
|
if ($this->lastCaptchaHasCallback) return $result;
|
||||||
|
|
||||||
|
$result->code = $this->waitForResult($result->captchaId, $waitOptions);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This helper waits for captcha result, and when result is ready, returns it
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @param array $waitOptions
|
||||||
|
* @return string|null
|
||||||
|
* @throws TimeoutException
|
||||||
|
*/
|
||||||
|
public function waitForResult($id, $waitOptions = [])
|
||||||
|
{
|
||||||
|
$startedAt = time();
|
||||||
|
|
||||||
|
$timeout = empty($waitOptions['timeout']) ? $this->defaultTimeout : $waitOptions['timeout'];
|
||||||
|
$pollingInterval = empty($waitOptions['pollingInterval']) ? $this->pollingInterval : $waitOptions['pollingInterval'];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (time() - $startedAt < $timeout) {
|
||||||
|
sleep($pollingInterval);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$code = $this->getResult($id);
|
||||||
|
if ($code) return $code;
|
||||||
|
} catch (NetworkException $e) {
|
||||||
|
// ignore network errors
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TimeoutException('Timeout ' . $timeout . ' seconds reached');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends captcha to '/in.php', and returns its `id`
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return string
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @return string|null
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
public function getResult($id)
|
||||||
|
{
|
||||||
|
$response = $this->res([
|
||||||
|
'action' => 'get',
|
||||||
|
'id' => $id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets account's balance
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
public function balance()
|
||||||
|
{
|
||||||
|
$response = $this->res('getbalance');
|
||||||
|
|
||||||
|
return floatval($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports if captcha was solved correctly (sends `reportbad` or `reportgood` to `/res.php`)
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @param $correct
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
public function report($id, $correct)
|
||||||
|
{
|
||||||
|
if ($correct) {
|
||||||
|
$this->res(['id' => $id, 'action' => 'reportgood']);
|
||||||
|
} else {
|
||||||
|
$this->res(['id' => $id, 'action' => 'reportbad']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes request to `/res.php`
|
||||||
|
*
|
||||||
|
* @param $query
|
||||||
|
* @return bool|string
|
||||||
|
* @throws ApiException
|
||||||
|
* @throws NetworkException
|
||||||
|
*/
|
||||||
|
private function res($query)
|
||||||
|
{
|
||||||
|
if (is_string($query)) {
|
||||||
|
$query = ['action' => $query];
|
||||||
|
}
|
||||||
|
|
||||||
|
$query['key'] = $this->apiKey;
|
||||||
|
|
||||||
|
return $this->apiClient->res($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches default parameters (passed in constructor) to request
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
*/
|
||||||
|
private function sendAttachDefaultParams(&$captcha)
|
||||||
|
{
|
||||||
|
$captcha['key'] = $this->apiKey;
|
||||||
|
|
||||||
|
if ($this->callback) {
|
||||||
|
if (!isset($captcha['callback'])) {
|
||||||
|
$captcha['callback'] = $this->callback;
|
||||||
|
} else if (!$captcha['callback']) {
|
||||||
|
unset($captcha['callback']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->lastCaptchaHasCallback = !empty($captcha['callback']);
|
||||||
|
|
||||||
|
if ($this->softId and !isset($captcha['softId'])) {
|
||||||
|
$captcha['softId'] = $this->softId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates if files parameters are correct
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @param string $key
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
private function requireFileOrBase64($captcha, $key = 'file')
|
||||||
|
{
|
||||||
|
if (!empty($captcha['base64'])) return;
|
||||||
|
|
||||||
|
if (empty($captcha[$key])) {
|
||||||
|
throw new ValidationException('File required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($captcha[$key])) {
|
||||||
|
throw new ValidationException('File not found (' . $captcha[$key] . ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns `files` parameter into `file_1`, `file_2`, `file_n` parameters
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
private function prepareFilesList(&$captcha)
|
||||||
|
{
|
||||||
|
$filesLimit = 9;
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach ($captcha['files'] as $file) {
|
||||||
|
if (++$i > $filesLimit) {
|
||||||
|
throw new ValidationException('Too many files (max: ' . $filesLimit . ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
throw new ValidationException('File not found (' . $file . ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
$captcha['file_' . $i] = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($captcha['files']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts files into separate array
|
||||||
|
*
|
||||||
|
* @param $captcha
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractFiles(&$captcha)
|
||||||
|
{
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
$fileKeys = ['file', 'hintImg'];
|
||||||
|
|
||||||
|
for ($i = 1; $i < 10; $i++) {
|
||||||
|
$fileKeys[] = 'file_' . $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($fileKeys as $key) {
|
||||||
|
if (!empty($captcha[$key]) and is_file($captcha[$key])) {
|
||||||
|
$files[$key] = $captcha[$key];
|
||||||
|
unset($captcha[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns passed parameters names into API-specific names
|
||||||
|
*
|
||||||
|
* @param $params
|
||||||
|
*/
|
||||||
|
private function mapParams(&$params, $method)
|
||||||
|
{
|
||||||
|
$map = $this->getParamsMap($method);
|
||||||
|
|
||||||
|
foreach ($map as $new => $old) {
|
||||||
|
if (isset($params[$new])) {
|
||||||
|
$params[$old] = $params[$new];
|
||||||
|
unset($params[$new]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($params['proxy'])) {
|
||||||
|
$proxy = $params['proxy'];
|
||||||
|
$params['proxy'] = $proxy['uri'];
|
||||||
|
$params['proxytype'] = $proxy['type'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains rules for `mapParams` method
|
||||||
|
*
|
||||||
|
* @param $method
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getParamsMap($method)
|
||||||
|
{
|
||||||
|
$commonMap = [
|
||||||
|
'base64' => 'body',
|
||||||
|
'caseSensitive' => 'regsense',
|
||||||
|
'minLen' => 'min_len',
|
||||||
|
'maxLen' => 'max_len',
|
||||||
|
'hintText' => 'textinstructions',
|
||||||
|
'hintImg' => 'imginstructions',
|
||||||
|
'url' => 'pageurl',
|
||||||
|
'score' => 'min_score',
|
||||||
|
'text' => 'textcaptcha',
|
||||||
|
'rows' => 'recaptcharows',
|
||||||
|
'cols' => 'recaptchacols',
|
||||||
|
'previousId' => 'previousID',
|
||||||
|
'canSkip' => 'can_no_answer',
|
||||||
|
'apiServer' => 'api_server',
|
||||||
|
'softId' => 'soft_id',
|
||||||
|
'callback' => 'pingback',
|
||||||
|
];
|
||||||
|
|
||||||
|
$methodMap = [
|
||||||
|
'userrecaptcha' => [
|
||||||
|
'sitekey' => 'googlekey',
|
||||||
|
],
|
||||||
|
'funcaptcha' => [
|
||||||
|
'sitekey' => 'publickey',
|
||||||
|
],
|
||||||
|
'capy' => [
|
||||||
|
'sitekey' => 'captchakey',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($methodMap[$method])) {
|
||||||
|
return array_merge($commonMap, $methodMap[$method]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $commonMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to determine if array is associative or not
|
||||||
|
*
|
||||||
|
* @param $arr
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isArrayAssoc($arr)
|
||||||
|
{
|
||||||
|
if (array() === $arr) return false;
|
||||||
|
return array_keys($arr) !== range(0, count($arr) - 1);
|
||||||
|
}
|
||||||
|
}
|
13
2captcha-php/src/autoloader.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
spl_autoload_register(function ($class) {
|
||||||
|
$prefix = 'TwoCaptcha\\';
|
||||||
|
|
||||||
|
$len = strlen($prefix);
|
||||||
|
if (strncmp($prefix, $class, $len) !== 0) return;
|
||||||
|
|
||||||
|
$relativeClass = substr($class, $len);
|
||||||
|
|
||||||
|
$file = __DIR__ . '/' . str_replace('\\', '/', $relativeClass) . '.php';
|
||||||
|
|
||||||
|
if (file_exists($file)) require $file;
|
||||||
|
});
|
93
2captcha-php/tests/AbstractWrapperTestCase.php
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
use TwoCaptcha\ApiClient;
|
||||||
|
use TwoCaptcha\Exception\ValidationException;
|
||||||
|
use TwoCaptcha\TwoCaptcha;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
abstract class AbstractWrapperTestCase extends TestCase
|
||||||
|
{
|
||||||
|
protected $method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sends captcha options through wrapper method,
|
||||||
|
* checks if correct parameters were passed to ApiClient
|
||||||
|
* and then checks if expected result were returned.
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
protected function checkIfCorrectParamsSendAndResultReturned($data)
|
||||||
|
{
|
||||||
|
$apiKey = 'API_KEY';
|
||||||
|
$captchaId = '123';
|
||||||
|
$code = '2763';
|
||||||
|
|
||||||
|
$apiClient = $this->createMock(ApiClient::class);
|
||||||
|
|
||||||
|
$data['sendParams']['key'] = $apiKey;
|
||||||
|
|
||||||
|
$apiClient
|
||||||
|
->expects($this->once())
|
||||||
|
->method('in')
|
||||||
|
->with(
|
||||||
|
$this->equalTo($data['sendParams']),
|
||||||
|
$this->equalTo($data['sendFiles'])
|
||||||
|
)
|
||||||
|
->willReturn('OK|' . $captchaId);
|
||||||
|
|
||||||
|
$apiClient
|
||||||
|
->expects($this->once())
|
||||||
|
->method('res')
|
||||||
|
->with($this->equalTo(['action' => 'get', 'id' => $captchaId, 'key' => $apiKey]))
|
||||||
|
->willReturn('OK|' . $code);
|
||||||
|
|
||||||
|
$solver = new TwoCaptcha([
|
||||||
|
'apiKey' => $apiKey,
|
||||||
|
'pollingInterval' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$solver->setHttpClient($apiClient);
|
||||||
|
|
||||||
|
$result = $solver->{$this->method}($data['params']);
|
||||||
|
|
||||||
|
$this->assertIsObject($result);
|
||||||
|
$this->assertObjectHasAttribute('code', $result);
|
||||||
|
$this->assertEquals($result->code, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass invalid file parameter to wrapper method
|
||||||
|
* in order to trigger ValidationException
|
||||||
|
*/
|
||||||
|
protected function checkIfExceptionThrownOnInvalidFile()
|
||||||
|
{
|
||||||
|
$this->expectException(ValidationException::class);
|
||||||
|
|
||||||
|
$solver = new TwoCaptcha('API_KEY');
|
||||||
|
|
||||||
|
$result = $solver->{$this->method}([
|
||||||
|
'file' => 'non-existent-file',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass invalid file parameter to wrapper method
|
||||||
|
* in order to trigger ValidationException
|
||||||
|
*/
|
||||||
|
protected function checkIfExceptionThrownOnTooManyFiles()
|
||||||
|
{
|
||||||
|
$this->expectException(ValidationException::class);
|
||||||
|
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$files[] = __DIR__ . '/../../examples/images/rotate.jpg';
|
||||||
|
}
|
||||||
|
|
||||||
|
$solver = new TwoCaptcha('API_KEY');
|
||||||
|
|
||||||
|
$result = $solver->{$this->method}($files);
|
||||||
|
}
|
||||||
|
}
|
78
2captcha-php/tests/CanvasTest.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class CanvasTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'canvas';
|
||||||
|
|
||||||
|
private $captchaImg = __DIR__ . '/../examples/images/canvas.jpg';
|
||||||
|
private $hintText = 'Draw around apple';
|
||||||
|
|
||||||
|
// public function testSingleFile()
|
||||||
|
// {
|
||||||
|
// $this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
// 'params' => $this->captchaImg,
|
||||||
|
// 'sendParams' => ['method' => 'post', 'canvas' => 1],
|
||||||
|
// 'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function testSingleFileParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['file' => $this->captchaImg, 'hintText' => $this->hintText],
|
||||||
|
'sendParams' => ['method' => 'post', 'canvas' => 1, 'recaptcha' => 1, 'textinstructions' => $this->hintText],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBase64()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['base64' => '...', 'hintText' => $this->hintText],
|
||||||
|
'sendParams' => ['method' => 'base64', 'canvas' => 1, 'body' => '...', 'recaptcha' => 1, 'textinstructions' => $this->hintText],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$hintImg = __DIR__ . '/../examples/images/canvas_hint.jpg';
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'previousId' => 0,
|
||||||
|
'canSkip' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => $hintImg,
|
||||||
|
'hintText' => $this->hintText,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'post',
|
||||||
|
'canvas' => 1,
|
||||||
|
'previousID' => 0,
|
||||||
|
'can_no_answer' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'recaptcha' => 1,
|
||||||
|
'textinstructions' => $this->hintText,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'imginstructions' => $hintImg,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalFileException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnInvalidFile();
|
||||||
|
}
|
||||||
|
}
|
28
2captcha-php/tests/CapyTest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class CapyTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'capy';
|
||||||
|
|
||||||
|
public function testAllOptions()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'sitekey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
||||||
|
'url' => 'http://mysite.com/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'capy',
|
||||||
|
'captchakey' => 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
||||||
|
'pageurl' => 'http://mysite.com/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
72
2captcha-php/tests/CoordinatesTest.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class CoordinatesTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'coordinates';
|
||||||
|
|
||||||
|
private $captchaImg = __DIR__ . '/../examples/images/grid.jpg';
|
||||||
|
|
||||||
|
public function testSingleFile()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $this->captchaImg,
|
||||||
|
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleFileParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['file' => $this->captchaImg],
|
||||||
|
'sendParams' => ['method' => 'post', 'coordinatescaptcha' => 1],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBase64()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['base64' => '...'],
|
||||||
|
'sendParams' => ['method' => 'base64', 'coordinatescaptcha' => 1, 'body' => '...'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$hintImg = __DIR__ . '/../examples/images/grid_hint.jpg';
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => $hintImg,
|
||||||
|
'hintText' => 'Select all images with an Orange',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'post',
|
||||||
|
'coordinatescaptcha' => 1,
|
||||||
|
'lang' => 'en',
|
||||||
|
'textinstructions' => 'Select all images with an Orange',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'imginstructions' => $hintImg,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalFileException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnInvalidFile();
|
||||||
|
}
|
||||||
|
}
|
38
2captcha-php/tests/FunCaptchaTest.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class FunCaptchaTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'funcaptcha';
|
||||||
|
|
||||||
|
public function testAllOptions()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'sitekey' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'url' => 'https://mysite.com/page/with/funcaptcha',
|
||||||
|
'surl' => 'https://client-api.arkoselabs.com',
|
||||||
|
'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
|
||||||
|
'data' => [
|
||||||
|
'anyKey' => 'anyStringValue',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'funcaptcha',
|
||||||
|
'publickey' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'pageurl' => 'https://mysite.com/page/with/funcaptcha',
|
||||||
|
'surl' => 'https://client-api.arkoselabs.com',
|
||||||
|
'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
|
||||||
|
'data' => [
|
||||||
|
'anyKey' => 'anyStringValue',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
32
2captcha-php/tests/GeeTest.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class GeeTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'geetest';
|
||||||
|
|
||||||
|
public function testAllOptions()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'gt' => 'f2ae6cadcf7886856696502e1d55e00c',
|
||||||
|
'apiServer' => 'api-na.geetest.com',
|
||||||
|
'challenge' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'url' => 'https://launches.endclothing.com/distil_r_captcha.html',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'geetest',
|
||||||
|
'gt' => 'f2ae6cadcf7886856696502e1d55e00c',
|
||||||
|
'api_server' => 'api-na.geetest.com',
|
||||||
|
'challenge' => '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC',
|
||||||
|
'pageurl' => 'https://launches.endclothing.com/distil_r_captcha.html',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
79
2captcha-php/tests/GridTest.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class GridTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'grid';
|
||||||
|
|
||||||
|
private $captchaImg = __DIR__ . '/../examples/images/grid.jpg';
|
||||||
|
|
||||||
|
public function testSingleFile()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $this->captchaImg,
|
||||||
|
'sendParams' => ['method' => 'post'],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleFileParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['file' => $this->captchaImg],
|
||||||
|
'sendParams' => ['method' => 'post'],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBase64()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['base64' => '...'],
|
||||||
|
'sendParams' => ['method' => 'base64', 'body' => '...'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$hintImg = __DIR__ . '/../examples/images/grid_hint.jpg';
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'rows' => 3,
|
||||||
|
'cols' => 3,
|
||||||
|
'previousId' => 0,
|
||||||
|
'canSkip' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => $hintImg,
|
||||||
|
'hintText' => 'Select all images with an Orange',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'post',
|
||||||
|
'recaptcharows' => 3,
|
||||||
|
'recaptchacols' => 3,
|
||||||
|
'previousID' => 0,
|
||||||
|
'can_no_answer' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'textinstructions' => 'Select all images with an Orange',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'imginstructions' => $hintImg,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalFileException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnInvalidFile();
|
||||||
|
}
|
||||||
|
}
|
28
2captcha-php/tests/HCaptchaTest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class HCaptchaTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'hcaptcha';
|
||||||
|
|
||||||
|
public function testAllOptions()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'sitekey' => 'f1ab2cdefa3456789012345b6c78d90e',
|
||||||
|
'url' => 'https://www.site.com/page/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'hcaptcha',
|
||||||
|
'sitekey' => 'f1ab2cdefa3456789012345b6c78d90e',
|
||||||
|
'pageurl' => 'https://www.site.com/page/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
34
2captcha-php/tests/KeyCaptchaTest.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class KeyCaptchaTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'keycaptcha';
|
||||||
|
|
||||||
|
public function testAllOptions()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
's_s_c_user_id' => 10,
|
||||||
|
's_s_c_session_id' => '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
||||||
|
's_s_c_web_server_sign' => '9006dc725760858e4c0715b835472f22-pz-',
|
||||||
|
's_s_c_web_server_sign2' => '2ca3abe86d90c6142d5571db98af6714',
|
||||||
|
'url' => 'https://www.keycaptcha.ru/demo-magnetic/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'keycaptcha',
|
||||||
|
's_s_c_user_id' => 10,
|
||||||
|
's_s_c_session_id' => '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
||||||
|
's_s_c_web_server_sign' => '9006dc725760858e4c0715b835472f22-pz-',
|
||||||
|
's_s_c_web_server_sign2' => '2ca3abe86d90c6142d5571db98af6714',
|
||||||
|
'pageurl' => 'https://www.keycaptcha.ru/demo-magnetic/',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
83
2captcha-php/tests/NormalTest.php
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class NormalTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'normal';
|
||||||
|
|
||||||
|
private $captchaImg = __DIR__ . '/../examples/images/normal.jpg';
|
||||||
|
|
||||||
|
public function testSingleFile()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $this->captchaImg,
|
||||||
|
'sendParams' => ['method' => 'post'],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleFileParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['file' => $this->captchaImg],
|
||||||
|
'sendParams' => ['method' => 'post'],
|
||||||
|
'sendFiles' => ['file' => $this->captchaImg],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBase64()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['base64' => '...'],
|
||||||
|
'sendParams' => ['method' => 'base64', 'body' => '...'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$hintImg = __DIR__ . '/../examples/images/grid_hint.jpg';
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'numeric' => 4,
|
||||||
|
'minLen' => 4,
|
||||||
|
'maxLen' => 20,
|
||||||
|
'phrase' => 1,
|
||||||
|
'caseSensitive' => 1,
|
||||||
|
'calc' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => $hintImg,
|
||||||
|
'hintText' => 'Type red symbols only',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'post',
|
||||||
|
'numeric' => 4,
|
||||||
|
'min_len' => 4,
|
||||||
|
'max_len' => 20,
|
||||||
|
'phrase' => 1,
|
||||||
|
'regsense' => 1,
|
||||||
|
'calc' => 0,
|
||||||
|
'lang' => 'en',
|
||||||
|
'textinstructions' => 'Type red symbols only',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file' => $this->captchaImg,
|
||||||
|
'imginstructions' => $hintImg,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalFileException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnInvalidFile();
|
||||||
|
}
|
||||||
|
}
|
64
2captcha-php/tests/ReCaptchaTest.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class ReCaptchaTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'recaptcha';
|
||||||
|
|
||||||
|
public function testV2()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'invisible' => 1,
|
||||||
|
'action' => 'verify',
|
||||||
|
'proxy' => [
|
||||||
|
'type' => 'HTTPS',
|
||||||
|
'uri' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'userrecaptcha',
|
||||||
|
'googlekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'pageurl' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'invisible' => 1,
|
||||||
|
'action' => 'verify',
|
||||||
|
'proxy' => 'username:str0ngP@$$W0rd@1.2.3.4:4321',
|
||||||
|
'proxytype' => 'HTTPS'
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testV3()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'sitekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'url' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'version' => 'v3',
|
||||||
|
'action' => 'verify',
|
||||||
|
'score' => 0.3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'userrecaptcha',
|
||||||
|
'googlekey' => '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
||||||
|
'pageurl' => 'https://mysite.com/page/with/recaptcha',
|
||||||
|
'version' => 'v3',
|
||||||
|
'action' => 'verify',
|
||||||
|
'min_score' => 0.3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
113
2captcha-php/tests/RotateTest.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class RotateTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'rotate';
|
||||||
|
|
||||||
|
private $img = __DIR__ . '/../examples/images/rotate.jpg';
|
||||||
|
private $img2 = __DIR__ . '/../examples/images/rotate_2.jpg';
|
||||||
|
private $img3 = __DIR__ . '/../examples/images/rotate_3.jpg';
|
||||||
|
|
||||||
|
public function testSingleFile()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $this->img,
|
||||||
|
'sendParams' => ['method' => 'rotatecaptcha'],
|
||||||
|
'sendFiles' => ['file_1' => $this->img],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleFileParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['file' => $this->img],
|
||||||
|
'sendParams' => ['method' => 'rotatecaptcha'],
|
||||||
|
'sendFiles' => ['file_1' => $this->img],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFilesList()
|
||||||
|
{
|
||||||
|
$files = [
|
||||||
|
$this->img,
|
||||||
|
$this->img2,
|
||||||
|
$this->img3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file_1' => $this->img,
|
||||||
|
'file_2' => $this->img2,
|
||||||
|
'file_3' => $this->img3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $files,
|
||||||
|
'sendParams' => ['method' => 'rotatecaptcha'],
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFilesListParameter()
|
||||||
|
{
|
||||||
|
$files = [
|
||||||
|
$this->img,
|
||||||
|
$this->img2,
|
||||||
|
$this->img3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file_1' => $this->img,
|
||||||
|
'file_2' => $this->img2,
|
||||||
|
'file_3' => $this->img3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['files' => $files],
|
||||||
|
'sendParams' => ['method' => 'rotatecaptcha'],
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$hintImg = __DIR__ . '/../examples/images/grid_hint.jpg';
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'file' => $this->img,
|
||||||
|
'angle' => 40,
|
||||||
|
'lang' => 'en',
|
||||||
|
'hintImg' => $hintImg,
|
||||||
|
'hintText' => 'Put the images in the correct way up',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendParams = [
|
||||||
|
'method' => 'rotatecaptcha',
|
||||||
|
'angle' => 40,
|
||||||
|
'lang' => 'en',
|
||||||
|
'textinstructions' => 'Put the images in the correct way up',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sendFiles = [
|
||||||
|
'file_1' => $this->img,
|
||||||
|
'imginstructions' => $hintImg,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => $params,
|
||||||
|
'sendParams' => $sendParams,
|
||||||
|
'sendFiles' => $sendFiles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidFileException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnInvalidFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTooManyFilesException()
|
||||||
|
{
|
||||||
|
$this->checkIfExceptionThrownOnTooManyFiles();
|
||||||
|
}
|
||||||
|
}
|
35
2captcha-php/tests/TextTest.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TwoCaptcha\Tests;
|
||||||
|
|
||||||
|
class TextTest extends AbstractWrapperTestCase
|
||||||
|
{
|
||||||
|
protected $method = 'text';
|
||||||
|
|
||||||
|
public function testSimpleText()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => 'Today is monday?',
|
||||||
|
'sendParams' => ['method' => 'post', 'textcaptcha' => 'Today is monday?'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTextParameter()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['text' => 'Today is monday?'],
|
||||||
|
'sendParams' => ['method' => 'post', 'textcaptcha' => 'Today is monday?'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllParameters()
|
||||||
|
{
|
||||||
|
$this->checkIfCorrectParamsSendAndResultReturned([
|
||||||
|
'params' => ['text' => 'Today is monday?', 'lang' => 'en'],
|
||||||
|
'sendParams' => ['method' => 'post', 'textcaptcha' => 'Today is monday?', 'lang' => 'en'],
|
||||||
|
'sendFiles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
14
2captcha-php/tests/autoloader.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
require(dirname(__FILE__).'/AbstractWrapperTestCase.php');
|
||||||
|
spl_autoload_register(function ($class) {
|
||||||
|
$prefix = 'TwoCaptcha\\';
|
||||||
|
|
||||||
|
$len = strlen($prefix);
|
||||||
|
if (strncmp($prefix, $class, $len) !== 0) return;
|
||||||
|
|
||||||
|
$relativeClass = substr($class, $len);
|
||||||
|
|
||||||
|
$file = __DIR__ . '/../src/' . str_replace('\\', '/', $relativeClass) . '.php';
|
||||||
|
|
||||||
|
if (file_exists($file)) require $file;
|
||||||
|
});
|
13
LICENSE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
14
README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# MCBBSAutoSignIn
|
||||||
|
MCBBS自动签到脚本
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
代码使用2Captcha服务来过极验验证
|
||||||
|
|
||||||
|
[网址](2captcha.com)
|
||||||
|
```
|
||||||
|
// 2Captcha的api_key,用于过极验验证
|
||||||
|
$api_key = "";
|
||||||
|
// mcbbs的cookie
|
||||||
|
$cookie = "";
|
||||||
|
```
|
||||||
|
api_key和cookie自行填入
|
199
Sign.php
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
<?php
|
||||||
|
set_time_limit(130);
|
||||||
|
require(__DIR__ . '/2captcha-php/src/autoloader.php');
|
||||||
|
|
||||||
|
// 2Captcha的api_key,用于过极验验证
|
||||||
|
$api_key = "";
|
||||||
|
// mcbbs的cookie
|
||||||
|
$cookie = "";
|
||||||
|
// server酱api_key
|
||||||
|
$key = "";
|
||||||
|
|
||||||
|
|
||||||
|
if(checkSignIn($cookie)){die();}
|
||||||
|
$chal = passGeeTest($api_key, $cookie);
|
||||||
|
if(!$chal){die();}
|
||||||
|
$res = signIn($cookie,"1","记上一笔,hold住我的快乐!",$chal);
|
||||||
|
if($res[0] = true){
|
||||||
|
sc_send("签到成功", $res[1], $key);
|
||||||
|
}else{
|
||||||
|
sc_send("签到失败", $res[1], $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function passGeeTest(string $api_key, string $cookie) : array|bool {
|
||||||
|
$solver = new \TwoCaptcha\TwoCaptcha($api_key);
|
||||||
|
// To bypass GeeTest first we need to get new challenge value
|
||||||
|
|
||||||
|
|
||||||
|
do{
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, 'https://www.mcbbs.net/plugin.php?id=geetest3&model=start&t=1667578418195');
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
|
||||||
|
|
||||||
|
$headers = array();
|
||||||
|
$headers[] = 'Authority: www.mcbbs.net';
|
||||||
|
$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9';
|
||||||
|
$headers[] = 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6';
|
||||||
|
$headers[] = 'Cache-Control: max-age=0';
|
||||||
|
$headers[] = 'Cookie: '.$cookie;
|
||||||
|
$headers[] = 'Sec-Ch-Ua: \"Microsoft Edge\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"';
|
||||||
|
$headers[] = 'Sec-Ch-Ua-Mobile: ?0';
|
||||||
|
$headers[] = 'Sec-Ch-Ua-Platform: \"Windows\"';
|
||||||
|
$headers[] = 'Sec-Fetch-Dest: document';
|
||||||
|
$headers[] = 'Sec-Fetch-Mode: navigate';
|
||||||
|
$headers[] = 'Sec-Fetch-Site: none';
|
||||||
|
$headers[] = 'Sec-Fetch-User: ?1';
|
||||||
|
$headers[] = 'Upgrade-Insecure-Requests: 1';
|
||||||
|
$headers[] = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26';
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
if (curl_errno($ch)) {
|
||||||
|
echo 'Error:' . curl_error($ch);
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
$data = json_decode($resp);
|
||||||
|
$challenge = $data->challenge;
|
||||||
|
// $challenge = explode(";", $resp)[0];
|
||||||
|
|
||||||
|
// Then we are ready to make a call to 2captcha API
|
||||||
|
$flag = 0;
|
||||||
|
$error = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $solver->geetest([
|
||||||
|
'gt' => 'c4c41e397ee921e9862d259da2a031c4',
|
||||||
|
'apiServer' => 'api.geetest.com',
|
||||||
|
'challenge' => $challenge,
|
||||||
|
'url' => 'https://www.mcbbs.net/plugin.php?id=dc_signin',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
print_r($e->getMessage());
|
||||||
|
$error = $e->getMessage();
|
||||||
|
$flag ++;
|
||||||
|
}
|
||||||
|
}while($flag < 10 && $error == "ERROR_CAPTCHA_UNSOLVABLE");
|
||||||
|
|
||||||
|
|
||||||
|
$data = json_decode($result->code,true);
|
||||||
|
return $data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFormHash(string $cookie) {
|
||||||
|
$data = get("https://www.mcbbs.net/home.php?mod=spacecp&inajax=1",$cookie);
|
||||||
|
preg_match("/<input type=\"hidden\" value=\"([a-z0-9]*?)\" name=\"formhash\" \/>/",$data,$match);
|
||||||
|
if(!isset($match[1])){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(string $url,string $cookie,array $header = null){
|
||||||
|
$c = curl_init();
|
||||||
|
curl_setopt($c,CURLOPT_URL,$url);
|
||||||
|
curl_setopt($c,CURLOPT_COOKIE,$cookie);
|
||||||
|
curl_setopt($c, CURLOPT_HEADER, 0);
|
||||||
|
curl_setopt($c,CURLOPT_SSL_VERIFYPEER,false);
|
||||||
|
curl_setopt($c,CURLOPT_RETURNTRANSFER,true);
|
||||||
|
curl_setopt($c,CURLOPT_HTTPHEADER, [
|
||||||
|
"Referer: https://www.mcbbs.net/plugin.php?id=dc_signin",
|
||||||
|
"Connection: closed",
|
||||||
|
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
||||||
|
]);
|
||||||
|
if(!is_null($header)) {
|
||||||
|
curl_setopt($c,CURLOPT_HTTPHEADER, $header);
|
||||||
|
}
|
||||||
|
$x = curl_exec($c);
|
||||||
|
curl_close($c);
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
function post(string $url,string $cookie, array $data,array $header = null) {
|
||||||
|
$c = curl_init();
|
||||||
|
curl_setopt($c,CURLOPT_URL,$url);
|
||||||
|
curl_setopt($c,CURLOPT_COOKIE,$cookie);
|
||||||
|
curl_setopt($c, CURLOPT_HEADER, 0);
|
||||||
|
curl_setopt($c,CURLOPT_SSL_VERIFYPEER,false);
|
||||||
|
curl_setopt($c,CURLOPT_RETURNTRANSFER,true);
|
||||||
|
curl_setopt($c, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($c,CURLOPT_HTTPHEADER, [
|
||||||
|
"Referer: https://www.mcbbs.net/plugin.php?id=dc_signin",
|
||||||
|
"Connection: closed",
|
||||||
|
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
||||||
|
]);
|
||||||
|
if(!is_null($header)) {
|
||||||
|
curl_setopt($c,CURLOPT_HTTPHEADER, $header);
|
||||||
|
}
|
||||||
|
curl_setopt($c, CURLOPT_POSTFIELDS, $data);
|
||||||
|
$x = curl_exec($c);
|
||||||
|
curl_close($c);
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSignIn (string $cookie) {
|
||||||
|
$signUrl = "https://www.mcbbs.net/plugin.php?id=dc_signin:sign&inajax=1";
|
||||||
|
$check = get($signUrl, $cookie);
|
||||||
|
if(!$check || preg_match("/您今日已经签过到/",$check)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function signIn(string $cookie, string $emote,string $content,array $chal) {
|
||||||
|
$signUrl = "https://www.mcbbs.net/plugin.php?id=dc_signin:sign&inajax=1";
|
||||||
|
$hash = getFormHash($cookie);
|
||||||
|
if(!$hash){return false;}
|
||||||
|
$result = post($signUrl, $cookie, [
|
||||||
|
"formhash" => $hash,
|
||||||
|
"signsubmit" => "yes",
|
||||||
|
"handlekey" => "signin",
|
||||||
|
"emotid" => $emote,
|
||||||
|
"referer" => "https://www.mcbbs.net/plugin.php?id=dc_signin",
|
||||||
|
"content" => $content,
|
||||||
|
"geetest_challenge" => $chal['geetest_challenge'],
|
||||||
|
"geetest_validate" => $chal['geetest_validate'],
|
||||||
|
"geetest_seccode" => $chal['geetest_seccode']
|
||||||
|
]);
|
||||||
|
if(!preg_match("/签到成功/",$result)){
|
||||||
|
echo $result.PHP_EOL;
|
||||||
|
$res1[] = false;
|
||||||
|
$res1[] = $result;
|
||||||
|
return $res1;
|
||||||
|
}
|
||||||
|
$res2[] = true;
|
||||||
|
$res2[] = $result;
|
||||||
|
return $res2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sc_send( $text , $desp = '' , $key = '[SENDKEY]' )
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'text' => $text,
|
||||||
|
'desp' => $desp
|
||||||
|
);
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, 'https://sctapi.ftqq.com/'.$key.'.send');
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||||
|
|
||||||
|
$headers = array();
|
||||||
|
$headers[] = 'Content-type: application/x-www-form-urlencoded';
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
if (curl_errno($ch)) {
|
||||||
|
echo 'Error:' . curl_error($ch);
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
return $resp;
|
||||||
|
}
|