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