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