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