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