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