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