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