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