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