|
作者:Hackfan # N2 z1 O8 Z/ p* M* {" ?
日期:2005.8.21凌晨
- e* c3 _: e& {# d" U联系:QQ:106814 Email:hackfan@vip.sina.com 3 C5 y+ I5 _ J+ }( @
+ a4 x& t; v5 H# o1 t1、研究说明 " `8 z" W9 U0 `. e% l+ m8 N) T
! A( S3 I2 T3 V. O3 Z) P) } Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 / I# l( N0 C; Y6 N1 _, h7 y" q
/ u+ s" i. X9 v- h: `4 Z: b
目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 . C0 A$ ^! Z# Z& N1 J) P
! Y' m# @7 ]) P4 V: a0 i
2、接口说明: & z# g4 X* r/ d" b/ `
, ^% }( d! G7 }- Z
接口位置:tqq.tencent.com:8000
& Z) s0 |" L) [' y1 X9 d 通信协议:HTTP
5 |1 a, H0 s" Z; R 数据传输方法:POST * p/ J; ~' N1 l, ^& g2 p
HTTP请求格式: - k# y. e: N5 E2 r; q4 ~" ]
& L5 C/ R0 j4 U8 G/ ^" n3 |& w( m
POST HTTP/1.1
) _' R7 n3 y* N+ WHost: tqq.tencent.com:8000
- z0 d! _+ ^% W5 t1 pContent-Type: text/plain; charset=UTF-8 $ P- \* `2 b" g
Content-length: 长度
$ o. Q: W5 P* g: p' }( J. nConnection: close
$ u% U' V: f0 X- [; Y( t& Q% x
: c$ z) v5 U. h" l9 ~1 r2 d数据
^) b5 i+ ]# P% v
5 u0 [$ U t0 p$ _ 其中长度为 数据 的长度,数据的格式:
8 ?6 I: c+ t# H8 s* y7 @; r VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... / k2 I0 Q' f0 Z+ ~- k& O
) G. a' d6 a4 U3 {! N
以上4个参数是每个请求都必有的。其中,VER表示协议的版本,目前为1.1,据说1.2已经出来了,这个乱写的话,服务器返回NULL; CMD为操作的指令,有Login、List、Query_Stat、GetInfo、AddToList、Ack_AddToList、 DelFromList、Change_Stat、GetMsgEx、CLTMSG、Logout;SEQ为当前请求的标记,防止重复发送,可以用当前时间,也可以用随机数;UIN是当前执行操作的QQ号。不过不同的CMD还需要不同的参数,下面我就公布我的研究成果。
: _- g" @0 F5 r3 K
) X5 \/ T9 y+ P3、研究方法: @6 {) }- ?/ ]7 V8 _1 d2 O" R
* t7 O0 ]* r5 ]. ^% i' {9 y 我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 b! S! T9 |$ J1 P( S0 V
下面我公布我探测的代码(PHP):- <? 8 T& g( X8 c' ]; T! S3 c
- $uin = "QQ号"; 8 J9 v6 _8 P' X' H+ p
- $pwd = md5("QQ密码");
1 I" y2 g) N+ [' v - ; N, R% t) h0 H& w# e* _
- //登陆测试
; V( g9 p8 u" ^) H3 c1 N - $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; + t0 h8 h! l @: [' D. }3 O/ A
- //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 7 a# k7 D, y# `, S0 W
- /******* # q5 \, P) w2 q7 d& ^' W7 @
- $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; 2 o" c/ w! G- }, h! P
- $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
$ a1 v0 N# e& s; k) H - $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
) p- N6 u9 I7 b1 _/ V2 O - $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
% f" K P# a! U, |( ~8 o - $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
' j7 @1 Z. H. Z1 C- p- n9 z - $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; t7 c2 n+ E7 [
- *******/ 2 m; w5 V/ |6 X# |) [4 y
- 2 U! e5 ~/ }& k9 b
- 8 P# }" f% s' \, x% _0 `" S7 U
- //得到好友列表
# s; E- }; p3 u6 h - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; 5 ^3 j# v4 ]! o
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; % a. \/ Q Z7 j) l: a* `7 A' g
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
Z( S9 m0 X* }2 e0 Q - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
; K! x9 A$ f3 ^ - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); * t9 ?* W9 i' n, q; e- c( U
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; " ^' u, c, ?8 d2 |% \6 R3 M
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
' ]& y4 P- N9 Y" o6 k# y* n - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; + }9 s* {. }/ a; ^, o4 |
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 9 @" [# y+ y1 R3 K8 e
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
0 Q2 _. r* B# H, T6 R e, O - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
6 o! f0 K2 e* B: L; }" l - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
0 S( W- B* J( o1 G - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) p" j9 {1 M F5 o) U" [6 V
- $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
7 x$ R3 `2 m9 ^1 o6 ?. M - $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; ' I6 { N, L) d
! `, D' x0 f6 A" t. _! B: r- //得到在线列表
$ Z4 K8 f6 E' N, h: j9 P/ v - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; ! X% l5 a# o5 u& ^
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
: f# W/ P8 {6 v7 @& l4 N - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 2 G& ~1 ]) w* m. W
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; , \8 e" v8 p/ w9 I
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
" l' |' S; d8 D; I - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
( A8 C/ A' Y1 V& v3 q6 {2 X1 @ - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ( a6 Q) T" y2 a3 B( q
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
' P# }6 L$ z0 Q3 L4 G% T2 W - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
; @4 l/ Y3 n( A* r2 ` - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 5 H% [! I' W: t5 \; w9 \2 |3 a: N
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; " N( ~- y- W6 k0 W! h% V; s( |
- $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
. `1 o; B/ O: Q( | - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
4 v4 J- c5 L( o2 S2 @9 e! y - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
2 I/ Y+ L' l C' O- S - $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
" t5 u: `: }' r3 A
7 b X' b% `7 A; c1 X- //查看好友信息 I/ j3 }/ U& J' n2 T, P A; R5 x5 P
- $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; ; y( {6 P W2 p4 t+ Q: {7 Y8 b, ^
- $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; 6 b9 ?) q/ O+ n* ^
- $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; 6 l m8 L- H. i/ B: m+ Q
- $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
9 ^+ L ^5 q$ U0 n - $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; 0 L" d+ E/ U. L8 g
- $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
. {: l) |. |0 s% R- ]0 O2 x - * O: ^- T! d4 y! v) Y* c0 S
- //增加好友
# r! C* M' }; M% @2 G. ?7 S - $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
4 w7 u Z8 l" b' |: h% q+ L
: J# o" D$ P! T4 T) A/ k- //发送验证
, l& H0 z' F: g( ? - $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
0 }4 _& G9 O" f$ t - $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
`) M: F1 h9 u6 e, o5 ?* I - $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
/ v1 u: T0 c: |6 ^: b2 r' ] - $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST"; 0 @2 {7 d% F8 Y9 g1 A! k
- $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
_9 d+ _5 E. `7 z4 O( r - $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
# B5 V) [/ i6 T9 ~# H
0 c5 l# Y d/ K5 ~6 s6 f) M+ E- //删除好友 / m1 ?8 X' k. e/ h: X t7 X+ l
- $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; 7 d/ a3 J9 k0 A7 R' X; F
- * u5 [+ o, X8 x0 |
- //改变状态 / z, L6 F( K2 w# ]! E* K" v- r2 m
- for($i=0;$i<=60;$i=$i+5) + O6 d& w% z; p1 P# w# P& P9 p& d
- { " W4 a& U% M1 m" p3 M: w
- $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; % P; A3 F9 D# x
- } + M4 [" m1 Q( `1 ~
- ( S+ j3 s5 o7 P1 T% D9 I
- //获得消息 . H1 \- d+ H- l( Z; g8 c m2 o6 D L
- $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
9 Y. C0 q6 F. k+ m5 `8 N
; v, E) s6 ], m, _3 A& ^: Q- //发送消息
9 G/ J: l# ~5 i3 Y7 }% T5 s - $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; . W; `/ }* c9 k2 J; @; q
- . c w5 r! @& @ }$ G
- //登出
0 J. p6 M2 T. {6 H$ M, q - $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; 7 o* i5 {) P, o+ `9 q
$ P) L% q% y* C1 q; ^- $file = fopen("p.txt","w");
* q2 p% \9 d3 T* t! u
; z. A& v/ \# C3 G1 B9 R: c% w9 ]- foreach($poststring as $k=>$v)
1 z6 A+ S) H$ g7 E0 V; U - {
( F. {# c# x6 {4 P- l - ss_timing_start(); % `3 R7 M- f( \, A: |8 Y+ K0 d
- $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10); + P: U& d% t+ E' p L
) G* y; G1 Q0 m$ u+ e ^- if(!$fp){ " X6 A1 j/ q2 T0 H& {* P% z
- //error tell us * y0 a. z7 t# t5 x3 ~( d- W
- $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";
- v# b" A8 Y2 ~# w* D - : V$ r& _, v2 J! J8 O8 t! C
- }else{
0 Q* G& W) l6 C5 A$ v
( Q5 l) _- t5 n. v# p- //send the server request
3 M0 ?3 M! s" X1 _3 ~ - fputs($fp, "POST HTTP/1.1\r\n");
; X/ u4 Q; z. R7 } - // fputs($fp, "Host: $host\r\n");
, Q2 } J; U; @. f - // fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
7 f! d3 E' b* d' s6 Q - fputs($fp, "Content-length: ".strlen($v)."\r\n"); , u. c) E' c, [2 N" o# u) g
- fputs($fp, "Connection: close\r\n\r\n");
* `' ^. k6 Q1 j/ l2 b( r - fputs($fp, $v . "\r\n\r\n"); " J- S" ~1 W9 @4 k
- 8 w) ^" h* b. t2 J4 Y# e
- //loop through the response from the server / @; c) y e# b8 F: {# @
- $res = "";
& o8 f4 _$ @1 v5 \( W - while(!feof($fp)) { # ?" k3 t$ f- x
- $res .= fgets($fp, 4096);
1 u8 h/ F: y3 l2 [8 X6 H - } # b) X! z. d% a. H9 \; V* q# S
- //close fp - we are done with it I M$ @: m% l* E9 n
- fclose($fp);
5 T% }& G8 i+ m: P2 v+ @6 x
: }/ s* {2 w1 F7 ^( j, o+ ]% |- $content = $v.chr(13).chr(10).$res; * ]: @' q* X' w4 n0 u* u) r, D' T# U R
- }
& \8 k2 G6 a1 _# A - ss_timing_stop();
k3 _5 f/ i4 X+ b3 G- ~+ q - $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
( B$ f6 ~7 O% `& o j7 v - fputs($file,$content);
' I0 g7 x8 U1 C - }
7 ~1 F6 @/ S+ P& b8 b - fclose($file); . y* S0 d/ F o5 }. K0 }
- ?> % h4 g; o8 c7 l6 N
- <?
: @/ T2 {) I2 v y - function ss_timing_start ($name = "default") {
* Y; \5 c& }6 m$ N | - global $ss_timing_start_times;
+ r8 y) Y/ C1 M3 [) o - $ss_timing_start_times[$name] = explode(' ', microtime());
; n. T/ z, U9 ~; j3 u- A - }
2 q! ~- V- K8 m8 F3 ]8 [ - function ss_timing_stop ($name = "default") {
l+ ~. B" T9 F: l7 Y- |. M - global $ss_timing_stop_times;
$ b. A+ [ a9 n* C8 t% |/ P - $ss_timing_stop_times[$name] = explode(' ', microtime()); ' A* D- A9 m: d' X. ?
- } % L+ P& X4 V2 v' J' \
- function ss_timing_current ($name = "default") { @5 W- P! e# ?# H& o: N
- global $ss_timing_start_times, $ss_timing_stop_times;
7 d4 c2 x& K; i, V - if (!isset($ss_timing_start_times[$name])) { $ Z# |* N2 l. ~. w" B. r
- return 0; 4 k1 U. b2 c' Z( D' `
- }
. T% w* ~7 Q6 ~+ K) H - if (!isset($ss_timing_stop_times[$name])) { 2 S( P4 K& P$ L' X8 Z+ m) K/ s
- $stop_time = explode(' ', microtime());
) ]) B8 J& H! j% P1 Y" g; N - }
$ Y; k) l$ V& y+ u - else { : y8 p% Q, n6 h+ H5 v
- $stop_time = $ss_timing_stop_times[$name]; - h+ n$ U; n% Y6 Y3 v/ \
- } - Q! e7 e; e, Q( a8 d/ q( `3 k
- $current = $stop_time[1]-$ss_timing_start_times[$name][1];
: X2 N4 l+ {. L( L7 ^ - $current += $stop_time[0]-$ss_timing_start_times[$name][0];
4 t! N0 V# [3 I& H& n9 g& d - return $current; , I W( y! [& W. D/ b( e
- }
* E d. u( L3 u5 Q - ?>
复制代码 ( f% P6 P0 f4 M- P
4、研究成果: * S$ G& i( b2 t- X; I
' E' ?) t7 l0 z, g
(1).登陆
! h3 }9 K* o- g9 ]( V& e 说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
$ J0 v9 k8 r1 m0 j *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ , \8 C" G, m0 Y9 X Q0 p
0 j( u4 s z) [4 J( N& X
提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 # Q% d6 H2 t9 \0 @
说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
2 G. ~! {1 V7 E7 c$ d! S M5这个参数的作用还不清楚,但最好为1。
: Y) [8 ]7 C1 j, s ^! P2 f- I; O LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
% P/ K9 [( y- h. B+ e7 G9 V L: v+ ]0 W" ^% N+ B6 H
返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) : X* d* x/ n' o0 |
VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) 7 f9 g, V' l" K
VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) , I( c0 Q+ q/ @- T/ K4 R
NULL(UIN为字符、PS为空、LC错误)
Q/ v6 S+ }5 d3 ]- w' h! ]4 y, O: u8 ]8 |" Z# B
(2).得到好友列表 % Q/ _- |, z0 \; J) t0 u" |( p
提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 * K, j3 D3 y8 }- R( _! B
说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 / ~0 a4 d4 u/ o+ u8 ?& C" K% c& U
* h$ R6 j o# o0 ]/ z! r
返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) * c. ?% `* ]$ ~- z
VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) ! r3 r+ m s( u
VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
) e% e5 |3 D4 E NULL(UIN、TN、UN为字符)
5 y. I! h9 S0 s9 N% H' h U: n) g3 o; d. p
(3).得到在线好友列表 % G" K' E8 C" \* s
提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
- B: c }; j- {$ I+ K. F 说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 1 Q8 [$ ~8 f; V+ a( }
, A4 p! L' ]7 U2 T; f; X 返回:VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES= 0&FC=0,&FN=1&SN=1&ST=10,&UN=106814,&NK=Hackfan 好,(当TN存在且非0时,FN=1,SN表示在线好友数,FC、ST、UN、NK的值用','分割,分别表示头像、状态、号码、昵称) & }/ G. A3 N2 t+ \& N
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
% X; t: m! V2 A* A NULL(UIN、TN、UN为字符)
/ d0 h5 L4 I1 O! y+ X) O 说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; + W- K$ a0 s3 i8 i( {+ t! d3 l
ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
2 y) H; J7 S% {2 I k2 e
/ H2 y! b c2 Q 特别说明:当参数TN=0或不存在时,服务器返回:
) e& r+ h9 z+ B, a0 Z/ qVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
: K+ c# \: m/ sHTTP/1.1 200 OK M" m8 [/ y I4 } ~& P. l ]
Server: tencent imserver/1.0.0 5 O5 [' N4 ?1 M4 N. |3 ?. G
Content-Type: text/plain; charset=UTF-8 & d6 F8 N E# \0 ?0 h
Content-Length: 56 * s7 i' j0 v( \" T7 K7 ^
4 o% `) Q% J, w' ]0 \: M7 y4 o
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
; _# \& u2 n: s) i# ^" iHTTP/1.1 200 OK
' K2 V7 a4 l* ?& tServer: tencent imserver/1.0.0
" _6 C( ^$ O) oContent-Type: text/plain; charset=UTF-8 2 N* W- D8 S3 F/ D: w
Content-Length: 77 & g! z3 R; D+ U8 J+ p' ]+ H/ o
5 V" e; z. d# T) [9 c) xVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
0 F- e8 [+ |& d1 A4 F+ v8 g 返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。 # w* B! M1 Z8 n5 ?# ~5 Y) \1 `
; H% D% ]- P% A
(4).查看好友信息 + D1 [, c3 b$ H: ^* X. J* o
提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 8 }$ V9 N3 k+ n% j) o
说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
9 y0 z. Z j3 r% Q$ C( t% E- q1 U5 R4 y0 @, G B
返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
1 X6 M2 v3 F% H d7 H8 f' M8 M VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&EM=hackfan@qq.com&FC=0&HP=http: //blog.hackfan.net&JB=学生
3 B' \$ y& K. e&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan
; U7 I" M7 R+ M6 b( E% q好(普通查询)
; m7 t2 a, D5 e* E VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 . z( Q s o: }" w9 V. E
&EM=hackfan@qq.com&FC=0&HP=http://blog.hackfan.net&ID =-&JB=学生&LV=3&MO=136********&MT=0&MV=&PC=邮编& PH=电话&PR=The guy is 9 J, i: H9 @# b9 U0 G
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
1 Y7 }; i" W: V9 a% I7 T VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
. g5 s* m+ J% k' c NULL(UIN、LV、UN为字符) ) D( K; l" G) i0 I- R; n' Q3 s
' V$ y8 ~; E0 d0 Z% `6 P9 {& W* ]
说明:AD为联系地址 2 L8 h+ A) n0 O0 D& D% z, o( w
AG为年龄 - q W Q# \, J R# k) R, m* \; Y
BT为血型
$ K8 P5 [4 ]9 ~4 `( g# a. S CO为星座
7 d. `; x9 m$ P- g& X CT为城市
& }' f a" W7 [2 | X9 T CV为未知* 4 s, Q( c, X# J: G) O
CY为国家 c- `# l' @- ^0 s/ K, [' }6 ?
EM为Email
. N# [7 m, B# F FC为头像
! l, v! ? @7 [5 e: M0 { HP为网站 ; }, b4 y7 ]3 h1 ]8 G& S# b( C+ ?
ID为未知
6 j4 s; l; H0 x, b% F3 I JB为职业
) M4 Y+ q" r2 r' I7 Y3 C LV为查询代码(就是发送的LV) ! @% F1 W" t q7 \: v$ C
MO为移动电话
! R; }$ j( X( v! N6 k8 i9 u MT为未知
. \. \2 P; K% D4 a7 O% \ MV为未知
- y& ~$ d5 Y* t$ b: { T- ~ PC为邮编 `: O4 G" u* y% M( @
PH为联系电话
' R- H' s H4 H1 O PR为简介 " U' _9 }. Q' b; e0 ?+ m8 H( r
PV为省
3 w6 E0 q, L8 V5 i! l RN为真实姓名 $ f; P$ D$ c' f$ o- j
SC为毕业院校
4 S. m, e3 c3 ~1 h SH为生肖
# {" E8 S9 w9 y SX为性别 ! x L3 w+ y, G9 F- a" r( _4 V
UN为QQ号 " k1 `: h/ i) f' Q% M U: ~- Q1 u
NK为昵称 2 P* O: n7 Y0 _1 s
9 d* C' ?/ H# f/ a2 ^( M 血型:0 => '',
t3 ]; [6 A: U* N& \% h% O 1 => 'A型',
' D6 J4 U* ~( Y/ L 2 => 'B型', + P, \8 M+ j9 ~% B
3 => 'O型',
: ~9 s" b4 W4 s$ _/ a: P 4 => 'AB型', 3 u& B, H* u$ R8 G; C6 d: [2 K
5 => '其他'
7 t: N, u' H; I0 u8 n) M+ z ]% z$ X6 n: E6 b
0 Z" s- n& A) @" }0 g) J/ j
星座:0 => '', " v, d+ W3 E: ?$ B! i
1 => '水瓶座', - \7 P2 O3 J, N7 o: Y6 l O
2 => '双鱼座', 4 z5 \: R3 @" G* p# n
3 => '牡羊座', 3 W, ^( V# S7 e. z; a7 S( k( S
4 => '金牛座', 4 R9 P4 [; c$ K
5 => '双子座',
( h* m/ d% r% p% ~* ?" I: | 6 => '巨蟹座',
' y( c w% n9 J7 q1 r9 R 7 => '狮子座',
d# g% K8 }5 S8 P/ l. U. ] 8 => '座',
7 J' a( K7 o7 A4 p; f3 x 9 => '天秤座',
0 P7 y: g1 J8 p' W, B) d$ U% O 10 => '天蝎座', 6 I5 G; D9 u, w# c' n: O
11 => '射手座', / f: a1 q0 M0 b" D. c8 p y
12 => '摩羯座' ) e. H0 J) J5 o, a
( \9 M1 i. V" b+ t/ I# O
生肖:0 => '',
% k, h P4 s# U! [8 F5 a) Q 1 => '鼠', 2 P9 L, j+ A/ h$ ^; \7 x2 l
2 => '牛', 8 _# `& A& i Y; @! G( a
3 => '虎',
9 |, Z2 V- y6 C" I% } j) _ 4 => '兔',
6 t: q. \- i: M 5 => '龙',
. f! H, o4 H c3 S3 } 6 => '蛇',
' p) `* r2 }! M/ {: f( h: K; ?1 | T 7 => '马', S. S3 f) e' q; J. ^5 E/ S
8 => '羊',
8 R9 Z5 J6 m% w1 ^* Z S1 @ r 9 => '猴',
# F3 ?8 h/ K. W5 K% n9 G/ \ 10 => '鸡',
% O; g. y$ l4 B2 j8 Q 11 => '狗',
2 T0 I ]9 p0 A' |* ]% L0 O 12 => '猪'
* a8 F& N: t8 R: G
0 Y( Q+ L8 A2 J# @1 v" v 性别:0 => '男',
' y! e" ]! d7 Z! J 1 => '女'
; l6 y' O* x( A' `9 h, ?& V6 s% Y: }
(5).增加好友
$ \% U0 J/ E" X2 u 提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
- T/ @$ E; a) l. P1 m1 b6 t8 `- n1 s$ Z: b# W9 V* }- ^ q7 ^2 }
返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
" N6 O) f( D7 ~( M" R4 Z" y VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
! G' ~, X! _& Y, | q5 U9 ] VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
0 o) H* I1 d: q' k! s2 _0 O, e VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 0 W# T+ J# }. \
NULL(UIN、UN为字符) : v% q7 [& `8 O
/ s# b; P6 q6 u# n' ~; X4 \
(5).发送验证 ; l& [9 D* n! M X' h/ S, k- n! g
说明:1、如果你加对方为好友,你需要发送验证 % F- b& m! |; K* D
2、对方加你为好友,发送了验证,你要通过或者拒绝 : t z: e7 L+ ?. a5 ~) D
这2种情况需要发送验证消息
) p9 h/ J f) y" _! m/ r1 T) N Q) Z% N% U
提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 * T, T Z9 j D9 B+ y0 o) s
说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
L3 Y4 m' I# ^4 U& |) [
* r, a+ e. N" W7 Y$ i5 j 返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 4 g% H+ [* h7 r) }. n$ z
VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
. a( u1 @! \; g" t" F+ D" L. H; K VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
+ j6 i5 r# a( F4 _" m8 j NULL(UIN、UN、CD为字符,RS为非UTF-8字符) 8 w$ I& A0 t% ^1 u8 p
*如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
8 D& K/ W$ v0 m% ?0 d W x/ \7 H& B: i& }& w8 ~% {
(6).删除好友 8 i7 v5 X( K2 s# i
提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 $ \& ]4 [* o1 y' h6 [& N
3 |: {$ g4 F) @& E6 A* x
返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
, o; y. d' F) n6 _+ Y' f" ` VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
. t1 G {% l4 W; Q& j1 \! A VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 N! g7 H4 }+ w$ L NULL(UIN、UN为字符)
" S& F3 e* l: Q( e! w
' x# g$ z$ B q7 G( d/ ^' s(7).改变状态
! ?, H9 A) N: D0 Q3 Z 提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
) B# k6 P" f1 x$ f 说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
# ?4 r/ p* ?/ h1 j- L8 A
k, X' `' A. {% d9 U 返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
& b8 K$ v4 r; Q. A VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
1 Z3 ~# O' q2 x* `; F# Q VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 f5 `0 A' E& t# z: q
NULL(UIN为字符,ST非法)
* N( k* ~6 u& E X% S( Y0 `( N4 d$ w% m3 n' [0 F; ] s# Y6 E
特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 y: ~( G* ^6 i1 g4 q/ o
同理,当你的好友改变状态,你也会收到一条系统信息。
. G' E6 `7 U# a4 }
' k3 S( ^* {' ~/ Z+ i! A, T(9).获得消息 ' q6 t2 G3 L0 q" I5 M+ m
提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号 9 H- a1 m `4 G3 {. f9 {7 k, W
1 H3 v7 g1 h i$ J0 K0 G& q 返回:VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0& MN=4&MT=99,99,99,9,&UN=36791785,99833581,99833581,106814,&MG= 20,30,10,hi ,(MN表示信息数量,MT、UN、MG的值用","分割,分别表示消息类型、发送人号码、消息内容)
' c$ r* D& k- Y" F$ i VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
; L% V% L4 t8 g& u7 ] VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 9 @( }+ p2 i/ M
NULL(UIN为字符)
( C. i B. k1 M' Y( `) o 说明:关于MT:
' A1 o* A5 `# D3 p 9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友
6 D& y" ^- h, `+ \" k 关于MG: 8 N9 K+ Z: Z2 Y3 b Y6 d0 b: }. G
当MT=9时,MG为用户发送的消息内容 + Z" O" W' q9 B6 e
当MT=99时,
& Q) e, {, O' H) a MG=10(QQ_STATUS_ONLINE)表示对方上线
' H! |( [8 Y& e: @! C( x z z+ i MG=20(QQ_STATUS_OFFLINE)表示对方下线 1 w" H) z0 ], v6 |7 w f( T) n% V( d
MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 , |5 ?$ M& b/ p8 R0 O' u# b
当MT=2时,MG为对方请求你验证的信息 . Y8 Z7 A8 u# S- s4 B
当MT=3时,表示对方通过你的验证 + \" i6 p6 y, F. `- H0 Y' J3 }
当MT=4时,MG为对方拒绝你理由
8 R7 }% F/ H: t" z! l/ I2 [
3 F0 P& @- q" Y- I6 c: y(10).发送消息 " s4 v0 n* m3 y2 i9 I/ m
提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 # ?9 I. i0 r. p+ `: x' A+ j! H
}; M: P# }4 f/ G8 N
返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) 3 n7 H8 ^( R- `7 p/ E0 [
VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 0 @8 ^9 q1 e7 U- S6 S& @0 [3 [
VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
6 Z! h* J/ A: U& @# p NULL(UIN、UN为字符,MG含非UTF-8字符) ) |7 `, E- u% S" ~
说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
. e, B. k# T8 C% ?, X& l( P T3 {6 t 你俩互为陌生人,且对方没有和你说过话
; B3 q0 C" T A6 M 你在他的陌生人列表里,并且他没有和你说过话(没有验证) 8 a7 ^ i7 K* \; Y5 e
2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s 8 w' {8 P; S5 L8 c- K' w
3、当我发送含有小写字母h的信息时,服务器有可能返回NULL 2 N6 r0 L/ V' E! Q6 q7 Z/ d: h
! j& z' R' e# | E7 H" ~6 U- [
(11).登出
k/ i! D- ]0 E- n; ` 提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
. c% X& v. T# N+ u# e: f/ D h7 y- C! R% @/ \
返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
& Y0 p) l) q7 p& W9 e% M NULL(UIN为字符) 8 l. }: q' }1 G0 g; z
5 i {& ~+ K3 f1 Q; P
5、总结 2 U: Q% G: S, f2 U# u0 V
# B& b% u7 h. `- @+ n 通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 . C/ W; s/ |& x2 [2 Y/ `
http://blog.hackfan.net/index.ph ... d=a_20050819_223558
8 ?) H' F3 `7 k 本文撰写时间仓促,难免有误,希望各位不吝赐教
. ^' w. ?/ h, u, W9 l0 k2 i3 a8 |9 K4 P2 U' k$ U
3 s. l, [0 y1 A
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301 |
|