找回密码
 注册
查看: 6075|回复: 0

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者: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. <? ( {1 s* p6 q6 c9 Z$ y3 ?
  2. $uin = "QQ号"; & Z7 N$ P; x* W* y
  3. $pwd = md5("QQ密码"); 4 @5 w: ?/ c5 H  `& e
  4. # p) T( H# L4 n# {; N
  5. //登陆测试
    ' O: N# j0 {. l; A8 V. g2 W6 `/ R
  6. $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
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 ( ?; ^- N. I& O0 s5 I" t1 [! X
  8. /******* ! V$ O/ e6 l1 c, w
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; ) L4 \. }4 s) `
  10. $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
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; ; O6 ]" w1 w; [) M
  12. $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( ]
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; 8 a3 B# J9 ?. L. ^( z
  14. $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
  15. *******/ / Z2 H  x" P( Y& v3 U$ B  _. `

  16. ! U7 J  r( {+ b. S' U( q
  17. $ ^5 f0 |* S4 q+ f0 t1 O/ a: @
  18. //得到好友列表
    7 d1 q4 M/ z, F  x4 A) i" l
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    2 l" {; w1 o- j+ t, L
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; , \# z6 \1 M  |: Q( j: S' [1 ]5 U- C
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    % C% r. X" L/ I$ j- _+ I& R
  22. $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
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    ! L0 T; Y3 I  R: J! b
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; - s! p6 Y" s; T
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    : A6 f8 D6 @+ {( h4 i
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 9 v8 |  H) v/ j" G8 I& f
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; - a0 z, [  t: B* o
  28. $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
  29. $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
  30. $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
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    6 A- P/ _# E* o- ?
  32. $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
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    7 d, y- Q/ ~- Y& t3 Z

  34. ! Q) ^* e2 `) e, f. ~- S
  35. //得到在线列表
    ; T0 |3 J9 L+ n5 z8 B, ^
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; ) N4 b: d7 c! s7 s$ a5 t7 I& E+ _
  37. $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
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 1 ]/ \2 P9 `* H! ]; Q; U
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 4 a. B5 F" f" B
  40. $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
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    & {& K! |8 {9 @& |
  42. $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. [
  43. $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
  44. $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
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; % k. U& U" ?( \  l- X
  46. $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
  47. $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
  48. $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
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); / [( M6 D0 e$ I* k
  50. $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
  51. ) L7 \# k" ]: k- Q, h$ e( t9 g& \
  52. //查看好友信息 / z* m, I' P  s. ^! p
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    % l/ H" g% q9 m* o
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; . {4 l% E7 l4 w! E/ F
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; - s3 D5 N, g7 a4 t( H9 ]
  56. $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
  57. $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
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    " A5 w1 |+ }& F2 Q0 S4 a

  59. 5 }2 P% ^  z0 M; w6 c
  60. //增加好友
    ) \7 ^+ S% ]1 X
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    5 G* F! |' S) J# c8 ?

  62. 7 `! b5 J, R7 N0 c3 R
  63. //发送验证 1 A( L2 `1 ?2 ~3 I4 X  X
  64. $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
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    ' u, L* ~' q* o
  66. $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 [
  67. $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
  68. $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) \
  69. $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

  70. , v, z( r. b$ j: ?- ]
  71. //删除好友 " I, c! a9 w. I& e: L
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; " |# P$ w9 A) y" d

  73. ; ]2 R1 Z# B  M2 l
  74. //改变状态 4 L' |7 T7 X. N0 W
  75. for($i=0;$i<=60;$i=$i+5) 4 @7 t3 ?, Q2 k( X. `0 X2 l
  76. {
    % g* Y) ^$ a  V9 K: s
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    9 z* w( `5 W0 c
  78. }   T8 Y' h4 X; b. J

  79. # ^, M7 i9 S4 ~; @
  80. //获得消息 6 [4 E8 V1 p9 j
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    % @( A3 C* }8 }1 C% h3 a
  82. 9 k) w2 q! o! k; F% B
  83. //发送消息 & g/ E8 H% F  Z: O1 }8 b
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";   O9 o$ W  D% [9 f& r
  85. 9 O( T/ P3 ~) `; J
  86. //登出
    4 {1 x: J* ~- _1 `
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    5 _; V- V) G( F8 a/ u- j1 Z
  88. : C! O! D/ }  X0 ]4 {
  89. $file = fopen("p.txt","w"); ' J3 ?" d: P  k( F* G7 `

  90. 2 q: \' d' `0 ?7 T
  91. foreach($poststring as $k=>$v)
    ( O2 l0 O9 W) {% A; O
  92. { 5 w; y5 i: o' u: [3 Y; y0 B$ C1 i
  93. ss_timing_start(); 1 \5 h* I& V2 M  S9 l; r- E  x
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    / i# q, n1 W' A7 s: f/ }# u; U( [

  95. ' w: l  a9 J7 K. S* F" N# O
  96. if(!$fp){  
    $ s9 ?6 _5 I8 s1 V' @3 S$ `) z
  97. //error tell us  5 p, a9 v6 W0 ]6 E( p. U
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  7 }3 _& v1 I# ^1 S  G7 w4 ^
  99.    
    - T0 S7 y9 x0 L8 |' U
  100. }else{  
    4 G- r, |) p0 O8 n5 b8 a

  101. ! \$ D% Y+ ^2 x: u6 G6 c
  102.   //send the server request  5 @- m. y4 N8 Z# J3 h, i
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    . i5 z& P- x; v7 V
  104. //  fputs($fp, "Host: $host\r\n");  
    % L& ~. Q+ ~' a* `  P) F
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    ' V$ P& l7 t& Z0 R3 H
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  0 e4 @# w& k0 u' s9 [
  107.   fputs($fp, "Connection: close\r\n\r\n");  & f) P' `. h, R4 a1 ?3 u. Z- U% Z
  108.   fputs($fp, $v . "\r\n\r\n");  
    - _) r7 v% k5 q0 G

  109. 4 z$ a5 o1 ?9 f5 e( `2 y% p/ z' U0 I
  110.   //loop through the response from the server  2 ^2 S- ~: {/ Y* m# G* U$ t0 v
  111.   $res = ""; 6 o6 c+ P2 ]" a3 e6 f
  112.   while(!feof($fp)) {  
    - l5 P- h) }" g2 `0 a8 o
  113.   $res .= fgets($fp, 4096);  % ]; I) n; m% ^
  114.   }  ' @: Q5 M, b' R  u% \2 I
  115.   //close fp - we are done with it  
    / F; `* f8 g# m
  116.   fclose($fp);  % N: S" K3 n; q/ P

  117. . C' G3 J- J, f: v- g
  118.   $content = $v.chr(13).chr(10).$res; 8 U3 @/ e* L4 d
  119. }  : n# q' p+ k9 Q2 b) r4 C
  120. ss_timing_stop();  
    % V/ D5 g4 s2 P  x5 n
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    5 j& `' I% q& B3 ^; Q# }
  122. fputs($file,$content);
    : m4 Z) q4 W8 v/ X% b
  123. }
    $ p0 x" c; z  g+ ?5 ^# @+ x
  124. fclose($file);
    , w1 v/ K6 V  e3 M
  125. ?> - f# Z3 G3 N+ X: U5 k% |
  126. <?
    " k  o. N, f. c9 z3 E
  127. function ss_timing_start ($name = "default") {  
    , O1 t+ b. _. h8 l
  128. global $ss_timing_start_times;  
    $ ^$ ?/ q! L- A# w+ |
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    * s- Z7 L7 U: x+ k
  130. }  % c% M( [  @0 ?: L8 A
  131. function ss_timing_stop ($name = "default") {  - W. d3 e3 E; J$ {( Q
  132. global $ss_timing_stop_times;  
    " f) ^( }, H1 F& p, O
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());    H2 x, p, n9 b9 Y8 J8 w8 d( E
  134. }  
    , \1 F4 r2 g- V+ i1 o
  135. function ss_timing_current ($name = "default") {  ( O" I6 T; U9 t
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    ' Y; R2 h* x4 F" p4 m) |( {
  137. if (!isset($ss_timing_start_times[$name])) {  
    ( m; m  e, P! ^
  138. return 0;  2 {2 c# {5 |) V/ ~8 D
  139. }  
    6 Z' o: k; [4 |8 ~2 D6 H3 ?
  140. if (!isset($ss_timing_stop_times[$name])) {  
    4 B' c" W8 l0 R9 p
  141. $stop_time = explode(' ', microtime());  
    8 v1 X5 n9 A/ s- c
  142. }  + g8 y! l, ?2 f! F
  143. else {    C( U) R9 {2 `0 L; W, N! ?5 k
  144. $stop_time = $ss_timing_stop_times[$name];  . A$ E7 M: t8 ?, m% ?) v
  145. }  " B9 Y5 F( ]: D# d2 z
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  8 w# b4 e, i& |9 e7 S- F
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];    a; w9 C. C0 s* n5 f6 L
  148. return $current;  3 p) N' R9 a6 _& N6 V6 [
  149. }  0 j& T; W6 O, R# o
  150. ?>
复制代码

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
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-1 20:51 , Processed in 0.018168 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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