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