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