在这里我觉得有必要讲为什么要选WebQQ作为接收和发送QQ消息的载体。首先QQ客户端不能用,一来直接从网络包里抓数据发现数据全是加密过后的,而且破不了;二来如果从QQ的聊天框里抓数据,想想就蛋疼。其次QQ提供了一些API,包括很多方面的如QQ空间,QQ微博,QQ群,唯独没有QQ消息的,我也曾经想过把Moonya搭在QQ群背后,但是觉得心里不舒服,所以也放弃了。接着还有个方法就是3GQQ,也就是手机上的网页QQ,不选这个是有私心的,因为别人都是iphone,android在线,我整个QQ手机在线,感觉也很蛋疼。最终选了WebQQ。

其实还有个原因是WebQQ研究的人多啊,可以借鉴前人的经验,下面着重讲一下WebQQ的整个登陆过程,不涉及源码,只讲理论过程。源码过些天我整理整理放到Github上,因为现在实在太乱了,代码框架自己也没想好,贴出来丢脸;此篇只讲登陆哦,登陆之后怎么获得消息,怎么一直保持在线以后再讲。

大家可以装上一个Firefox+Firebug,然后登陆自己的Webqq,对照着看比较有喜感,比较有收获,当然最好登陆两个不同的QQ,这样比对两次不同的登陆过程,可以看哪些是变的,哪些是不变的。登陆过程分下面几步:

Check
我们先向服务器索求验证码,以下面的url形式请求:

1
2
3
4
# uin是qq号
# appid是服务器应用的id吧(我也是瞎掰的)
# r是一个随机数,random.random()产生即可
https://ssl.ptlogin2.qq.com/check?uin=375365338&appid=1003903&r=0.4128782916521636

也许在你的firebug里看到的请求地址比我上面的要复杂好多,其实另外一些都是没什么用的,至少我按照上面的来弄最后成功了。这个时候服务器会返回类似下面这条信息的内容:

1
2
3
4
5
6
# 不需要关系这个ptui_checkVC是什么东西
# 如果返回的数字是0,那么表示我们不需要读取图片验证码,直接拿第二个参数当验证码即可
# 否则我们需要进一步请求服务器,获得验证图片已获得真正验证码
# 第三个参数也在后面的加密中有使用
ptui_checkVC('1','c930832eb62f541f88192f83ab3b1447c44af36a790893c1',
'\x00\x00\x00\x00\x02\x51\xb9\x3b');

GetImage
如果我们不需要读取图片获得验证码(即上一步中的返回值是0),那么请直接跳过这一步,否则慢慢看吧。我们向服务器请求图片,以下面的url:

1
2
3
4
# aid就是刚才的appid,还是不知道什么用,不过没有变就没错
# r依然是随机数
# uin还是qq号
https://ssl.captcha.qq.com/getimage?aid=1003903&r=0.43143656925179086&uin=38910267

上面请求到的图片你随便保存到哪,然后打开看看,看是什么验证码,然后记住这几个字符,应该是四个吧,下面有用。

Login
现在终于到了真正登陆的时刻了,按下面的方式请求:

1
2
3
4
5
6
7
8
9
10
11
# 这个参数实在太多了,不能忍了,本来我还想精简一下的,但是我发现我删了几个就无法工作,后来就一个都不删了
# 挑几个我们认识的说:
# u是qq号
# p是加密后的密码
# verifycode是验证码(就是图片上的那几个字符)
https://ssl.ptlogin2.qq.com/login?u=38910267&p=8C8601FEA1BA94FA6FEEBFEEAF98E86A
&verifycode=SCAZ&webqq_type=10&remember_uin=1&login2qq=1&aid=1003903
&u1=http%3A%2F%2Fweb.qq.com%2Floginproxy.html%3Flogin2qq%3D1%26webqq_type%3D10
&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert
&action=2-16-12690&mibao_css=m_webqq&t=1&g=1&js_type=0&js_ver=10031
&login_sig=TMleTJUYKLpddOBagYQnx5gu3s6irvQnaUX9z5vQPgCcUzrMqXEwaluWfllQa6o7

上面一步遇到了很大的问题,一是需要加一个refer的http header头,不知道为什么,二是密码的加密,这个我下一篇会结合获得朋友列表时的hash值计算一起讲解,所以现在忍忍吧。当然你也可以看下载过来的那个对应的js里的代码,理解一下…不要用别人的代码,因为这个东西似乎老是在变,还是按着最新的js来比较靠谱…

假设我们应该请求成功了,那么我们可以拿到服务器发过来的cookie,从里面拿到我们ptwebqq(这个等会需要再发到服务器完成登陆)和uin(这个东西后面有用,其实就是o0038910267),但是登陆过程没有用了。

Login2
把刚才获得的ptwebqq再次发到服务器,通过下面的url请求:

1
2
3
4
5
6
7
8
9
# 但是这个是个post请求,所以需要额外加参数进去
http://d.web2.qq.com/channel/login2
# 参数如下:
# 看参数一头雾水是正常的,其实很多都是你认识的,比如%7B是{,%22是“
# 但是不能把{,“直接放进去,因为这是要放在http传的!
r=%7B%22status%22%3A%22online%22%2C%22
ptwebqq%22%3A%22ea14c01367a9c4476a09e01d3483cd1cdb5a76157e269bdcdea345accfc13063
%22%2C%22passwd_sig%22%3A%22%22%2C%22clientid%22%3A%225556011
%22%2C%22psessionid%22%3Anull%7D&clientid=5556011&psessionid=null

请求之后会得到一个json数组,如果里面的retcode是0的话,就表示你成功登陆了。这个时候别人看你的qq就是webQQ在线啦!!!