This commit is contained in:
jie Ago 2022-11-05 23:51:39 +08:00
commit 39db30c13e
70 changed files with 4482 additions and 0 deletions

72
2captcha-php/.gitignore vendored Normal file
View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);

View 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
View 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>

View 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);
}
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace TwoCaptcha\Exception;
use Exception;
class ApiException extends Exception
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace TwoCaptcha\Exception;
use Exception;
class NetworkException extends Exception
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace TwoCaptcha\Exception;
use Exception;
class TimeoutException extends Exception
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace TwoCaptcha\Exception;
use Exception;
class ValidationException extends Exception
{
}

View 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);
}
}

View 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;
});

View 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);
}
}

View 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();
}
}

View 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' => [],
]);
}
}

View 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();
}
}

View 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' => [],
]);
}
}

View 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' => [],
]);
}
}

View 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();
}
}

View 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' => [],
]);
}
}

View 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' => [],
]);
}
}

View 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();
}
}

View 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' => [],
]);
}
}

View 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();
}
}

View 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' => [],
]);
}
}

View 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
View 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
View 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
View 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&amp;model=start&amp;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;
}