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