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