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