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