找回密码
 注册
搜索
查看: 5907|回复: 0

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
+ e5 R, e7 g, T5 y" F# n% \* e日期:2005.8.21凌晨 ! L6 J/ o  q1 E- z! f7 }
联系:QQ:106814 Email:hackfan@vip.sina.com " R1 v. {# s; v! I9 M6 _
7 S" X8 q/ Z+ g+ R& Z' B
1、研究说明 - p9 O5 ^) `$ c7 L' m% t1 G* V
- N, ]. b! {- |5 e8 f/ N
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
. [7 B; m0 _+ a% j) @( a; R  a1 ^
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 6 i6 J( A+ P2 [1 v- b
9 @" X0 X  [! D3 c
2、接口说明:
5 _5 n* L$ `9 d
- b& @$ G0 d$ M1 f0 o8 H  接口位置:tqq.tencent.com:8000 " Y* p' k6 s  K6 s$ V. Z; Y  m9 e6 E
  通信协议:HTTP 9 C# t4 ?3 v) [3 i, X7 _
  数据传输方法:POST
7 p1 l  v4 g" D  @. c- I% O. C/ `  HTTP请求格式:
6 j, @: T4 p3 V2 j: o
1 G9 X: ^- ?2 g, x3 |POST HTTP/1.1
% h, L: g5 ]' ?. x+ m- t* E' H% [; g: HHost: tqq.tencent.com:8000
) i" `8 ]1 C/ nContent-Type: text/plain; charset=UTF-8
. Z5 s% u* A# f7 X" GContent-length: 长度 1 B5 I7 e" ?! o$ B4 g
Connection: close ) p4 b3 X; i* \, Q: j

7 |) O1 z, V6 {# R数据 ( q7 @2 @: p1 O' K
# }+ g  J/ D( @8 _0 |3 P. m& u
  其中长度为 数据 的长度,数据的格式: " I" I, C; P8 }. I. R# x6 o
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... , N9 |' c9 }  x3 K: _

" C) G+ k' p% t1 c! S. Q$ g  以上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还需要不同的参数,下面我就公布我的研究成果。
. T5 N$ `: V' p
. Y5 E* J) _- F5 b1 q5 ~7 n3、研究方法: 2 z* q4 `8 z% w2 W) t$ I# I% y# N
) j( k" c: ?0 d, X
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
0 ?: g8 e$ X7 q. J/ ^$ R  下面我公布我探测的代码(PHP):
  1. <? & j) x2 ]2 S, b% b3 K
  2. $uin = "QQ号"; . I4 k, q6 w4 B2 U$ d) |$ T
  3. $pwd = md5("QQ密码"); 9 k9 Z$ N+ K" W% D3 E& a
  4. 9 t- X2 k, c; _5 b( P7 `
  5. //登陆测试 % S8 \: r4 f. @; [, S6 I
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    # X+ @& R5 {8 y; }4 {3 U8 I' N5 n) k/ n
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 + p5 }% |! |+ j9 B" W$ h( T; N
  8. /*******
    ' q' f5 B) e8 I5 R' {6 [1 b
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; & H8 Z4 ^$ t7 F) z2 C
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    + a  S- H& H, q+ w" S
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; ) r) D+ b- G5 r, Q) D
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    5 U2 m" J  Z  r: y: S
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    2 `* k3 F, u4 e
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; , `8 x3 O2 S1 X6 d5 S5 W: ?9 X8 k
  15. *******/
    " v" v6 A# o) b2 z% @; D

  16. & S& K3 D) [% l+ O- b/ N

  17. : y2 d- |- [2 x7 G. b$ }" N
  18. //得到好友列表 2 U5 @# A2 x6 R
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ) h4 y4 a2 v$ a+ U3 B
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 5 [2 r5 U  `7 V
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    * e* U. M# I0 P* {8 a7 R
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    5 k  K2 G' l; |; {
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    ; x8 L; s8 R  L
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    3 a* K/ q- [- G$ s: D2 R6 \
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 5 X2 o, b: c$ p2 `- Q# O
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    , ~0 y3 E! g. m" o
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 0 ]5 L' O1 ~  q0 F2 H% F
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    6 G8 _$ p$ o' s- P1 v& [
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
      ~7 D, V# d# j0 \3 y
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) H( W7 x4 j( h$ _4 {
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    3 ~. C, ]; Z3 X) O" w
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 7 d7 O2 Z/ x3 i" Q) n- ~: {% U
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    8 t( @/ \  k, w1 W* E- y
  34. 6 S. l, q$ V' Z
  35. //得到在线列表
    % Y, E# K: n: M, \; N2 W1 F6 C
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ) U! g* N9 |& g$ }
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 2 Y) V0 ]# w/ @
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    & Q9 m  V7 K2 h, f4 j
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    7 S% \( z' {: R, V4 H4 E" v
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 4 w1 W" j9 \( {$ v: }
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    + h- K! H' G# k/ k( b! W" l; M& M' |
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    5 e9 d, D7 b/ ?0 e: Q. o
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ; O3 u# X( Z- }5 D7 U) L2 N. z
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ! Y) X2 t! ?4 ^
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ! P! f4 `4 n7 q5 J' z
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    3 d1 {7 W- [/ A( U' k: H2 T: I
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 2 s9 z; Q9 ^; L# l8 n3 ?
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    1 d# R% f, `$ b% m( }
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); + U/ b! b; X+ a4 }
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    3 c) g( s* H  m% x) `3 @
  51. 4 o+ T, l  _" ]: f
  52. //查看好友信息 ; C0 O' z1 Z: U8 I, L2 D+ `
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    1 Z  m# [# X1 _3 G1 v: b7 F
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    4 W4 V% V# X( b0 W
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; 7 g& v+ Z3 F# Y8 y4 i8 O0 {
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    $ u( x  C" @# D% R8 D7 m: r0 {+ a
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    : C* H- C' K6 n/ N: Q9 |  \) q
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    # {. m' p& R$ v7 T$ |
  59. , K5 Y& m! W6 r* F: U. u! e' J
  60. //增加好友 + E% B+ u. K/ ]0 P, x
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    1 F% `4 z; G( d) u; ~: u  P6 |+ i

  62. & W! j% v$ k3 F' r9 A- E  v
  63. //发送验证 6 l% V8 a8 a/ J
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    $ M& ^" D4 C% k2 r+ K% M' W
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
      H# D- S' h: i& h' z
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; % N3 V& B; w& G8 d4 k4 ?
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    " l& b" r: t0 E) k
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    . J! c6 ~0 a  B
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; 0 \9 d* r9 U. U, z$ _6 ~# m, H

  70. . h) v" A% g; ~# S4 T: j1 {
  71. //删除好友 & I; r/ N+ o" R
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    8 P/ a8 r  w( v

  73. 4 N0 U% u% M1 |6 l. o
  74. //改变状态 7 r4 u$ t. P' J0 N4 P
  75. for($i=0;$i<=60;$i=$i+5) + G- i- w9 J0 F6 r) m7 U8 R4 h
  76. { ) K7 ?; {" {7 y9 X% g: ?
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; 8 G0 K- \! G4 H7 _
  78. }
    $ h- z6 |2 K) x" R3 _4 L* R
  79. 3 J3 l& B) |8 v3 R/ R
  80. //获得消息 " {8 C3 u# y% P2 @6 I; P
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    + d" F1 M2 Q! u7 }0 B( ?9 G
  82. ; X" b2 R' d! g. K; [5 Z4 T
  83. //发送消息 ' h* V! f  p4 e! X
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    8 R8 W! K- D0 Q% {% l

  85. 2 B5 _1 N$ G, I. P* y" l
  86. //登出 & y" I/ D& p' n
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; ) Z6 r7 P' F+ o0 }8 d+ o( D- T5 h
  88. % Z9 h! B; C5 \5 n. |) A- L
  89. $file = fopen("p.txt","w"); " `* d4 G) R7 M  T6 @6 e6 y% b

  90. + v" Y5 m. M& {  i( l$ C
  91. foreach($poststring as $k=>$v)
    0 w. ]" ?3 N" G( Y# l" r4 R
  92. {
    3 l$ ?; I% _* {* v
  93. ss_timing_start(); - e3 b& c9 b6 n/ H' x& V8 e
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  % `& i  X# t$ ~

  95. 4 u! c+ a3 t; k) }
  96. if(!$fp){  6 f* e# }* n& o3 b; _" k
  97. //error tell us  
      ], e- E2 d1 _. b$ Y
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    / r( q* G; j7 c0 z& |
  99.    3 O! Y6 W' I7 z* T
  100. }else{  6 ], O; w0 }6 s4 y9 M9 D4 a1 r9 K

  101. 1 t! e6 ~2 @2 O! R
  102.   //send the server request  1 A5 \* Z4 J& c
  103.   fputs($fp, "POST HTTP/1.1\r\n");  : \  `: S: G3 r5 ~
  104. //  fputs($fp, "Host: $host\r\n");  8 J! a/ [3 X7 L$ R+ U
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    7 s8 Q. ?: G! `8 D! f8 U' h
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");    q' t6 O$ x4 d# v. \' J$ |) Q
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    . ]: w' P) z" H& i- l( G5 I7 j
  108.   fputs($fp, $v . "\r\n\r\n");  
    7 B; Y: E5 [* L, V/ b

  109. ! o" M, f  z2 J. q5 q* w' ~8 |
  110.   //loop through the response from the server  
    , s6 n2 V; m5 V- @$ m: f
  111.   $res = ""; 1 I3 N1 r4 u" l; G- q
  112.   while(!feof($fp)) {  2 `# ~0 G: F( u3 g% I& {6 u6 c
  113.   $res .= fgets($fp, 4096);  
    - s. v0 p, [  |5 i
  114.   }  + n% R& i0 y- D6 L  r
  115.   //close fp - we are done with it  
    ) X. U& Y# J6 b! P/ J' y0 g( @
  116.   fclose($fp);  + K6 U3 i3 r* ~, }% I. x( n

  117. % e8 Z$ b2 n- N4 o* g
  118.   $content = $v.chr(13).chr(10).$res; / P0 t! d7 H+ s& Z# m
  119. }  4 ?9 z5 `; l1 S& W7 x7 J
  120. ss_timing_stop();  / M$ V0 B  J. ^1 M3 `$ ~
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); 4 K0 q; n& N- y8 d$ \8 L
  122. fputs($file,$content);
    ! y+ A3 G6 K$ @3 ^
  123. }
    * _! w, @/ _% }- A( @- {: D6 i( f
  124. fclose($file);
    ( v$ O5 M# K7 R8 X. O2 C
  125. ?> : w: R/ l0 L/ I3 Y$ x& k
  126. <?
    + L8 R) u& F7 L2 d# V2 b1 r
  127. function ss_timing_start ($name = "default") {  
    ) k( U. G  g; }0 t5 a
  128. global $ss_timing_start_times;  * l" y, H$ u' M  X* {
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  * R7 n* Z! H! q/ v8 P
  130. }  & r( c) u4 X; @' T% _1 P  Y
  131. function ss_timing_stop ($name = "default") {  . k1 D- _# }! }: \2 ~3 J# d
  132. global $ss_timing_stop_times;  5 x7 a: S1 h: d: G  \
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  . z8 R% c3 Q) ?) B% p% e
  134. }  
    $ K6 l) `2 A2 o+ p3 H& |
  135. function ss_timing_current ($name = "default") {  # G1 J1 w+ A# X, @
  136. global $ss_timing_start_times, $ss_timing_stop_times;  9 n5 l  |+ N0 d( g" q4 f: `
  137. if (!isset($ss_timing_start_times[$name])) {  
    7 n2 [" b1 l& _& Z1 b
  138. return 0;  
    - F6 N  d) L7 j9 U/ E3 i) k
  139. }  
    3 h7 k3 K5 E5 N1 O
  140. if (!isset($ss_timing_stop_times[$name])) {  
    ; q) W, E; R" F/ y/ J! y9 M
  141. $stop_time = explode(' ', microtime());  3 S2 ]3 h. Z* \* f8 h
  142. }  
    % j) D1 f2 f# c" t( `' t# c
  143. else {  
    8 H" U% i+ R* Y. h1 T* Y; {3 S
  144. $stop_time = $ss_timing_stop_times[$name];  
    2 _$ S. O0 W5 V3 P3 [
  145. }  
    4 G2 {8 R0 C2 I8 d1 y: h+ o
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  ) E4 P/ k& V9 @: z9 t; |
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  2 o9 P' M7 E) T) A3 Y( ^
  148. return $current;  ) d% s  w# r4 N3 b9 a; m
  149. }  $ M; k' f  J( B$ S7 M+ y
  150. ?>
复制代码

; E! W/ j' j+ B4、研究成果:
1 |  p* i6 X* f' s( t4 @. @+ J* _( T! z. Q7 a% R/ j
(1).登陆 ' T4 F" F5 d+ N  A% B
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 4 F8 x% x' f4 N  _1 P
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ / e; o* O  e2 u& e4 M/ f

1 n: y( n  g+ g: ~+ t  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
' Z  C8 {) M$ I# `" a6 H) N$ D  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
) {4 _2 Q8 \( P0 J5 l' }     M5这个参数的作用还不清楚,但最好为1。 ( H9 Y" t  t& v6 P2 M
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
& S3 ]! x" J' j% h9 h& X7 [  g* y
" }& C  {0 J1 h- \0 w, ?  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) $ E* O% k$ C. m
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
0 j$ D+ S! R& X' v& U7 I     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) + ?  v) n" Z1 I5 v- M* ]4 b
     NULL(UIN为字符、PS为空、LC错误)
; E) @0 e' `% J+ C. U3 X
" j* W. y1 ]9 I7 V1 e(2).得到好友列表
8 ?- _4 d5 t6 A: P, G  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
% R+ ]8 ?: `) X  u  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
# @+ @( y  v- _" h+ T
; S% c% r3 |: w0 E% g8 e, c  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
7 g, E0 }8 _4 _6 t& @6 P" O     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) + L) y2 H6 c7 ^4 |4 I; F2 S* f8 q
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 A) k1 c* n: j8 e  P
     NULL(UIN、TN、UN为字符) $ b$ R) ]6 M1 N
; a, K7 f" `4 i4 I
(3).得到在线好友列表 : \5 I3 m6 U& P" \0 j5 U2 g) l! m
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 ' V* E; m2 }. q8 ?# @' E- M2 t8 l
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
- j: o3 z/ I5 n7 k8 _2 M6 S
$ E& r% X: b$ J. G0 D* 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的值用','分割,分别表示头像、状态、号码、昵称) 2 @+ v) [+ ^3 j% N1 H
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& q" L$ \' B8 F     NULL(UIN、TN、UN为字符)
9 B* k8 D- V5 U: t  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
) n, ~1 k  l4 G" T+ R) B6 t5 B. N     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; 8 }0 p9 `6 E' G$ n3 t2 ?/ y$ e& g! [

. n( A- m% @" ?" s  特别说明:当参数TN=0或不存在时,服务器返回:
& w; p8 \% {& g# NVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 ' |5 j! ?  F: W( i2 m8 _, H6 i0 i
HTTP/1.1 200 OK 5 K3 {8 K* Y* P2 X8 G4 k
Server: tencent imserver/1.0.0   F( J: }% z8 o
Content-Type: text/plain; charset=UTF-8
: u! S& s& s: Y  SContent-Length: 56
8 H0 C4 [$ I2 W0 u& ~
' I* ]  b: Z# ]* G. p+ SVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 " u/ `; D! w, q5 j* m( _
HTTP/1.1 200 OK
$ J7 {1 |* @$ e: b8 _/ f" SServer: tencent imserver/1.0.0 2 p/ X: z  n. G4 ^
Content-Type: text/plain; charset=UTF-8
( n4 \+ ^( L6 O5 ZContent-Length: 77
& B% X, k% r, u8 I. u$ U8 f* I  w4 p# K
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
/ d" f3 `: z# n! `# h* ?: \  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
2 H, C* T: B' }. J. @( P3 d, g
+ S3 O# K4 G0 o6 l! j! ~" Q$ F(4).查看好友信息
0 J' z" A1 J- q% Q- v7 L6 ]  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 : I* X0 s8 [* ], R3 U! E1 g
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 . }+ n! P+ W7 A$ h6 ^; T5 G
2 e7 [7 ]$ W! i9 E) Z8 h- B7 g. I
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)   M' T9 y/ r4 c2 B/ G* q* K+ d
     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=学生
' u2 G. \; p& _4 A3 n5 R3 m) K&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  4 f5 z$ ]. V5 _3 _' g( G( t: k
好(普通查询)
, }' d; i( r; ]$ {6 @8 E     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 4 {3 ?6 F, ^) g
&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  
0 p. @/ d  u7 {* eupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) ( |5 w. j+ ^$ V7 j0 F
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
3 @' `- ?8 W" f8 J. o* J: ^. X     NULL(UIN、LV、UN为字符) 4 k% E6 X% s/ c, c5 a4 m

2 W; N: k! [1 |) A: Q2 a  说明:AD为联系地址 " B  D% {: @  @+ |
     AG为年龄 9 M3 n& Z7 I# Y% J8 g- {
     BT为血型
  S1 ~# {8 d5 q& v( L( o* ^  H     CO为星座
6 e; i( T% V7 b$ Q     CT为城市
7 @" Z- v$ t0 o/ [     CV为未知* , H1 `* |0 [) M4 z) V
     CY为国家 # @% P2 h# S2 P/ ~
     EM为Email # g+ n! I* h$ g* B" `2 S5 E
     FC为头像
9 R5 H+ r1 x' m5 y     HP为网站 $ {( g# h) Q2 @1 D
     ID为未知 3 O" t0 u) T, L# ^' k+ q3 t: i7 M
     JB为职业 ' O, Q: ^! b# R( w/ v5 t4 z
     LV为查询代码(就是发送的LV) $ Q# ?! F2 W/ `9 H& Q0 {6 U; |
     MO为移动电话
4 g; u6 x* q; h$ s  E1 G" T     MT为未知
& a9 E& C* R. _     MV为未知
$ {# G3 }8 e. j% [5 W. E' S* ]     PC为邮编
# A8 }% k9 U9 Z4 W; w# m     PH为联系电话 " P% j. W5 T: t; A' O# R( r
     PR为简介
# `& Q- \7 X: ]6 e# E. T5 {     PV为省 # o& |9 E# J% J% D8 P
     RN为真实姓名
7 y2 `( C# R6 e6 ]     SC为毕业院校
  O* u" {+ j! i/ ^     SH为生肖 ; i& c1 t4 E' v1 q/ V
     SX为性别 . \3 @5 r  [4 S( Q8 {
     UN为QQ号
2 r2 F) T# v  d, @1 \( I     NK为昵称 ! c, a5 K6 g; u& f7 O. r5 @

- ~) j, P; m; s- v5 m/ @     血型:0 => '',
1 f% h! s# h) C* q/ |        1 => 'A型', % A; C/ |) Q( B5 m  o- H* X
        2 => 'B型',
5 N0 M$ E2 R- O: r" T        3 => 'O型', 0 L* c1 e5 i8 Z; c. P4 S+ P( k
        4 => 'AB型',
, u6 n( t* [: R3 S  y        5 => '其他'
+ {/ b( E# V! m8 ~8 ]" i% K; v
1 C: ~- I0 h( O8 ?0 h! i1 N( T
3 R+ F; D0 P# l6 d     星座:0 => '', 9 g: T' c7 i6 Q* N4 h8 Q
        1 => '水瓶座', . y0 U/ d3 a# ^% v; \
        2 => '双鱼座', ) I# @- K9 G* S# Z5 R
        3 => '牡羊座', ( w  `8 q( V: {8 [0 F% f2 F, l
        4 => '金牛座', & y6 D: W1 U7 r2 d8 r
        5 => '双子座',
( I' a- r: s" e        6 => '巨蟹座',
' o9 @9 X" u( D, }" m        7 => '狮子座', 1 M+ R3 X/ J! R0 p& q- T8 p
        8 => '座',   X) r2 g4 f" n) S( R, T
        9 => '天秤座',
% n4 e; w9 l& l, `        10 => '天蝎座',
, s5 K2 ~5 V+ S0 m1 J/ m        11 => '射手座', 6 F. o  X- n7 w% e
        12 => '摩羯座'
8 v0 g4 g' Q$ J$ H% g3 x1 C
$ r( N6 j) g; }  {" _0 z- J     生肖:0 => '', 7 k5 q# ~# V# r( v- F
        1 => '鼠', ( U; a( O& l) c" L
        2 => '牛', / n9 ]3 C" s$ n
        3 => '虎', , e. Q" ?! n5 e5 L) I$ S, a. i
        4 => '兔',
6 u# X) j" @& Q- ~6 A& h" Q# G        5 => '龙', 1 r5 j/ o$ v/ y- f- i9 ]" v3 h
        6 => '蛇',
$ B% q* h8 [( z/ }1 t* X0 b        7 => '马', ) ^1 x6 |3 w' y# A( t# ?4 t1 U: \
        8 => '羊',   g/ P" e# P2 R6 {" A6 g
        9 => '猴', , g4 \( ]6 |4 _9 M* ^
        10 => '鸡', 9 Q2 ?6 l3 P; ?: H% X: O: s  G
        11 => '狗',
; P; s; ]/ s2 M' c        12 => '猪' 3 n1 k0 V# e) l. K, `# G
# J% `2 g8 o, r! X" v
     性别:0 => '男', 1 g; S9 d' `! R# j! Q( Y, l4 i$ a& h
        1 => '女' : s. t5 P' j& q" g9 G$ _

) f3 w1 V( c+ O! N# @(5).增加好友 + w. w- `7 m4 {1 `# F6 z: G. U! N/ s
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
# E$ \2 C( s- d5 x$ N4 I" J+ q8 S# p1 s8 z2 b: _$ _: {0 ~1 b' r0 N
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
; ~8 o2 d/ V8 J& |3 E* `$ i, z& b     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)   J7 D* g9 B) `$ x5 Q
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) + Z; u: y( F+ g
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ; M  E- b; f' E" C" @  d9 |
     NULL(UIN、UN为字符) % X& e% W( Z# H5 g

- F" i( b9 Z0 E: Y- Q(5).发送验证 & }/ V8 F1 C# Q; a6 B9 d& x0 d' F
  说明:1、如果你加对方为好友,你需要发送验证
6 W4 D4 Y, v4 R     2、对方加你为好友,发送了验证,你要通过或者拒绝
6 L2 y! l# R. y' d( s6 r5 G9 X     这2种情况需要发送验证消息 1 J  h; L& b% z; |4 S+ K

$ A/ a5 @5 v# m4 M' c  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
8 a& c  S$ s" E& @8 `( R  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
! |6 F  _+ s: ^% u+ k! M5 K% D$ v6 g
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
2 D, l5 y/ @% q: h     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) 1 ?; [9 \3 H4 J, q4 y$ C( ~
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ' L) v% g. {( O/ Y
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) ; _0 W, e7 l$ H
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
, n" r! y! ^. g2 |( H) _* g- z# L# A9 E, O
(6).删除好友
0 [  J+ G* B1 n# S& Z5 x7 l  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 ; c* _3 Y0 d3 k$ q" }6 Y
: e1 B8 i5 K  T
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
$ Q0 U% f6 ]2 E" ~     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) . t# e5 w5 z7 H9 x' }
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) - D, p% |; U. h0 r0 I
     NULL(UIN、UN为字符) / Y$ K( E# B) _$ [9 {

9 f/ B8 Z# s( A5 H/ U(7).改变状态
, l" f1 _( N6 C$ ^0 l2 e6 r  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
2 h1 U0 V# p" v0 C9 a# m. R  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
2 z/ [( L, L- a: [( d: g4 Y* [2 `0 ]3 n4 I7 `, j) h6 o+ D
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
( ]# p: I* l& B0 ]0 ^: c- V3 s1 \1 k     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)   d/ B% ?/ e5 m& Q
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ; y+ e3 g. w+ h; }
     NULL(UIN为字符,ST非法) 5 b* [8 V% C3 ]* t; V

1 I2 d9 g6 j; T. D% l. O! K* C  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 2 k1 i7 W0 O& N1 c' ]( j% p
       同理,当你的好友改变状态,你也会收到一条系统信息。 , S' P% K: ?, m* d4 C' M

3 L; E" J) e- J( Q# V2 q(9).获得消息 . ?0 \9 }( t+ C2 S& H
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号 2 z2 n( Z' W8 u+ a! e

" c9 `# M" O2 ~( m  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容)
2 s6 G6 x- N5 N  {( C  N" {6 C     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
1 h9 Q/ v8 U$ B     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 I! P* l+ L4 S" `; u( `$ F     NULL(UIN为字符)
; i0 P$ v/ t* b6 z' p: T4 |  说明:关于MT:
- e0 ?( O$ _7 E/ ?! u$ X       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 $ c0 c$ W0 {' ^' P2 C# z, F7 G
     关于MG:
+ b( _& N- T" e8 A, U$ c) w       当MT=9时,MG为用户发送的消息内容 # q  ~$ a5 E( D; X( Z6 A; o, Z
       当MT=99时, / |  _5 y  p9 t7 `! y" s8 Q
         MG=10(QQ_STATUS_ONLINE)表示对方上线
+ h# e6 ?# L8 z% k; j1 u! p  C* c- j         MG=20(QQ_STATUS_OFFLINE)表示对方下线 - }, X/ K, a! `# Q$ v
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 # A) Q5 B! J# q0 {
       当MT=2时,MG为对方请求你验证的信息
6 l# [+ Y% [2 P' a       当MT=3时,表示对方通过你的验证 4 v/ t4 B$ M+ W1 f
       当MT=4时,MG为对方拒绝你理由 8 C! N9 ]6 ]% V) [" X0 ~

% u& J8 i: ^! Z(10).发送消息 7 p. Y  A2 g  K) {. U
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 ; }% z, W- a( Y- G
+ v  x' D2 k  X/ f4 t1 T. |/ Z
  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) $ P( F& c" b/ u5 s5 L* B
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
! u1 Y0 |& D, p/ W/ d; m. z     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 5 R8 M5 M) o& U% B' ~
     NULL(UIN、UN为字符,MG含非UTF-8字符)
! h* O! `! M8 z! i! z9 z  U  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
* R4 J3 m$ u6 a. b       你俩互为陌生人,且对方没有和你说过话 7 D  P* M& X( o# H, h% H7 j8 `$ [1 V! m
       你在他的陌生人列表里,并且他没有和你说过话(没有验证) / {+ g% D8 B& f# W6 d" Y% j1 H
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s ! g3 @+ \+ S2 e' i* b9 H& J
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL / l4 {5 [; U# L% z
; S3 B6 S, J" Z2 ^: d
(11).登出
; t1 o  |, o9 e  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
. w8 J! C* O4 y' \2 ~
) ]# d( W1 T) H  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
# }/ e! M4 @$ n! z) t5 t     NULL(UIN为字符) 4 I7 D6 B8 Y6 r& `0 `: K
" M& u5 q6 q4 W; F8 F& \& n
5、总结
9 n' t; h. J2 X$ W: G8 j
! ?0 X: j: ^: S, w" V4 k. C  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
! X8 j8 t1 }+ Y  n- O; }- U& r  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 $ ]3 g4 _7 O4 e. F- u( r
  本文撰写时间仓促,难免有误,希望各位不吝赐教
1 z) Z2 V% `) v1 ?, n  y3 O" R
5 [+ x+ p  o* _- h, \! `7 M) U) T* _. [: i: M
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-6-18 06:53 , Processed in 0.025585 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表