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