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