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