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