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