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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
& ~8 Q% \" c8 s2 {/ M; o日期:2005.8.21凌晨
7 Z: J' e; o* L- u/ L. m联系:QQ:106814 Email:hackfan@vip.sina.com
# X: q! b  E/ H0 F8 J6 L  [
' }. c+ r  o; {, f# S1、研究说明
5 |; t8 d5 M& S# z$ @% }" C# u: W5 L0 R1 R6 l- e7 B( P9 _5 @
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
, G8 P$ h; F9 e3 F
5 q) z9 m! ^& E! _! L  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
3 V& R% s( T9 M' j% w$ t4 U( Y5 _1 p% e2 b
2、接口说明: 0 ^5 m( L0 }- ^& Q- i  q# Q
9 x$ F: I3 Y9 f: e# [
  接口位置:tqq.tencent.com:8000
; o7 E1 h& W, ]5 K. v  通信协议:HTTP ! G" N$ C6 G. `# z; z
  数据传输方法:POST . o# s" h3 F* K' |
  HTTP请求格式: 2 l6 ^1 D9 r7 [9 J) Y5 j3 Y
& s3 M( w/ D: E5 d+ r* M/ e
POST HTTP/1.1
) ~/ s# k' C# q+ GHost: tqq.tencent.com:8000 9 U1 l$ i1 F1 X+ j. Y
Content-Type: text/plain; charset=UTF-8
9 ^8 @! Q+ e$ F, p# p4 xContent-length: 长度
  K5 m# J& F# A2 x7 qConnection: close 1 y/ R+ x6 c. \5 f
7 T. `' V+ O+ E; A
数据 , g' K0 K8 @, M0 c

6 w5 q1 x( ]9 f9 s  其中长度为 数据 的长度,数据的格式: + U2 q! w  u  J/ T; J) {
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... ) R  a: d- F" |) S2 h8 C
7 |* d8 b7 N0 v8 X, v2 y
  以上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还需要不同的参数,下面我就公布我的研究成果。
/ g, I: o& R3 t. p" T, k9 |- g5 ]
  `2 R4 [: U' X4 _! x2 K3、研究方法: * x7 x7 l/ O: A$ B

6 J) p# e1 E) F, p  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 + v+ V4 @* b! K, i" |
  下面我公布我探测的代码(PHP):
  1. <? 2 K+ y1 N# ^( W1 g, {5 X& p
  2. $uin = "QQ号"; 7 ?1 ~3 h7 z' ]5 h
  3. $pwd = md5("QQ密码"); 0 E2 z5 d; u: |) f
  4. 8 z- e0 ]6 f. a+ w
  5. //登陆测试
    / z! o8 _- \6 Z) i$ F5 D' }/ ?) V; t# N
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    ) {# N& s* [" Y
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 6 h- A1 x) G5 ]& G- N. y, |4 m" n0 w
  8. /******* ; [- S; e4 g, K6 w. U
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    ; n$ Z& c2 |2 t6 _* \- D
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    + E1 e1 [, A5 s. q( K' E: w4 O- z
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; & }% @8 _; P' L+ I
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; $ z3 Y' a0 w% X# S# _4 D9 \- n
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; . Z+ L& D; G7 K" J+ |
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    , E% I/ t  T3 N: w6 A# S0 Z6 ?6 B. r4 ~4 h
  15. *******/   s3 u% D( H  {. C- C* m' S

  16. ; @8 K) |3 s' G  B3 x
  17. & g% m3 ]4 ^% g& H' G: k% a, ]) t
  18. //得到好友列表 - U' U4 X5 X0 v9 h  R3 \) ~
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; 1 l* l4 c1 R- ], `
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; - B5 E! m/ q. k6 a+ h4 {
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";   x% J2 D: v8 s% C( {* j% Z
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 2 }; F- d& A1 L' G+ p4 W6 N
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 7 ?$ C2 C% n2 a* w  ~/ m5 l9 p
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; / X- K  H! b# K/ F# \* h
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    & M& z1 L4 Y0 h" f
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 0 o- {6 }9 J, h0 e0 K
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; + d0 p6 x& n" N7 H
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ( N9 k* @+ l; |. Y' E$ Z; N& B" N
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; : I1 C$ v- I6 U8 n# }
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    0 G) N+ ^2 A4 c+ q! a
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    - o* B6 v9 o: y7 U7 z
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    % ^, C1 @; ?' |: B0 ?
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    . Z/ J' z9 f7 \2 \) U6 ?
  34. 2 f; V7 f7 Z1 w1 |- J
  35. //得到在线列表 0 `& j$ E4 M( M* y5 l8 i" r' q, }
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; / T6 L( q8 C) t# e1 j
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    . y+ w$ D5 K0 s) D- h) N
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; , l. q9 [7 K& O6 a" A+ J0 ?9 R- }
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    $ y' J1 s  v  I* }$ Z
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); # M1 O2 i" }: {8 f1 H
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; . X* `2 w# @0 t& R# o& Y  u" j/ P: ?
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; - X# Q, y- H5 o; C+ @2 O
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    + O, x0 m) C& F/ i3 e
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    7 Z% N# i# C! d; {% `5 [
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; : o! K5 h' x. d- a1 i8 T
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    & K+ w( n" y1 Y( R6 `5 s7 a7 O
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 9 e* v% I4 [9 k8 M: i
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 4 `6 v- N% R! u& L9 P5 t9 ?8 J
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ( m/ g5 F) r; ]- |0 b+ L! F# P# j
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    + K# U( Q& S: S3 N3 v. N

  51. 0 @: |4 R7 ^; [# o
  52. //查看好友信息 ! |) W8 q5 @! A" X4 ]# s
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; ( B. E  h$ Z; R! m4 n% @1 F
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    3 r8 j* A# q4 e" [! r
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; ' K4 C( k1 Z' ]
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    5 ]+ r* ?. U+ v( Z* e
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    % N! [) l" C, J  E3 y
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; 5 w6 J4 h* P  o

  59. & H7 E. M/ j# K3 T) g( K& Z' i" Z1 d
  60. //增加好友
    9 S% x- }8 m/ p8 Q" z5 b+ v5 D& w9 Y$ F
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    9 o! e" N% g$ v/ f* o  \
  62. % f& ^& S& i. l4 U9 l
  63. //发送验证
    1 V/ M5 _6 z/ q4 V
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    , x" m6 f& i2 g% _% f
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    : _8 n# i8 w3 v! a3 T- F5 W
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    / o; N, z. h3 s6 w( m$ A) W
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    3 c& |3 \. w; ?. \$ ^- O; T8 q
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; 6 f/ r/ f% O; d, \
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; 4 F- w) b. C, u0 K* G

  70. 9 ^$ e% ~; ~/ h5 ~- n
  71. //删除好友
    - W( ?9 F6 W+ f; J1 a
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; " l& W% Z* S6 T, \* i
  73. * @* I) L* v  h& e7 J8 c/ O
  74. //改变状态
    - y* C5 G- l1 p1 z2 w
  75. for($i=0;$i<=60;$i=$i+5)
      N/ U8 d0 n, v3 q
  76. { 8 p5 w4 ^5 r' M4 e. x
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    ) D+ S4 s& m, E4 `' S$ ?
  78. } 7 u( A$ }4 |0 Z
  79. # r4 _  b0 g+ \! x% @
  80. //获得消息 : c, v$ y3 B/ X0 s& @" f
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; : D$ O( z9 K) [# i
  82. 9 E& h8 D" g- J  }5 N% @
  83. //发送消息
      T/ Y2 P/ ~$ B& s$ I
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; ) g( b4 B& `: j8 J
  85. 8 s: A  a4 u0 _! j
  86. //登出 / b, I. d: |& x
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    ( R( c. M9 S8 O6 P7 i- A' a" e) H
  88. 4 B# A) x% ]/ C3 o" e
  89. $file = fopen("p.txt","w");
    7 k% j* i; f3 H* |9 ^
  90. 9 ]5 G* x& l6 G& D
  91. foreach($poststring as $k=>$v) . h0 z; v) }8 B! o) ?
  92. {
    2 R( f$ S6 y' x" F8 c1 {+ p
  93. ss_timing_start(); ( a1 s8 p# m# t8 C( R
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    ) L2 W+ n& y% T% J0 g
  95. ( O4 P# t6 J* o' e
  96. if(!$fp){  
    4 A! [* A$ L7 u2 t$ U
  97. //error tell us  + I3 x, ^. u: k! D
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    5 K) o7 e( J' U4 U# J
  99.    & Q! q6 g* V8 G& l8 R5 @2 j9 L+ ~1 |
  100. }else{  
    2 ~* Y8 I+ F; ^# D- j0 ?

  101. ' |: m4 W3 O$ r$ w. n* z
  102.   //send the server request  
    0 G/ p4 ~: m. w0 v' _
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    ) M6 ^% |; M8 y9 c, b
  104. //  fputs($fp, "Host: $host\r\n");  
    # C) p! f, A/ b2 h% k5 I
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    4 K7 K/ {$ h0 }- `
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  0 C# t8 F4 k2 V2 e
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    + k8 g  m/ A. p& K) R
  108.   fputs($fp, $v . "\r\n\r\n");  
    8 d+ c1 s* O& ]8 M9 F5 Z5 E2 ~
  109. 1 ~' W) o; ^3 ~
  110.   //loop through the response from the server  % y1 |+ e9 ~$ r& o1 O; a0 K
  111.   $res = ""; & P& r% e3 M9 C$ E: ^
  112.   while(!feof($fp)) {  
    & J  o; e0 _  l3 \
  113.   $res .= fgets($fp, 4096);  
    8 t1 ?! h5 r/ L/ V! ~* ^/ {
  114.   }  / m5 @+ J7 _2 K( o& s/ K+ \
  115.   //close fp - we are done with it  3 q0 Y" _. X0 H9 X0 E
  116.   fclose($fp);  
    4 H$ L' B9 [& X& F
  117. / S" ^* _* _  Q2 e/ A/ f1 q
  118.   $content = $v.chr(13).chr(10).$res;
    3 Q! H7 k1 c  D2 S1 {
  119. }  
    * ^8 ?1 F- U' D' b
  120. ss_timing_stop();  - i; g: O1 \7 d  Z
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); . }- n; S! ]: Q) |+ g# S: Y" J
  122. fputs($file,$content); ! w/ i( H% u3 `# Y
  123. }
    : k4 N  q3 t9 ^
  124. fclose($file); ' F- G% o, w4 _- W6 B" g' ]5 P- M
  125. ?>
    " ]) h+ R2 D  v1 M
  126. <? 3 U6 ^* @* q. `  y
  127. function ss_timing_start ($name = "default") {  9 `+ z! M. c' q$ D4 D! ?
  128. global $ss_timing_start_times;  6 K* Y6 R7 }' J  i
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  9 _% x! Z5 D( h) T
  130. }  0 X, Z, _% r+ e) h; m4 ^, h- H% G
  131. function ss_timing_stop ($name = "default") {  ) W% j6 o0 W2 v  ?; ?6 J
  132. global $ss_timing_stop_times;  
    " g7 u: }& t: {8 k% f- x: _2 _- |
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
    * D5 {$ _" `: d% w
  134. }  3 ?9 v$ D! g: M  p
  135. function ss_timing_current ($name = "default") {  . U6 K  i3 k# P! A8 W6 @
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    ! |  @3 u+ M  Y1 Q7 P
  137. if (!isset($ss_timing_start_times[$name])) {  
    & u0 @9 t) M. `( N
  138. return 0;  
    " m/ N4 _5 j7 T3 `
  139. }  
    - n& s# ^/ N% ]% u- d9 s% T$ W& s, U
  140. if (!isset($ss_timing_stop_times[$name])) {  
    / W+ N+ E3 [  l* z4 _
  141. $stop_time = explode(' ', microtime());  ; h2 M% C7 M5 F5 b3 s
  142. }  " _. y; r1 g2 m
  143. else {  
    - {1 F# G5 Z; ]% o3 h
  144. $stop_time = $ss_timing_stop_times[$name];  5 U* E$ c4 B3 c: U% H# p
  145. }  : {# r* U3 ]& r
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    , ^7 S  N6 J5 P# U+ k6 A  z
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  ' x/ ]2 `9 M- i% x8 V+ e: n3 M
  148. return $current;  
    ) A# y) E  B0 o1 G2 c2 V
  149. }  / D$ l  ^4 e6 P! h/ k3 s
  150. ?>
复制代码

6 C$ r: C. |' z3 P4 V* K0 ?( e4、研究成果: . P! {7 N0 u8 u, K2 E! K+ R7 a
& g4 k* w6 n6 I7 d$ y2 y# C
(1).登陆
% T; x& J0 X% j; S6 ^  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
: k( [: H$ ?3 M  }7 ^. t+ k  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^   ~! d& f  j* c

7 `) l8 P+ B' {$ |  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 & \* ?" s( W8 ^6 y7 v
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
; C5 V' B) H0 k$ `( H0 K     M5这个参数的作用还不清楚,但最好为1。
# q$ H) n4 m% Z4 H     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
# b) s0 O3 ]/ S5 m# i: U" f
4 v0 T: V0 ~, f! g6 T' Y5 z  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
8 `+ ]% R. |/ Q+ @) a# q     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
, M$ W- o2 y: r0 v) P$ C/ k9 S$ k: p     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
* b- O1 N! f, ]3 ]$ U     NULL(UIN为字符、PS为空、LC错误)
3 [+ y6 C% v5 _
7 ^' `- U  d# i& _+ a. W(2).得到好友列表 3 e8 n! P1 D2 ?: C# ?1 H$ e, u
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
6 J6 o  {. y0 R6 j$ j4 Z  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 , M: E+ F. _6 S$ a$ f) w. @- X' _

0 G2 Q6 S: R/ a; z2 F. H# u  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
7 z. K" ]; d) e6 q( K     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
5 C  ^7 J) Y, E9 U( C# V7 n     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) + h8 P) w" Z# c/ c" d  A4 q+ r
     NULL(UIN、TN、UN为字符) - {) i4 L* [- l; X+ f1 `
& s! v6 F8 W" t& b# V; a. }2 Y. v
(3).得到在线好友列表
* ~; K! }/ N* Z, o9 v' n  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 7 a* D3 d7 Z+ Y
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
9 A+ n: ?) b$ o$ W" u3 F( H9 C# S. }, z# u) W; `
  返回: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的值用','分割,分别表示头像、状态、号码、昵称)
1 S) c. v0 u! M: o% `) N     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 8 ?" \4 F, X" z1 i
     NULL(UIN、TN、UN为字符)
5 f& X" y- ]* ?1 u5 [( e  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;   S' x( w6 _1 ?+ B6 {4 Z) T- T
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; 2 y1 i8 @, C6 i& j! B3 A7 {

" G- B; R% \9 v  特别说明:当参数TN=0或不存在时,服务器返回: 3 X; D: }$ V# z4 P- V2 `! T+ ^
VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 2 H' _) [+ L) v/ v1 g
HTTP/1.1 200 OK ' ~1 \% B  m- x6 _) ?8 a
Server: tencent imserver/1.0.0
" Z& x; F" ~  S! U& ]Content-Type: text/plain; charset=UTF-8 * y* p& W+ l5 S* t" j  c0 U: p
Content-Length: 56
# a) L# v" V4 j! [- d2 ]$ u  j4 k2 l( y9 @
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
# o" Z3 p6 B/ [, d+ L( Z' PHTTP/1.1 200 OK 1 W- u/ Q9 M3 F+ P% U
Server: tencent imserver/1.0.0
: N0 m8 G0 |* `4 c  kContent-Type: text/plain; charset=UTF-8 $ J; \6 S! k5 z2 b5 i" O
Content-Length: 77
# H5 A3 k3 y: V3 V5 s3 `
- }4 Q$ N- C2 ]  z& v4 H, sVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= $ v5 h% y7 V  {3 M3 S
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
" w( C! D- c9 j, X) E' H" Q9 k, |$ ~& T$ V* G
(4).查看好友信息
2 q! ^( ~2 @. P+ g! ^2 d6 C% m7 W  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
* w1 t4 R% }6 n4 M+ T6 c, i  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
  j: r: z6 f8 w0 t: a9 u( J% x" T7 h+ X$ N+ ?
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) 1 d+ E8 ?; O5 J: o1 o+ x, J* z
     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=学生 ; m7 C6 q3 W/ i# w2 |
&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
0 v( r! `/ b% N好(普通查询)
6 f- n. f5 K$ a: e1 _( o* d; P4 O9 Z     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 6 c' v! j  L2 Y* _( f* N, L
&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  . k; q# U: l; p& j$ l
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
  T  H5 Y! a- G( x0 z3 T     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ' m1 q! [" R1 o, i
     NULL(UIN、LV、UN为字符)
1 ]! j! v1 A1 J# _+ Z# m' z' m
5 T" ?6 D7 C4 ^- u# ^: [! Q  说明:AD为联系地址 9 n4 F7 y* D. L% e
     AG为年龄
4 a- }5 f5 ?5 z5 ~5 i% I     BT为血型
; k3 q( `1 Y3 n1 L     CO为星座
  o: h6 `& }+ N6 ~     CT为城市 4 H, t" `& f' @; B' M' i% {# s
     CV为未知*
: N7 d9 l( r6 T9 q     CY为国家
8 Z- ^) ^" k: D; R. w, s. q( ?     EM为Email
# P- X, V7 U6 K- A0 f/ p5 n     FC为头像
& E9 u1 c7 L. n4 Y     HP为网站 * U) \+ y- ], h+ i4 v  l( L
     ID为未知 & n" w8 ]* }+ J) q
     JB为职业
3 K* z4 i! G1 _  V' I9 W) l1 n     LV为查询代码(就是发送的LV)
5 X7 g% w: N0 U$ E9 l- o8 @4 @* d9 |     MO为移动电话
$ J' N" w) W5 g* O- t     MT为未知
/ [+ H0 W1 O: f# i0 T     MV为未知
7 d$ C: F; x* X; ?: ]     PC为邮编
  u- e. `9 v, |. g     PH为联系电话
/ r7 Q7 a! |, U  L7 D. w     PR为简介 / Q0 T, `! f5 Z8 s: E- _
     PV为省 5 x4 F9 {+ F$ V: L* J: K
     RN为真实姓名
$ |8 e% D" G" W# m# M- T     SC为毕业院校 2 o8 ]" S: Z& e2 k  r" K
     SH为生肖
& T$ P7 }7 m6 z7 z' C0 s% p% X% p+ N     SX为性别
5 z1 r5 _& P! v3 k: W) p3 W" Z9 ^  J' l% o     UN为QQ号
6 ]/ Z6 M6 H. _4 y/ L8 y( G9 q& r% ^     NK为昵称 : R0 Y3 K) O7 ?2 u3 S4 i0 J- t4 q

9 G# Q$ c7 o1 G6 v8 A' P5 J7 h     血型:0 => '', ; h) F4 [5 \& e" U
        1 => 'A型', 8 e8 B  A" e5 D
        2 => 'B型',
" A, o- E" D$ _5 a" s' K" m        3 => 'O型',
, B3 k/ B. D1 j( U3 A) ?9 i        4 => 'AB型', # }# t6 `, P7 f- S3 f6 j
        5 => '其他'   g: K% W" f# I' W$ ^2 d$ ~& p& Y- c

$ H* d" Q' E6 q' H+ H. |$ o  O) ~3 h0 l2 k, A3 d, A: L
     星座:0 => '',   v+ ?' ]* ^3 k% Q3 E0 A9 s) w
        1 => '水瓶座',
5 n" l9 n" N; @1 ?7 k        2 => '双鱼座', 9 E0 e' e8 V! U
        3 => '牡羊座',
2 H3 [/ U/ S2 p% [) i; b        4 => '金牛座', 9 g- m6 o6 ?& ?* q/ T6 z2 `
        5 => '双子座', # R: X0 v7 K( V0 U6 N6 O5 _' d& ^
        6 => '巨蟹座', $ i8 j  U" Z9 `' |/ Q$ {/ w
        7 => '狮子座',
( o* G! I/ Y8 Y* W        8 => '座', * ?$ e6 \4 K8 U/ ?+ P
        9 => '天秤座',
) p7 f( z2 L  B0 F' z        10 => '天蝎座', ) h  s4 a, n+ O* `
        11 => '射手座', - }1 @9 X6 A+ ^1 j9 u: p# I3 h; z
        12 => '摩羯座'
9 n6 q0 }* @* e) d" G
1 f( ^# H2 }/ }8 a4 k( N9 f! O     生肖:0 => '', ) H6 _/ z7 K# c8 h
        1 => '鼠',
, f+ ~: d8 ]7 W  R! J" v8 e        2 => '牛',
: D% y/ ^9 D: S        3 => '虎',
' A) a- t0 F0 J, `        4 => '兔', / Q6 _0 r$ O( f3 [
        5 => '龙', ) u5 f" I- ~9 |$ r3 f
        6 => '蛇', $ o6 ~2 Y6 ]7 @0 }5 [3 e- y+ j5 ?
        7 => '马',
5 f) v% P1 R# H        8 => '羊', 4 `8 E- d- w! c/ a+ H1 r6 ]
        9 => '猴',
3 ]3 `# Y" ^( {* h5 `2 f) ~        10 => '鸡', 5 H- L3 e5 w( y  m' k
        11 => '狗', & V& J& d1 A% K' s
        12 => '猪'
1 {  J# d7 @9 ?4 u5 R2 d5 D: u
1 W$ L& h' Y* b# Z3 o     性别:0 => '男',
; p& n; ~/ E$ E8 A0 k3 h' ^2 L        1 => '女' 0 x* r7 ?. ~& @# w) t! H
3 {. M/ K6 @* Z+ u" |
(5).增加好友 ) o: X4 m0 q6 T1 _8 G
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 6 [) \) g" j5 A! A7 B
  _5 C& W, C/ ^& ?! K/ p
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
1 F( M  M+ B2 ]# _& A     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) 9 e0 o5 A1 E1 Y/ E
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
( {2 K3 A1 X: ]' L2 r! e     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ' o5 S7 J5 P+ A6 \) o6 A
     NULL(UIN、UN为字符)
' d1 h5 l5 m3 M6 ?; f% d4 n
! D' [- f) _1 ^$ u(5).发送验证
2 B; [/ _$ d6 h' a. p3 \0 e+ y  说明:1、如果你加对方为好友,你需要发送验证
' L- }( d0 R" l' J( B+ g0 f     2、对方加你为好友,发送了验证,你要通过或者拒绝 ; {1 Q6 B! F. p8 g- K* N
     这2种情况需要发送验证消息 * u+ l; f; w6 o' f

$ y) U% ]; i5 h5 A' j  {# Q0 y  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 , z4 G1 p. T% y% M4 T8 p9 u
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
8 w1 m6 H6 X9 S8 e* }
7 V8 F7 O: F2 `7 _) {- A$ q  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 5 B' u3 b. q' l5 p' n& U7 Y8 ?8 t
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) 4 |  F" n; X" J
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
+ b1 M5 R7 \+ l- z. ~2 X     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
7 J5 ?. X/ F  ]+ V9 O+ D& z6 J) Y9 W  H  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
6 u( z2 Y! K( Y6 F( T8 t' k! N$ B" d) w8 x
(6).删除好友
7 Z. `; H- F% ?! z1 w  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 + n  m; X; m$ D& J3 z) ^

3 t! S0 w4 F3 I. o" g3 y  l7 ?* h1 Q  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
# U9 M5 s. I- \1 \8 f     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) 1 m# U# Z% h) R' e
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
+ ?6 _" b4 X. Y* D0 f$ Z; N     NULL(UIN、UN为字符)   r. T" z) T: ]# w) W
8 J. a. K$ |; c5 F- J
(7).改变状态
& k% U+ [% }4 G" z  k5 Q  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
' O2 m& r4 G+ |. H1 U& ~* B2 w  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 8 V+ V* z  u( u9 K) O" \2 _" U
1 f7 }7 H+ P; l8 ~& g: T
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) % `* b' c9 t$ j* D, U! E8 z
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) ; m! ~0 y/ m3 D3 ?3 P
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) " o# O, S3 E* y* i$ s# j  h( a
     NULL(UIN为字符,ST非法)
) n' w& `$ d% C1 j, x& B2 N( G5 C- I: y" A& ]
  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
9 i' v* C. w: d       同理,当你的好友改变状态,你也会收到一条系统信息。
2 _& G3 E  j: B+ A. f; Q* y" g* H" H: c2 }+ ]+ t
(9).获得消息 & c+ b# L4 m, [, a' ^5 B  Y
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
* l- }2 D0 v6 G/ Q  I9 B
6 k& R4 B( f) T( F  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) $ g& m" g& Z( a8 H- w
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
* W+ `( t& s3 x0 `4 v- J     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
  `2 P9 t. c2 u6 A     NULL(UIN为字符) ; R. Y( l# f9 }+ G( @( _
  说明:关于MT:   }9 u& o! K9 e: z5 Y
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 3 y3 o2 z5 R7 k
     关于MG: - R0 |* J" g- [4 t( q: s
       当MT=9时,MG为用户发送的消息内容 ! a2 `% Y$ X+ o; `
       当MT=99时,
% t8 B0 |) d2 @& x! _( o7 C% i         MG=10(QQ_STATUS_ONLINE)表示对方上线 ) ]0 c# S5 s7 D. g8 P& ?
         MG=20(QQ_STATUS_OFFLINE)表示对方下线 0 b$ O* f" j0 S1 Z( ^# K6 ?/ d9 i/ |
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 7 j) X  A& q/ O; Q" q
       当MT=2时,MG为对方请求你验证的信息
+ D' x" s7 }. k5 z( L9 n4 R       当MT=3时,表示对方通过你的验证
1 _" |; k5 c  f5 ^# _       当MT=4时,MG为对方拒绝你理由
# L7 \- T- P% r! J* k0 S+ h# n( z" n( P+ Q" O! k" [& Z
(10).发送消息
: z' K' n( G0 W  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
0 m2 T3 @( i0 {0 \% ?8 C7 k
+ P$ l/ d6 _2 P  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
' h7 D3 w5 C. L9 D6 J     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)   V; x9 ?3 v3 U" N2 x. M( C
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& i, _  C3 d% v% \0 c  I     NULL(UIN、UN为字符,MG含非UTF-8字符)
6 O  e% u" N, K5 I* J- k  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
/ [* g5 K- ]& J$ I! h2 c       你俩互为陌生人,且对方没有和你说过话
9 x9 m' s" |& t       你在他的陌生人列表里,并且他没有和你说过话(没有验证) : o; ^- T* B9 f
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s - m5 s( w# T; `
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL : _) ]$ F2 c7 Y1 W, _

8 z9 t% @/ d0 [, d(11).登出 ( R2 B  N9 }# {0 n# [
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
3 g. a; x9 x9 e! [" I& B4 B; B( J  M5 e  m5 t
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) 2 J' R* c+ X. b" x
     NULL(UIN为字符)
* Y  C3 ~) o$ Z" M: {  R5 k- j* J9 }5 n  k" m1 ?4 A
5、总结 ) B; [4 L4 K  z' c# L0 Z4 U; _

: B. [9 q" r7 Y( L  q2 `6 E- o1 U0 m  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
1 x, y3 ^6 Q/ Y1 C5 n+ T  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 ; @7 T' s1 \! i
  本文撰写时间仓促,难免有误,希望各位不吝赐教
. J- H) C1 n  a7 w+ r$ x: k7 D+ ]
- v8 j  b. Z6 R5 x0 k) T1 g5 @' N
4 i2 {# B0 T  s7 S- K8 U0 iTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 18:06 , Processed in 0.020174 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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