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