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