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