Test Failed
Push — master ( 1211a5...b50906 )
by Taosikai
12:48
created

CredentialResolver::findQRSign()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the slince/smartqq package.
5
 *
6
 * (c) Slince <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Slince\SmartQQ;
13
14
use GuzzleHttp\Cookie\CookieJar;
15
use Slince\SmartQQ\Exception\RuntimeException;
16
17
class CredentialResolver
18
{
19
    /**
20
     * 客户端id(固定值).
21
     *
22
     * @var int
23
     */
24
    protected static $clientId = 53999199;
25
26
    /**
27
     * @var CookieJar
28
     */
29
    protected $cookies;
30
31
    /**
32
     * 获取ptwebqq的地址
33
     *
34
     * @var string
35
     */
36
    protected $certificationUrl;
37
38
    /**
39
     * @var Client
40
     */
41
    protected $client;
42
43
    public function __construct(Client $client)
44
    {
45
        $this->client = $client;
46
    }
47
48
    /**
49
     * 获取授权凭据.
50
     *
51
     * @param callable $qrCallback
52
     * @return Credential
53
     */
54
    public function resolve($qrCallback)
55
    {
56
        $this->cookies = new CookieJar();
57
58
        //获取二维码资源
59
        $response = $this->sendRequest(new Request\GetQrCodeRequest());
60
        $qrCallback((string)$response->getBody());
61
62
        //查找"qrsig"参数
63
        $qrSign = $this->findQRSign();
64
        //计算ptqrtoken
65
        $ptQrToken = Utils::hash33($qrSign);
66
67
        //验证状态
68
        while (true) {
69
            //查看二维码状态
70
            $status = $this->getQrCodeStatus($ptQrToken);
71
72
            // 认证成功
73
            if (Request\VerifyQrCodeRequest::STATUS_CERTIFICATION === $status) {
74
                //授权成功跳出状态检查
75
                break;
76
            } elseif (Request\VerifyQrCodeRequest::STATUS_EXPIRED == $status) {
77
                //查找"qrsig"参数
78
                $qrSign = $this->findQRSign($this->cookies);
0 ignored issues
show
Unused Code introduced by
The call to CredentialResolver::findQRSign() has too many arguments starting with $this->cookies.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
79
                //计算ptqrtoken
80
                $ptQrToken = Utils::hash33($qrSign);
81
            }
82
            //暂停1秒
83
            usleep(1000000);
84
        }
85
86
        $ptWebQQ = $this->getPtWebQQ();
87
        $vfWebQQ = $this->getVfWebQQ($ptWebQQ);
88
        list($uin, $pSessionId) = $this->getUinAndPSessionId($ptWebQQ);
89
90
        $credential = new Credential(
91
            $ptWebQQ,
92
            $vfWebQQ,
93
            $pSessionId,
94
            $uin,
95
            static::$clientId,
96
            $this->cookies
97
        );
98
99
        return $credential;
100
    }
101
102
    /**
103
     * 从cookie中查找 "qrsig" 参数
104
     *
105
     * @return string
106
     */
107
    protected function findQRSign()
108
    {
109
        foreach ($this->cookies as $cookie) {
110
            if (0 === strcasecmp($cookie->getName(), 'qrsig')) {
111
                return $cookie->getValue();
112
            }
113
        }
114
        throw new RuntimeException('Can not find parameter [qrsig]');
115
    }
116
117
    /**
118
     * 验证二维码状态
119
     *
120
     * @param int $ptQrToken qr token
121
     *
122
     * @return int
123
     */
124
    protected function getQrCodeStatus($ptQrToken)
125
    {
126
        $request = new Request\VerifyQrCodeRequest($ptQrToken);
127
        $response = $this->client->sendRequest($request);
128
        if (false !== strpos($response->getBody(), '未失效')) {
129
            $status = Request\VerifyQrCodeRequest::STATUS_UNEXPIRED;
130
        } elseif (false !== strpos($response->getBody(), '已失效')) {
131
            $status = Request\VerifyQrCodeRequest::STATUS_EXPIRED;
132
        } elseif (false !== strpos($response->getBody(), '认证中')) {
133
            $status = Request\VerifyQrCodeRequest::STATUS_ACCREDITATION;
134
        } else {
135
            $status = Request\VerifyQrCodeRequest::STATUS_CERTIFICATION;
136
            //找出认证url
137
            if (preg_match("#'(http.+)'#U", strval($response->getBody()), $matches)) {
138
                $this->certificationUrl = trim($matches[1]);
139
            } else {
140
                throw new RuntimeException('Can not find certification url');
141
            }
142
        }
143
144
        return $status;
145
    }
146
147
    /**
148
     * 获取ptwebqq的参数值
149
     *
150
     * @return string
151
     */
152
    protected function getPtWebQQ()
153
    {
154
        $request = new Request\GetPtWebQQRequest();
155
        $request->setUri($this->certificationUrl);
156
        $this->sendRequest($request);
157
        foreach ($this->cookies as $cookie) {
158
            if (0 === strcasecmp($cookie->getName(), 'ptwebqq')) {
159
                return $cookie->getValue();
160
            }
161
        }
162
        throw new RuntimeException('Can not find parameter [ptwebqq]');
163
    }
164
165
    /**
166
     * @param string $ptWebQQ
167
     *
168
     * @return string
169
     */
170
    protected function getVfWebQQ($ptWebQQ)
171
    {
172
        $request = new Request\GetVfWebQQRequest($ptWebQQ);
173
        $response = $this->sendRequest($request);
174
175
        return Request\GetVfWebQQRequest::parseResponse($response);
176
    }
177
178
    /**
179
     * 获取pessionid和uin.
180
     *
181
     * @param string $ptWebQQ
182
     *
183
     * @return array
184
     */
185
    protected function getUinAndPSessionId($ptWebQQ)
186
    {
187
        $request = new Request\GetUinAndPsessionidRequest([
188
            'ptwebqq' => $ptWebQQ,
189
            'clientid' => static::$clientId,
190
            'psessionid' => '',
191
            'status' => 'online',
192
        ]);
193
        $response = $this->sendRequest($request);
194
195
        return Request\GetUinAndPsessionidRequest::parseResponse($response);
196
    }
197
198
    protected function sendRequest(Request\RequestInterface $request)
199
    {
200
        return $this->client->sendRequest($request, [
201
            'cookies' => $this->cookies
202
        ]);
203
    }
204
}