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