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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan " {% @* M+ A, i$ q' t0 N
日期:2005.8.21凌晨
# v( V! X4 p) v) C联系:QQ:106814 Email:hackfan@vip.sina.com
; y0 z1 m$ i  G$ [
" h# H5 J2 _, ?0 b7 t# q4 [1、研究说明 ! m3 K/ C2 z0 t  y, A' G7 U0 i! U

4 m$ L# G. I& r  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 ) e; Q$ p% I! A; D0 r- \# |& ]

# I# @0 t) f' B/ a8 u  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
  _6 \& A  [6 G) P
8 o1 p2 n8 s$ n8 f# L( {) s3 u2 P; C2、接口说明: 2 l8 G# ]6 O1 p* I$ R
, n# r* y+ J2 D4 _8 Q/ N% I
  接口位置:tqq.tencent.com:8000 / H( H" a( V9 z& s' C
  通信协议:HTTP , n4 q$ D5 ~  C/ i. G6 s
  数据传输方法:POST
; V" `- A0 O- ^" K( ~& w! v& T  HTTP请求格式:
$ t# H3 Z! g/ l2 I" z' j! n- J1 i4 Q! k) }: D6 \# g
POST HTTP/1.1
$ ?" p2 s4 z$ ~5 c: {0 kHost: tqq.tencent.com:8000
7 k. _7 I3 Y: n- z4 l4 IContent-Type: text/plain; charset=UTF-8 ! m; g# ~9 h% y% _7 V  l7 p
Content-length: 长度
/ L& e1 j# e, N* BConnection: close
7 T" B- W6 @; y# V( F6 ^; Q( y) d0 I$ a; h4 j
数据 0 X! v3 t7 K! `; _% j
! D' t9 O# d3 Z+ Q: d" [$ F& L# d
  其中长度为 数据 的长度,数据的格式: * Z/ @8 V' F& f; o, L
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&....
, N" l$ t( j4 K0 ]/ v3 P7 [2 }, E* f8 D# D$ l% x
  以上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还需要不同的参数,下面我就公布我的研究成果。 6 m$ ~2 z- R( x+ f4 `% H! p
# o% o, g6 O+ ^2 a; t# i' p! i
3、研究方法: 4 j! ~2 c* s; E( U! S
7 r5 i7 V7 l) ~  Y, u
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 " m; D2 `( I$ _1 T
  下面我公布我探测的代码(PHP):
  1. <? 8 i" {1 v' x6 R7 d( R5 V) N
  2. $uin = "QQ号";
      y0 v* I9 G2 w4 r4 C' o
  3. $pwd = md5("QQ密码"); 0 Q, j4 N; q+ V' `8 m$ X2 [% z

  4. 0 m0 n0 b, U2 _% E3 D
  5. //登陆测试 ) J4 j9 ]4 O7 @  A$ L% n
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 2 H8 T# |4 i; g, h5 J! G
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    8 b, T' F/ l" L% j2 C
  8. /******* 8 V2 H7 y6 N( {
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    ' x4 D2 l  G( E
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; , v0 M0 w# }, w
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 9 H1 ^! g0 ?/ [$ g/ @1 K. R
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    9 z& ?$ {, m4 b9 b& W
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    , A5 e2 i% }, ]) J9 m
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; * G& e! z" o: ~1 F( T+ T
  15. *******/
    & T; S2 u% w6 o6 w# u8 p5 @

  16. 5 U  |' [+ L' F2 `4 d4 A" F) S' y7 d

  17. # M3 d& p- y6 _
  18. //得到好友列表
    7 F& c* {! a4 ?+ V" ~
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; ( z8 H2 S8 ^6 n7 m$ D' O! f! ^4 r, Y( \
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; ' U& w, |5 X/ C  i. ?; t
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    % G% x7 W- H' D4 y, X
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    4 n1 {8 j. o8 M; t& @- l- D0 w  G
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 0 x5 g, S4 o8 q& v4 d* H
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; & i: r/ S! A. }) h- r; e
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    + `! X) m1 b# l) g
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    + E! y( n) K3 f1 W) D- i$ }  n
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    3 S# ]( I6 g' P0 s8 W
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    8 d; }6 g3 \( y  O2 G
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";   I8 R% d# y7 D$ r
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);   [1 B$ V8 F$ S* K, N
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    3 T3 p4 w, O# m6 T' d* L
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 5 G- _* w/ B% y5 m' o7 I+ U, d
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    0 E3 t- K% d0 \. `2 D
  34. % H4 U- z% S( F6 A
  35. //得到在线列表
    # j$ [+ O' `8 g  n/ Z8 U( y
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    1 b6 a5 a& A$ D# Y- M8 r& ?2 Z
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    , f7 E7 G; y6 u; T9 \
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 4 G' v+ H' f7 ]1 H
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    4 y; B4 ]4 [4 }
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 9 N6 A2 |7 h& k+ I5 @
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    7 P* t! U9 `! T$ W# ~
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 5 @* P; ]9 s+ @  [4 B3 ^9 n; U
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 3 b& [. P3 R2 n! ~! U9 g3 _% K. S
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    / e! a! J" O7 ~, p" j
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; + Q8 ?5 g; I$ l2 ?- y
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ' i3 H6 }- s; g: t
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    $ b' U' f! x  n/ _% `
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) d) f- A& G9 p# L8 o! B4 ?
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    # ~/ W! t9 U1 E1 K" W
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    & V. ?  }! x1 l7 b" ^( n- j
  51. . {  [1 ]- U; s( P
  52. //查看好友信息
    ; a8 J# G+ A( L% Y9 s
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    9 E; r7 x& g$ A5 G9 _0 G# |
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    ' M: n5 \$ B% ~& e9 t" v" K' w
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; 3 b; J, ?( H1 e6 ^0 B! i
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    * [: N) l3 `: A6 Y/ y& ?% P
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; $ f4 \; m, w% }6 U! f/ S
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
      l4 y0 J6 V. f' E$ W/ t

  59. 8 ~& ?  `1 j, F1 c3 p' P5 f
  60. //增加好友
    ; D5 N" v; c  ?1 w! j, s# X
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; " o. ~$ M( c* l) d

  62.   D( Q1 y0 ]3 q7 r
  63. //发送验证 ! O+ _3 A/ h9 i1 C4 R
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; 7 W* {8 w& N- v; Z- d& j/ J+ ^
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    % o" X$ \# F2 c
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    & c# Y1 N8 n: U5 F. ?+ h
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";   ~  t8 ^  [7 q
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; 5 E- ]% P" ^$ u2 O/ W
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; ( Z/ [  I6 ]% u/ F7 U

  70. + |  M* O4 Q: l5 B( Z
  71. //删除好友
    - C7 w' u0 Y% m
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    % _: J# |4 V% e
  73. 6 \8 _4 h4 `3 P' i: ^' G
  74. //改变状态 + D7 ~$ q# e# O; Y9 `! `, y
  75. for($i=0;$i<=60;$i=$i+5) 7 F8 u. [& ]" b- n; }* v
  76. { ! E  N. @% u+ \* e$ ]/ b# M
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; % ]  m, |* ]+ n3 k) z
  78. }
    - \& G# ?7 ]2 t  P6 A& g

  79. . _! _' u0 l" _
  80. //获得消息
    " M: ?! K1 Z! f
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    ' ~' M  L$ n  T) N/ E

  82. 2 C# E% Y& I0 p% ?, e* f! h
  83. //发送消息 # |3 [; Q# L& H; F$ t8 s: l
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; 9 f! F. [6 k: s: D3 |. y/ j
  85. ' h0 p4 j# r4 I9 h/ N4 B
  86. //登出 9 J$ j1 `2 R' o
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    2 U; V" R  Y1 s8 ~' \
  88. 5 m$ c% T8 Q$ z6 N% m- J" L
  89. $file = fopen("p.txt","w"); 9 P" k# G* p% F+ [6 I
  90. # [7 j6 Y# L: f  F1 g/ `+ l- D0 D
  91. foreach($poststring as $k=>$v)   C8 s& D- Y/ [0 \' Q
  92. {
    4 t9 v7 C: N/ N9 {
  93. ss_timing_start();
    ' v7 q( Z! z( j7 K: x/ G3 C
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    9 s. f( I& a" I9 N
  95. + g% W  @; ~, p( [$ r0 G
  96. if(!$fp){  6 J3 Q3 _. V: }! G9 a4 w; \
  97. //error tell us  
    5 D* x, R7 x4 D9 v0 U( Y# q4 p
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  5 n/ q4 f5 s+ a7 d3 ^1 t: |
  99.    
    ; a9 x/ _& O1 t1 A* w
  100. }else{  
    0 \' H. D( z/ }0 e7 v) O0 i
  101. , ~1 ]6 j2 z3 H' A2 P, Q
  102.   //send the server request  
    2 Z& G- K  T- H( S( U4 n0 N# i* D
  103.   fputs($fp, "POST HTTP/1.1\r\n");  ( @4 m, ?7 f1 `* q! y- a0 l
  104. //  fputs($fp, "Host: $host\r\n");  
    5 G( s8 k4 b! _- B
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    ; r3 H1 f; ^/ u
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  $ C. k% G* V  J1 G/ a8 ]/ f
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    5 t) S: p0 f3 Q8 Y) s; M
  108.   fputs($fp, $v . "\r\n\r\n");  
    + D, V* f( ]; c/ M2 F
  109. 8 O3 p! w0 f) B$ B8 u) P. k
  110.   //loop through the response from the server  / m5 e6 u+ ~* M
  111.   $res = "";
    ' Q9 M( _6 g( d; u( u5 e
  112.   while(!feof($fp)) {  
    4 f2 Z2 I' O. n9 D2 y) Y! @( R- z8 g
  113.   $res .= fgets($fp, 4096);  
    # S! Z5 N; J8 Q5 u, r
  114.   }  
    & r) T/ _) T& w( G( u
  115.   //close fp - we are done with it  
    % f6 }" l# H4 C' H3 Q9 m$ v
  116.   fclose($fp);  6 o! b  L, f6 n- V1 D; H' m
  117. " B9 v; a" }% w! s5 c4 y
  118.   $content = $v.chr(13).chr(10).$res;
    : }. @( W* c% X# U2 E2 e: p4 a* i. _) b
  119. }    T9 O& r0 r: {- L4 P
  120. ss_timing_stop();  6 k* v1 u( f7 F" U$ I3 c9 g
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    0 C+ f! Q, v8 U) x: Q1 N5 j2 a
  122. fputs($file,$content);
      M2 ^( K3 c" K9 _' I% \
  123. }
    0 m* `3 w5 o: d; ^
  124. fclose($file);
    ' c# k4 D0 D( j# O8 X; D! @/ q6 t
  125. ?>
    2 w" X3 Q% J& R; ^
  126. <?
    . K. ]+ K3 u/ E+ c
  127. function ss_timing_start ($name = "default") {  ! O# G, C* ?+ Z% R
  128. global $ss_timing_start_times;  
    + x3 ], ^) W- y% b4 M9 b$ ^8 i0 p
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  . E1 ~2 S; _8 n5 b# b  o
  130. }  
    ' B6 i, ^& _  y1 h
  131. function ss_timing_stop ($name = "default") {  
    ! j9 j- B4 `: c) D7 C! D7 e
  132. global $ss_timing_stop_times;  
    # Q4 K9 v4 b4 a0 N
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  & U  b4 U" i* L* v; O! a
  134. }  
    : ]* N( M2 h! K1 T
  135. function ss_timing_current ($name = "default") {  
    : Z1 {; |/ r/ K1 y1 Q, Y' l
  136. global $ss_timing_start_times, $ss_timing_stop_times;  ' ?" P1 G$ }+ H! l
  137. if (!isset($ss_timing_start_times[$name])) {  ! r( M$ a& F% s& m
  138. return 0;  
    0 Z+ D3 L. o0 O& a
  139. }  4 U% p/ @6 l; a
  140. if (!isset($ss_timing_stop_times[$name])) {  
    3 w* U+ k" j" g$ g0 U
  141. $stop_time = explode(' ', microtime());  " Q* a2 p! e" w9 x* ?
  142. }  8 Y0 D4 V* A2 D* m
  143. else {  ; X2 e/ l, ?% c& c# i: V( W
  144. $stop_time = $ss_timing_stop_times[$name];  * i+ x# V& m1 s. i
  145. }  
    ; b6 O$ C! j: C6 f5 {2 X
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  9 H3 ]' T% p# ~$ r
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    ( L0 N2 a) I- D( C. y- u
  148. return $current;  & ~* F+ K3 V7 l% G
  149. }  
    & s- v* u* a' ^; q. F6 l
  150. ?>
复制代码
) y$ T! `# f& t0 ~3 |) |" k
4、研究成果:
5 z3 Q* H. A# ~
/ e3 u$ H+ y' m(1).登陆 4 ]5 r+ Q$ }; F7 }1 A7 q. _: n
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 * u! D1 e$ k0 U' c: J- M& x
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^
1 n' }2 m& S9 }% W) j, Z, C
9 z  i, D( ]( C- M4 N5 R  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
* C& U1 e- w+ c) [2 z# t  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
, z; h3 U: {- u6 s     M5这个参数的作用还不清楚,但最好为1。 2 v% z! n8 k  t" O
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 # Y2 B% v3 @9 H3 B

3 O6 w; ~1 d/ g* q* U  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) 4 h! ~. g* O5 l+ U
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) " D3 H; m1 h# U3 C$ f- ]2 g
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) " Z5 z6 o! q' m# K4 T
     NULL(UIN为字符、PS为空、LC错误)
9 B7 i6 `' n. U; l
; z& c3 ]6 `- T0 Y, E3 y4 J% V(2).得到好友列表 6 ?" e1 R8 R* Y" b7 }4 {
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 ( ?! n8 W, C! Y
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 , X- W$ f5 k( ]( C5 e. Y! H

# b: o6 [- [2 K* ~$ D  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) 8 S* |  b" S( S0 m" H* D
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) 5 P) J8 F( j3 \$ U1 H: s1 q& ~$ E7 I
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
5 R1 N) _: _, Q2 W% ?, t     NULL(UIN、TN、UN为字符)
5 @# q$ v: R) R( w; r4 _8 R. F% }' M" X  o8 Q) p: H
(3).得到在线好友列表
# l# _3 \7 }. p# {, l9 p0 H. T  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
, v6 E, b. y9 S6 c7 r- P  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
( E3 l" o$ W, G, c
2 @/ ^6 `& _! y; U, {  v  返回: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的值用','分割,分别表示头像、状态、号码、昵称) 9 N0 P2 l1 [- M4 e9 o; K1 ?9 m
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
1 j$ ]) l) l# |4 ~" A3 |     NULL(UIN、TN、UN为字符)
9 k1 ~9 r5 V* X+ t2 D  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
+ [4 Y( v; q4 h, Q. r( W' a: x+ s     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
1 w- E( d3 x3 I% T* t
. ~" R3 C; c/ {  e6 h4 k  特别说明:当参数TN=0或不存在时,服务器返回:
" L# ?1 v, ]8 a$ z' }8 o( XVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 1 X9 }3 l& g7 p- ]$ K
HTTP/1.1 200 OK 2 b. e$ x  G& m' J7 p3 L0 N
Server: tencent imserver/1.0.0
3 P8 O- H/ J8 J/ N* z6 W) D2 P- hContent-Type: text/plain; charset=UTF-8
* f$ C5 a7 b2 S3 IContent-Length: 56
+ N; U) j( Z$ r! i. Q% K
+ x& `) J4 @5 o+ x+ dVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
! G) u2 ^1 ~3 L; \) F. D. `  Q1 }HTTP/1.1 200 OK ! O5 u  X6 `& e7 ]0 O
Server: tencent imserver/1.0.0 1 m# j6 {3 z) ?5 \: l
Content-Type: text/plain; charset=UTF-8 $ V9 v, N- J  @& ]/ ~& b8 X! T
Content-Length: 77
1 B1 D6 V  v& b2 H/ W+ B( Q/ Y! `
: W; h& {  V! U: gVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
% P' H0 U$ c8 u3 P* l. p  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
* Z# T7 A, H8 ?* L% Q- ^! [8 l: h; o- X3 a8 Z2 _4 M
(4).查看好友信息 ( g$ k' G& E; C$ z# O
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
, c. m% @' y" z  h- E  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 1 R3 A0 ?6 E/ l! J8 c
  C7 U( q3 m5 t3 r' o- H
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) 5 O+ K% u# i; \# \6 }. n
     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=学生
/ P% I5 Q5 f3 @0 g7 P5 z&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  . A) a4 X4 m/ ^4 z& ^% G
好(普通查询) . \& J- i# G6 i5 n+ K5 o; S
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
2 M0 @$ U7 r5 Z2 M9 l- J&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  ( n* R7 k& A8 ]8 c1 @
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
' ~9 {. I6 A) v     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) & i! [  S, _. c1 B+ [: W
     NULL(UIN、LV、UN为字符) / n. ^& T5 t2 P% e/ z" u. C/ T( s

5 Z2 ?1 d8 E: o  说明:AD为联系地址
4 }0 s& S, T$ N) O8 x# X) \7 O     AG为年龄
: G% k- _/ i. Q3 N     BT为血型
$ F! Q% E" k3 O9 c     CO为星座
0 {5 v$ P& g& T/ U( i     CT为城市
. T( ^# J2 I5 H5 c7 ^8 [     CV为未知*
/ r, }- F& T. Q0 o% K     CY为国家
. ~& V, ^6 D7 D" P     EM为Email
0 W1 K) ]; e: X, o( c4 B     FC为头像 & {1 \" E( r- N2 b0 Y; M
     HP为网站 , ^! F6 }6 B8 B& F. J
     ID为未知
4 ?8 ^" }  @' d4 Q     JB为职业 " R% C0 P/ C) J6 X
     LV为查询代码(就是发送的LV) 6 ~; H: V! A; _: s4 r; q
     MO为移动电话 $ l7 c8 c* \# ]  a+ B
     MT为未知
4 n7 C" a) p. Z     MV为未知
: z7 t  q! m( T- t     PC为邮编 2 o6 z. @9 K7 l) X: c* v
     PH为联系电话
% u* i. R' N9 X/ t6 p1 \* o     PR为简介 3 n7 l; N7 l+ P
     PV为省
" F; X; Y; W+ t* O  c$ D9 \2 g     RN为真实姓名
" n* n5 X3 ?/ s& w8 s# o6 ]     SC为毕业院校 & l9 D+ H6 |$ a; L# I9 H
     SH为生肖 9 z; x) ~  u% @( w* ~
     SX为性别 4 a' D* R5 Y9 \2 w- T
     UN为QQ号
3 Z9 v9 \+ X# j4 C/ T     NK为昵称 2 S& A! r8 O$ `% d
7 f) d. t3 j* J" ^( K% v" t
     血型:0 => '', . X6 w  F+ ~: a
        1 => 'A型',
1 l' W) @( s; Z$ d+ z" P: h        2 => 'B型', ; F$ h1 ^# e* J
        3 => 'O型',
2 D$ l9 K9 b9 r+ g( ?        4 => 'AB型', " h9 A5 J) B, R/ M+ v; S- j& f+ N
        5 => '其他' 3 L2 ]3 j6 ~6 u# S+ D
/ O6 v4 F6 t( _6 u
" Q0 F: d8 k& O% x4 e+ \+ w
     星座:0 => '', # t) O& ^) h0 {+ ]9 d
        1 => '水瓶座', ! \6 K) T5 X# V3 E8 R5 t9 C& ~1 j
        2 => '双鱼座', ) n% M3 u( {& I7 |# z
        3 => '牡羊座',
" T( ]& y" q; @1 c  S        4 => '金牛座', 2 Q8 q: c% H$ E
        5 => '双子座', ' z4 B! X) l0 V, a' `. C) j
        6 => '巨蟹座',
: W" B1 E2 y+ D$ C9 Y+ i  m) ^        7 => '狮子座',   _5 E4 S/ r4 [
        8 => '座', ( m- z8 j  J$ O- M3 {
        9 => '天秤座',
, }5 n. g7 k+ s+ X        10 => '天蝎座',
- s! g2 t% ~6 F& w1 _: s        11 => '射手座', * ~$ p7 t  ?1 W  n( o* F
        12 => '摩羯座' 6 t6 ~6 e; R# X

/ C# g, W7 Y* D* _! f( W" r$ M     生肖:0 => '',
& Q4 E) }6 a- c/ a        1 => '鼠',
8 t  |* J4 N9 `4 l  ^$ _        2 => '牛',
4 H0 a7 d0 ^. \. M- _        3 => '虎', 6 }; e' w% n' y6 h9 t3 q2 j
        4 => '兔', * p5 P% f2 S1 h8 S
        5 => '龙', 0 S* f! ], X0 m% n. W3 Q1 g' M
        6 => '蛇',
* v3 Y  z' {, T5 |2 _* Y& q        7 => '马',
7 ]; S6 i# ~& y0 }, h        8 => '羊', 8 H, M" [+ {# a1 d) T- I2 T+ \
        9 => '猴', - V/ `" \" ^4 |, o" b5 U; @- h
        10 => '鸡', ! G! p5 j- M4 W; ]# J$ M
        11 => '狗', . L" c6 F" R0 \2 C
        12 => '猪' $ U) ]6 L8 o" P

  P. @, B. H% B     性别:0 => '男',
, m7 _3 n0 z  Q5 |6 t        1 => '女'
/ q2 Q: {, q2 S4 g: c. x3 p0 F
0 I+ M$ H" q2 `' Z( x(5).增加好友
' s/ Y, J# S3 K) ]; g0 Z/ M  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
- {- Y- o% `. N* d$ a$ j
7 k0 z: `; _$ l  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
$ c4 @) W- B- n' ?6 F* {1 j     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
5 A# Y2 L; I$ w+ l% h+ o     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
4 ?3 Q: w6 `8 ^8 x7 ^7 y5 Q     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) $ Y1 J  H# Z1 X4 K( {$ ~) v
     NULL(UIN、UN为字符) : t) M5 Z6 a: B' a) A4 D: O

2 X9 `( z+ M4 ^2 J* y8 ?+ q(5).发送验证 * c7 q( L$ x) k# C
  说明:1、如果你加对方为好友,你需要发送验证 7 x8 ?) n& m6 Z  x* l+ q$ v
     2、对方加你为好友,发送了验证,你要通过或者拒绝
9 b9 x. B5 d- H' T3 m  j$ }  E     这2种情况需要发送验证消息 5 k) Y; ?, n; i9 J7 M/ d/ e% {

% y! x$ Z9 r6 |- b  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 - g; s. P% R8 c& Y; b
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
+ l$ {' `8 I4 Q' O% _4 c
/ j- s! L/ f; V' z+ w) h9 Q+ Y! E  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) * X/ f+ Y# F) y0 S
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) 9 q& A" r# ]' H6 |( v+ \
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
0 |: U) j0 M0 ?  x/ |. i0 r3 J     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
/ _5 V3 Z1 t; ~" I  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
( T. u% e% T* S& h' o& ?, X% r  R2 H+ W- ^
(6).删除好友 $ \8 M4 |: F1 x! s
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
5 u5 @3 t0 ], ~: u1 |; W6 w3 @: D" ~8 D& B4 H# ?* j
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) 4 E* q& U7 {1 B5 E6 F
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) . ~* h* ^  F6 a1 `
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
; L1 p) o9 _9 r  O     NULL(UIN、UN为字符)
9 H5 Z+ x* J/ Y) \; O2 ?- u' j9 \* N8 k. `5 }3 z
(7).改变状态
+ o# r/ b" e& T# j# N7 a  f& ~5 w  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 1 s, `4 X  ~# D" \$ p9 T
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 + p1 k  R% w* Y$ }& o: h) }% k, W3 S

: e+ p+ _4 F8 _* @6 r4 D  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
" ~" w( ^, ?9 z" Q: O     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) + Q5 J% Z' ^" U
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 q, [" _! C8 E9 n: g9 M     NULL(UIN为字符,ST非法)
" K) b. _: j0 [
' x0 h1 i4 G/ Z) x- L  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
3 C' r# f3 G9 @; V+ O+ X/ g       同理,当你的好友改变状态,你也会收到一条系统信息。
3 r; s4 ], _, G, U1 i- g
3 V* q3 z  V: l; C6 ~  b(9).获得消息
3 Z& c4 f# y4 w- L2 L$ A  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
( f" H$ G4 c, q8 @0 Z! X# c6 [5 d* s" o4 E4 `
  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) 5 q) K& P, \* _" W5 h6 n
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) & U/ L, C0 o! R- v: S1 m) o; i
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
5 A8 f) ]5 _% p     NULL(UIN为字符)
1 r2 P: q3 k3 a/ V& g4 X  说明:关于MT:
' V6 u6 w; t" E) b3 e& I7 g       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友
7 D7 v; h( [7 _8 \  t     关于MG: + G6 o1 B9 l# e$ Y/ {
       当MT=9时,MG为用户发送的消息内容 3 t8 S5 m- P8 c
       当MT=99时,
8 }+ N9 E- `1 ?& w7 c         MG=10(QQ_STATUS_ONLINE)表示对方上线
( i# X5 ]0 k' l- ]1 }4 n0 n4 ~* U         MG=20(QQ_STATUS_OFFLINE)表示对方下线
& k( @: ~* N$ N5 Y         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
4 }5 k9 S% [2 s6 ^6 y0 e       当MT=2时,MG为对方请求你验证的信息
4 [* S3 L) p' L" M2 r       当MT=3时,表示对方通过你的验证
2 G' c! K8 F8 e% O/ ~       当MT=4时,MG为对方拒绝你理由
9 |* x# Y& c" r- G3 A( ~$ O( P, ]
& Q% E. c9 k- P' E: I(10).发送消息
- f0 z" I% L! S4 I. S" G* N) d) I  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 + D/ U! r! v2 w" z# ~! ^; F
8 W! q$ h1 @4 [! X2 z
  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) 7 \' e2 a. s( X. A. f
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
- E2 s. c, }9 w5 K% N7 s% m     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) + s+ D4 m* H( e' C* K- `
     NULL(UIN、UN为字符,MG含非UTF-8字符) 9 k& F/ }# v5 \* ^6 C; {8 k
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
' u- Y! l/ P& p' }8 K6 ?       你俩互为陌生人,且对方没有和你说过话 $ C5 j- g6 W7 j1 R: X" C8 X
       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
8 u" |" m+ r6 Z7 G- ]& l     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
1 M- n6 Z- c3 W% s8 ?9 Q" A# J     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
* |/ I* {  i' b/ X
2 C* s6 `+ n$ g; F! `  x(11).登出
. C$ u) [+ ?( E: C1 w  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
2 c0 G. H& q0 _. U1 C" \( `$ [3 B
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) 3 M5 ]# }9 D- z
     NULL(UIN为字符)
7 ]. `9 c$ e5 R* X: J, d  \6 Y) M2 }; `( }5 q
5、总结 " U7 A/ ?! Y  A  r3 N( A
4 {- o9 k) C0 s" b
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
. B  e) |$ }2 ?1 [: D  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
/ U3 ?8 c8 ~( p2 k0 V% S  本文撰写时间仓促,难免有误,希望各位不吝赐教1 C* P' G7 u4 B1 Q' V  p/ Z# K) R$ V

, ^9 }, {( K; W" v: C
! B# _- ?8 l8 u9 X, JTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 08:56 , Processed in 0.028384 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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