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