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