Commit 36830edf by hanccc

增加登录方法

1 parent 174552dd
......@@ -9,7 +9,11 @@
}
],
"require": {
"guzzlehttp/guzzle": "^6.2"
"guzzlehttp/guzzle": "^6.2",
"querypath/QueryPath": "^3.0",
"symfony/dom-crawler": "^3.2",
"endroid/qrcode": "^1.7",
"symfony/css-selector": "^3.2"
},
"autoload": {
"psr-4": {
......
......@@ -9,24 +9,73 @@
namespace Hanson\Robot;
use Endroid\QrCode\QrCode;
use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;
class Robot
{
private $client;
public $tmpPath;
private $uuid;
private $baseUri;
private $baseUri = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin';
private $baseHost;
private $baseHost = 'wx2.qq.com';
private $redirectUri;
public function __construct()
private $skey;
private $sid;
private $uin;
private $passTicket;
private $deviceId;
private $baseRequest;
public function __construct(Array $option = [])
{
$this->client = new Client();
$this->handleOption($option);
}
/**
* 处理option
*
* @param $option
*/
private function handleOption($option)
{
$this->tmpPath = $option['tmp'] ?? sys_get_temp_dir();
}
public function run()
{
$this->getUuid();
$this->generateQrCode();
$this->log('[INFO] 请用微信扫码');
if($this->waitForLogin() !== 200){
die('[ERROR] 微信登录失败');
}
if(!$this->login()){
die('[ERROR] 登录失败');
}
$this->log('[INFO] 登录成功');
$this->init();
}
/**
......@@ -53,6 +102,115 @@ class Robot
$this->uuid = $matches[2];
}
/**
* 生成登录二维码
*/
public function generateQrCode()
{
$url = 'https://login.weixin.qq.com/l/' . $this->uuid;
$qrCode = new QrCode($url);
$file = $this->tmpPath . 'login_qr_code.png';
$qrCode->save($file);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
system($file);
}
}
/**
* 等待登录
*
* @return int
*/
public function waitForLogin(): int
{
$urlTemplate = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s';
$retryTime = 10;
$tip = 1;
$code = 0;
while($retryTime > 0){
$url = sprintf($urlTemplate, $tip, $this->uuid, time());
$content = $this->client->get($url)->getBody()->getContents();
preg_match('/window.code=(\d+);/', $content, $matches);
$code = $matches[1];
switch($code){
case '201':
$this->log('[INFO] 请点击确认进行登录');
$tip = 0;
break;
case '200':
preg_match('/window.redirect_uri="(\S+?)";/', $content, $matches);
$this->redirectUri = $matches[1] . '&fun=new';
return $code;
case '408':
$this->log('[ERROR] 微信登录超时。将在 1 秒后重试');
$tip = 1;
$retryTime -= 1;
sleep(1);
break;
default:
$this->log('[ERROR] 微信登录异常。异常码:%s 。1 秒后重试', $code);
$tip = 1;
$retryTime -= 1;
sleep(1);
break;
}
}
return $code;
}
public function login()
{
$content = $this->client->get($this->redirectUri)->getBody()->getContents();
$crawler = new Crawler($content);
$this->skey = $crawler->filter('error skey')->text();
$this->sid = $crawler->filter('error wxsid')->text();
$this->uin = $crawler->filter('error wxuin')->text();
$this->passTicket = $crawler->filter('error pass_ticket')->text();
if(in_array('', [$this->skey, $this->sid, $this->uin, $this->passTicket])){
return false;
}
$this->deviceId = 'e' . strval(random_int(100000000000000, 999999999999999));
$this->baseRequest = [
'Uin' => $this->uin,
'Sid' => $this->sid,
'Skey' => $this->skey,
'DeviceID' => $this->deviceId
];
return true;
}
public function init()
{
$url = sprintf($this->baseUri . '/webwxinit?r=%i&lang=en_US&pass_ticket=%s', time(), $this->passTicket);
$content = $this->client->post($url, [
'query' => [
'BaseRequest' => json_encode($this->baseRequest)
]
])->getBody()->getContents();
print_r($content);
}
private function log($msg, ...$args)
{
echo sprintf($msg . PHP_EOL, $args);
}
public function __get($value)
{
return $this->$value;
......
......@@ -8,6 +8,7 @@
require_once __DIR__ . './../vendor/autoload.php';
$robot = new \Hanson\Robot\Robot();
$robot->getUuid();
echo $robot->uuid;
\ No newline at end of file
$robot = new \Hanson\Robot\Robot(['tmp' => realpath('./tmp') . '/']);
echo $robot->run();
echo 'finish';
//echo $robot->uuid;
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!