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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan , S( ?7 {% B1 a: R- @
日期:2005.8.21凌晨 $ ^! O  _3 _9 t( M3 ^8 q
联系:QQ:106814 Email:hackfan@vip.sina.com + d- z: V4 C( C' ~: a

* c0 B$ M6 f4 p, e6 t% p4 d1、研究说明 ; C+ w8 H7 \4 j8 w
* l/ E3 {' w' m5 {
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 6 [0 l0 n1 h. H# P" O
7 P- X7 f' T- A' h, f  x# J7 J8 Y
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 5 c9 R6 Z0 V, k) W
9 D/ M9 ?+ d0 t; x
2、接口说明: : a8 t8 k/ @/ b$ x# u* u5 |9 W! o- |
. g1 J0 C* _# h* G0 V
  接口位置:tqq.tencent.com:8000
' E: ~9 C* e# ?) t- Z  通信协议:HTTP , _; P3 p4 l' w4 V
  数据传输方法:POST % V3 k7 U( Q5 X$ j& S
  HTTP请求格式:
5 D  ]" H% w8 C0 m. O& a( h8 t/ T% I
POST HTTP/1.1
0 p  l( V" \1 I2 t6 F- ?! P0 LHost: tqq.tencent.com:8000 " S# W" n+ ^* t6 c1 g7 \
Content-Type: text/plain; charset=UTF-8 4 q/ n& [6 V4 g5 E/ _) L  j  O
Content-length: 长度
6 X, k0 n) N+ ]" O6 M- LConnection: close
( I& w- \7 n; l- G! m4 i- @3 ~' d* E( J7 a. X
数据
1 w4 e  u! \6 x1 L  h2 {3 ~0 Q! w& a8 @+ g, I
  其中长度为 数据 的长度,数据的格式:
; c( \0 X/ f& a1 @  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... - U6 N3 z) p" n7 C; z1 Q) E
8 F' f/ R7 u! C, n5 v5 W0 `) z
  以上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还需要不同的参数,下面我就公布我的研究成果。
  n7 a* y9 ?. _7 G5 C1 N; s9 m3 t: i$ |9 H! q  x2 a
3、研究方法:
0 d. o2 s8 m" ]1 ^4 z
0 Q* {: Y8 }. T# U, V* a  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 # i0 Q0 Z* |& H$ a" J' ]0 S; L. F
  下面我公布我探测的代码(PHP):
  1. <?
    5 N. T9 J$ E) T: ]$ s
  2. $uin = "QQ号";
    & r" W7 e8 U9 b! ]- O/ m3 h: B
  3. $pwd = md5("QQ密码");
    : v7 s; {7 R- f$ a# ^7 x
  4. " S) y5 X) H& N' {; x( L2 j
  5. //登陆测试
    9 x/ l) q0 o( a4 _$ l
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 1 v" K8 Y/ k7 V; |2 Y7 H
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    ' ?  W+ v# P# Q( V6 H6 y+ w0 [" ^; y
  8. /*******
    " }8 M3 F! _3 A% x
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; ) o# x9 T8 d6 H
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    / E; P/ C2 q) X. ^+ l5 {5 S
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
    ' q6 G4 b. U7 Y: ~4 h
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; # S' T( h. Y0 b) C
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
      e! B, t. q0 u. J5 H8 `) m
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    ) q' z5 q' h8 p' u* S- F) b
  15. *******/ 1 U* h. g8 k0 [, i4 v" d, K

  16. " d- C  D4 g& x& w% n7 g) v: `* L
  17. ; y% f/ |4 D9 W, Y& m) f' k
  18. //得到好友列表
    ; m3 Y( l1 g* s! [3 i
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    . [, v, O. l$ {+ e
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    / _4 n+ Z0 n- u+ @) N3 R6 |
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; ; \0 V! [8 J# P/ l$ @
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    , b' d0 T2 ~) B! i
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    5 v# J  ?6 n+ @. I4 }
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    3 l6 T$ p! p. |4 f' r& {" s- |
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    " i" X* \+ w, _! i: v# |
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 3 Z* y" y1 ]- t: h, n
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    1 H' z2 h9 {; i
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; " L, p7 J0 K. L2 i3 n
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 1 ?0 e  t. X* e+ M7 U. f
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 2 B5 a- K0 z3 n' @7 m. m" J
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); % G! l2 ^/ _6 [' E, x% ]. R
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); - d2 \/ i- W1 m. l
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
      I2 b% \! T. ?4 |+ }

  34. ; F0 e- H) {$ h, V2 |# ^; ]
  35. //得到在线列表
    ) `  y4 g: v9 Q
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; . W. N# ~6 ]0 m5 O6 i. y% o7 M$ J! `
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; # J6 R- ~( r- I0 E# k
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    # j' x- d% [4 Q) g2 ~
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    ) R( X) {1 ]% t' F0 x
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
      a! J' W  p  _8 s1 I: d9 Y: e
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    # c! M. \9 y0 d# ]" V  U
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 0 ?# j$ b8 s* l
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ' K9 Z) z* d( D8 M6 A! L( [; C$ _
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 5 _2 j( B% k6 d$ Q
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    " p; y( ~. a$ ^; ~' u- E/ J
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    7 |4 X6 R: g9 F, Q8 s3 C, \7 G
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); $ K: q$ C3 @7 y7 w6 r
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    % I- @' u% C; Y( J( y9 v$ S
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    - M# |1 v' Q' u2 O
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    8 N0 D6 g" ~9 v- l

  51. # k( D$ U8 t3 `- x, N
  52. //查看好友信息
    ! v( |* {2 r; q6 E3 @( m5 g5 j
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    ! ^# a$ o) o. a9 \: p) _: B
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; + x, h+ Z& P  H0 e: T4 o
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    : E  r! }$ ~" {* n  [5 N7 X( t
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    2 Z4 S6 x" J6 e" u' b
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    $ ~- j2 R# w( e
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    : C, l  r3 |' j8 e
  59. ! x: E0 ]7 d/ i7 ~5 [! [: ^  ]6 _  g  N
  60. //增加好友 ; v6 M" R- Z  g( {  f
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    * t7 x1 `. U+ t( j2 |; l2 R
  62. 2 [1 J2 I1 `  g$ A
  63. //发送验证 : w* r4 W: I2 O5 f, ]
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; & v) ?1 W( _3 i% ?3 ?
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; # `( E7 c: G: I
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    " n0 J( K7 }8 ]+ r0 d! I+ A# E# f
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";   A* F* D4 F) r" t* v1 Q
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    7 n" x0 I6 m- M! U1 F! L% h
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    7 d' h1 r/ O" {8 e+ p
  70. 9 P; }& ?  S% a) u
  71. //删除好友 8 @7 K  F* e; ~6 {) T! Q8 H/ B! w# N" z
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; ; h, }+ A6 ]2 Z+ N7 E4 \
  73. ! n: _. G$ h0 C( C" \9 R5 e
  74. //改变状态
    ; c5 Q0 V. b" D; V( f2 W3 z) v
  75. for($i=0;$i<=60;$i=$i+5)
    8 u* G. a! q6 c
  76. {
    " }0 j- E5 }3 S$ V4 l
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; - p, B7 |) y8 h# p/ j& T
  78. } + U4 R1 m5 D2 V0 K
  79. 4 h4 c. b, p' r8 l. u
  80. //获得消息
    - A# r0 T7 a7 M( C) S/ M/ I3 R
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; $ E. X; }* i, i9 O1 E' s

  82. * m6 E  Y( j0 V1 k. E/ W
  83. //发送消息
    5 l/ ~1 j/ E+ p. M0 h" W: j3 {( V
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; # Q$ \+ O2 z+ ]. \. e5 l, k

  85. ( ~0 J6 b7 n, z9 c( Q+ L
  86. //登出
    . o% w( U- p/ [( r# V+ h
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    5 g1 Z+ L$ |- d$ W) i  k; H: H. I

  88. 3 ?2 B# c: C' F! q  R( u% r
  89. $file = fopen("p.txt","w");
    ! f" ~/ ?9 _" ]' H& k8 X! Y, _, l
  90. % S  w1 u' G* E2 o9 D" M( H- [: a2 Z
  91. foreach($poststring as $k=>$v) $ ]1 ]( Y9 B1 P
  92. {
    1 y1 p. T' _$ G- E& [
  93. ss_timing_start();
    - o" F3 O9 \' @1 g7 W$ o4 G
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    # k7 p8 c8 N) o+ f) }

  95. ( Z, ?6 z+ ?5 f9 I
  96. if(!$fp){  ) o+ [3 `! E; m
  97. //error tell us  
    ' ?: r: P( q; W0 ]1 l
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  % p# u& _3 V7 K; i7 d% @8 Y
  99.    # m: U* L  U( v( J6 ^
  100. }else{  
    / l9 p4 ]$ \5 V9 {$ \

  101.   t) k8 u0 [7 O, ?* T
  102.   //send the server request  
    ! F8 T! Z0 k! {$ B8 X( p/ n; W; Z* x
  103.   fputs($fp, "POST HTTP/1.1\r\n");  ' L& T* H' j, |. i
  104. //  fputs($fp, "Host: $host\r\n");  
    ) C# N. r" V" f
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  # z  ~7 j. U7 W  ?
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  9 X( j3 ~2 a1 |4 s
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    3 d2 u+ J' E: G7 a! V0 A
  108.   fputs($fp, $v . "\r\n\r\n");  
    ' L( r9 N- D0 V# t
  109. ) ~5 p; i) [* [8 Z. w/ a
  110.   //loop through the response from the server  
    $ F5 A2 w( Q8 J1 J5 C9 P
  111.   $res = ""; $ j* v' Z) z7 G1 H5 |! n7 }9 a4 `
  112.   while(!feof($fp)) {  9 G# o" r  G- e- c2 K
  113.   $res .= fgets($fp, 4096);  % r6 c2 o9 Q; i1 w
  114.   }  0 }! U+ [- \% o' c
  115.   //close fp - we are done with it  
    7 o6 A6 n: n/ M' A
  116.   fclose($fp);  
    ! W. ?0 L' ?8 H6 l% j
  117. 0 x3 T' s& H0 C5 T( `' K/ F
  118.   $content = $v.chr(13).chr(10).$res; 9 c; D# O5 Q/ W# r
  119. }  
    1 Z- P& A2 k3 [' V) W% I! l
  120. ss_timing_stop();  ) z' M$ ~3 d% J5 M- n3 n
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); * H2 W8 X6 _* w" \7 j
  122. fputs($file,$content); , ?& t" M/ W- a/ x: n0 y
  123. }
    # a8 [4 z2 S% v( g4 t
  124. fclose($file);
    , P+ Z8 M5 ~. C$ b( _% Q
  125. ?> # [& H$ J7 i, l& j' y, i8 R: k- f
  126. <? + E; E; v- J# u# @& u8 C
  127. function ss_timing_start ($name = "default") {  ( K0 p+ X' i" P- F7 w1 X
  128. global $ss_timing_start_times;  
    5 R0 K8 o1 p5 {5 @# y( d5 }6 C
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  - i2 S* t+ }7 n' X
  130. }  
    - x( ]& A8 }6 x4 `! H
  131. function ss_timing_stop ($name = "default") {  - `2 S1 R$ O9 t) f! ^) U
  132. global $ss_timing_stop_times;  
    - N" o) C& t1 c) _3 [$ m1 N0 c1 H
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  % `; K9 [0 t9 S7 [: s
  134. }  3 a' O& r7 D$ |
  135. function ss_timing_current ($name = "default") {  * s! V1 @7 V: U8 J: C, C
  136. global $ss_timing_start_times, $ss_timing_stop_times;  1 C# _0 ^+ q4 @0 Z' r. f
  137. if (!isset($ss_timing_start_times[$name])) {  % v7 u2 n2 E- j4 q
  138. return 0;  
    + Z" Q% Q/ w7 K# n0 z" N
  139. }  ) z& Z, t+ [+ W. \
  140. if (!isset($ss_timing_stop_times[$name])) {  
    6 @7 e* J( c/ l4 t) X" P
  141. $stop_time = explode(' ', microtime());  
    ; O, W& Y0 ?1 A5 ]( L
  142. }  7 l# ~6 q+ l/ L4 t8 e
  143. else {  0 I* U; R/ \2 t4 S6 _7 I
  144. $stop_time = $ss_timing_stop_times[$name];  
    ! u& l2 t' q1 w2 E
  145. }  
    , R) b$ r8 V% ^; k" n* Y
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    4 r3 B# y3 I+ f
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];    w' F8 G' {% C' d4 O2 L
  148. return $current;    g+ }3 G8 k7 }. V1 s# T9 U' [4 n
  149. }  
    6 q4 {3 {2 v1 A3 @7 _+ P! g( w
  150. ?>
复制代码
; R& Q4 h- l. j" {2 E. ]
4、研究成果: 5 y$ _3 [! c  W* X, p

) |/ O, Z0 p! l4 ~3 S# M! B(1).登陆 # |! Y4 C" [, K- ]" Q
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 # A. {6 `, \& ]: A% G
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ + ]- |; g& a. N, f. T
1 p( g7 \. b$ Z' ^' w! a+ Z# ?! I+ L; Y
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
" j3 U  H3 ]0 A( }) d" n3 Z  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; " y6 i6 i4 s, {% G  j1 j
     M5这个参数的作用还不清楚,但最好为1。
1 {' r* i% S7 `1 o+ I0 S     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 , r8 i( D  g$ W- `- r0 h2 c

4 o8 a7 i1 k; ~9 t  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
* _( n. x8 F* ]) q     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) ! ^& p/ P0 ], m- Z5 A& N7 G
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
) A! Y7 p3 T0 r- F9 s* ^$ v     NULL(UIN为字符、PS为空、LC错误)
5 T: w  Y7 ~3 r- ?3 i& Q( {; f& c7 G
4 i( e6 [; A4 p$ |; m6 Q( F6 e# g(2).得到好友列表 5 W( z, y6 b8 X; v* i% @/ c1 }" ]
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 0 B, Y2 d0 c2 L
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
" k5 K$ R6 Y/ K; b
7 ]* _6 D7 e+ o" e: o7 l  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
" e0 b* e5 j* e$ d6 [2 N- h     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
( D& Q4 a2 k/ @8 a2 X8 e3 }     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)   z: F9 e3 }: k
     NULL(UIN、TN、UN为字符) 9 @  F) K0 B: Y  p4 \9 C6 A6 j" y
. E5 h# M% W) J& F# j
(3).得到在线好友列表 $ C( R, m/ n* I, y
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
) D4 K) Y3 w. C- o& X9 N  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
' z8 G( z3 a, l' F" s( u9 X
, E7 s2 \1 c4 S  返回: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的值用','分割,分别表示头像、状态、号码、昵称)
; d+ |1 ~# Z5 a8 _- Q# l* l     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) / R( x9 E5 W( d: g6 n, e. I1 l# w. Q
     NULL(UIN、TN、UN为字符) 0 L" ~% E5 G7 j% A
  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
6 L4 ]3 y4 [, F2 n     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; 8 m- O- [9 Y% Y. \" F

6 p( {  j" G" X  特别说明:当参数TN=0或不存在时,服务器返回:
+ f  D3 u; n' t$ vVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 + A! W' S2 T% \# c& `" m6 l/ o
HTTP/1.1 200 OK
: J( }' v- j. m- CServer: tencent imserver/1.0.0
, b6 d. M4 }  X% {- w. FContent-Type: text/plain; charset=UTF-8
6 l, c- \  a( ?! WContent-Length: 56 8 ^; i& @1 G9 D1 E

+ I; q3 D' W; e$ e7 r" RVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
) {0 y5 K& |: }' @" C& `HTTP/1.1 200 OK
; W2 B9 F  U+ G" h$ e+ S+ p1 D! oServer: tencent imserver/1.0.0   x: Q6 Q1 B  z. @1 k
Content-Type: text/plain; charset=UTF-8
( H  F) ?+ a5 ]( r1 V; c( QContent-Length: 77
0 T8 L$ }3 B2 C, q( B( R  F+ c8 F0 n9 ?1 y) D, M1 b; x0 d$ a
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
+ F8 `  B5 X3 E& N  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
* V' [) ?6 P: v* T/ ?. B' V5 n& B; F. E" ]$ Z+ v# n
(4).查看好友信息
* }7 e, [9 V- c% C2 H& t, A  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
) o+ M/ u6 K5 M  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 1 R; M) g  X, l! i6 G# J

/ ^- f2 M: E, }. j  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) 5 b% g" u6 P* h- \. y2 s2 f$ Y1 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=学生
! C/ Q, S7 i, R! n& u9 P% t&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  3 L: V% M3 k6 @; n- p; R
好(普通查询)
7 i1 r  n: m3 r! c5 e     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
: C; q6 G6 w( z7 I5 B" A! r6 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  
/ e8 d! k  l/ X  ?1 l3 B6 T, zupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) , C+ W7 ]  W! x  ]1 t! I* A  J
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
2 B; E+ d# u4 Q; w. [     NULL(UIN、LV、UN为字符) 3 ~( O; n/ r/ r4 c( l

/ X& A  p3 j! `; y8 D  说明:AD为联系地址 $ H2 G4 u4 {" D4 H
     AG为年龄
- R4 d! b% y! j8 k; N8 B     BT为血型
# u2 u/ A/ A3 I3 K3 g, [/ b6 ]     CO为星座
3 v5 L0 o1 @0 ^7 A     CT为城市 0 s% }* h! B+ x7 c0 R
     CV为未知*
' V+ {) r% W+ V2 S; l* n/ j     CY为国家
' Y; X; Q6 F$ ]. w3 A4 I     EM为Email 7 @4 P$ a( c7 \0 P
     FC为头像 6 h) H- ]% k) c# R
     HP为网站
: a6 S2 B" o. h. C$ g* j6 ]     ID为未知 2 C2 U* e5 F: Y5 {$ A
     JB为职业
0 z: r) C2 {/ i% L3 ?     LV为查询代码(就是发送的LV)
6 f! K3 M# p5 |2 m6 V% e     MO为移动电话 2 b  M; e. H, M. O2 `& g
     MT为未知 " w- V1 g3 f7 O7 E
     MV为未知 6 h$ {. c* J( K; V* |$ [) [, K
     PC为邮编
* r3 z' y8 j* h* f     PH为联系电话 $ J9 G1 G$ K# u( y
     PR为简介
& j& t/ T* }& I! c2 s/ }/ B/ b     PV为省 " Z$ n; u- v7 T
     RN为真实姓名
$ Z1 f$ W% `  x- O: l% _- l     SC为毕业院校
: x: Y+ `1 Z- E     SH为生肖 * @. ?7 q4 B  p" A
     SX为性别
, Y+ W  m  K$ v! B6 D& u8 g' I$ ~/ a     UN为QQ号
4 P# R! u$ `+ x     NK为昵称
3 D- W" s1 t1 n+ a' V! k
$ `7 D& h! e- R5 Q     血型:0 => '', 4 t0 E" q% F2 Z
        1 => 'A型', # s$ E# h. j( A% z* v3 f7 l
        2 => 'B型',
+ ^9 C  `& c1 c4 E# S( \* q: t( s7 P        3 => 'O型', $ p6 D2 e" a  X$ x. e+ s
        4 => 'AB型',
$ C0 P3 s, j& a* y* }        5 => '其他' % S# ?) K2 T" M5 w4 C) ~7 `' X

' m4 @, g" d' G/ ?( r% ~/ X8 j$ z" C% x  t
     星座:0 => '', ; c3 V" \$ u# k0 R( |8 p
        1 => '水瓶座',
) w# i* \5 e/ \' V6 m& s8 L        2 => '双鱼座',
6 X$ L, C8 w4 t  x6 {        3 => '牡羊座',
" G/ d+ [& r( c7 x( o- F( d0 c6 l8 L4 h        4 => '金牛座', / _; W7 D$ T2 G# Y
        5 => '双子座',
8 J# D/ v, \# G( P; \* [+ T        6 => '巨蟹座', 5 M2 C( z) o4 q6 [
        7 => '狮子座', 6 |5 f) B2 f# l1 W8 v
        8 => '座',
" e/ f: H! o" g: C% N1 c        9 => '天秤座',
/ }6 ^& x3 i9 Y9 D        10 => '天蝎座', 6 i5 ]( T$ R* L/ Z' y# }
        11 => '射手座', ! B  l. B8 \% |1 p( k$ t8 ~
        12 => '摩羯座'
! x2 J" i; Q& h! s; z7 }0 f$ p) k/ h& U
     生肖:0 => '', $ I) M  |. Z4 x  w6 B; u% z& I
        1 => '鼠',
, c8 K6 [# h% P- k) S* z        2 => '牛', " n$ A# c0 h5 {2 b, Q
        3 => '虎', 3 w( w7 @: R7 Z! T
        4 => '兔',
- z; y/ j8 p8 i        5 => '龙',
. B% x; u1 l: o7 A1 B; S+ L        6 => '蛇', 7 s  O* j0 A! V) h1 r
        7 => '马',
2 Z% @+ d; B. Q% D0 a        8 => '羊',
5 i" i( Z! J( ^6 U' p$ k        9 => '猴', 7 A1 h: ^& [; {. x, y# Q( p7 }! a1 r  ]
        10 => '鸡', * a! N9 O$ J+ R) g
        11 => '狗', ! H( [8 n8 O7 V$ B% ]7 G. v
        12 => '猪'
+ S8 K& _, j' F8 ?3 ~4 ~  X
& G! W: Y# f$ K+ M/ g  b4 S     性别:0 => '男',
% K, D. J. g  C        1 => '女'
( ]4 _2 \& x! k% S
  K+ x' F# [9 q. V(5).增加好友 1 k' B* n, z9 R9 Z$ ~
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
! T8 Z. S; i! o/ J9 W: ~, L- s4 N7 G3 U! Q/ S
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
* `* u( a; ~, X- @. }     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) 2 G, @. i, y! ?/ W) s* a9 Q% K1 u
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
4 @! V! E; w$ y+ E     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ' J! o& k/ [* a- \. E( `" o
     NULL(UIN、UN为字符)   l' B) S2 q- A& s

/ W4 s( y- U7 D; z3 }(5).发送验证 6 |7 @0 a4 U& K. [6 O- ]
  说明:1、如果你加对方为好友,你需要发送验证 7 U, P+ x2 `. `) q
     2、对方加你为好友,发送了验证,你要通过或者拒绝
/ i9 H. s; ?0 F6 z     这2种情况需要发送验证消息
% q4 _6 U0 n* J: V. m, e
7 r0 p$ a4 o, y  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
: X5 l/ n  l3 L/ v( A1 a  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 5 u! g  j$ o4 `/ Y6 v! t$ _
: v+ t9 j& C- f; s  k0 V
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 6 H( u4 H' U4 l8 f% j
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
! \; j) P! I! s3 w     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
4 u) f  m; Y7 j     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
3 J1 `2 m6 T( m* j; D  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
" X- R; C8 ?$ e/ {' y$ J, ?
- e- }, S+ w; H* f6 p(6).删除好友 ( \% |7 l7 v4 A; Y6 F
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 . V7 y) ^8 C/ X  ^7 B

- X% _% F6 G8 A5 a  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
! F& {/ n! z* y$ n8 s$ @     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) - O/ C. v3 ~5 v- Q5 L6 `
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) " g, m. M' b2 A6 ]; [2 \) s
     NULL(UIN、UN为字符) 9 [7 |* ~. t; s( e& d  Q- N' \

. m. z/ U8 n. n7 G  s, n(7).改变状态 1 o, ~0 K7 g& m  e
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 , b1 X* ?/ D( I( G  n
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
# }2 ~6 r7 {. r" s1 ]$ w/ \% Y1 z4 [1 p" a' J
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) 6 M7 f, t$ {/ l( L. D
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) 9 ^4 w* z& z. X( B8 _
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)   }" e4 g8 b: c4 S) G) e
     NULL(UIN为字符,ST非法) 3 S- X. \7 p3 h, B

/ S; x. R! L$ O( {; @  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 ) @# A8 v% R  M, y- m7 M
       同理,当你的好友改变状态,你也会收到一条系统信息。
! A! C, M5 s$ A' a7 r0 h2 ~
( _1 Q1 @) W# W5 R(9).获得消息 ; D, o- L/ l; W4 Y2 |
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
, \+ F- t; A. }2 \( m1 [/ z3 Z! N5 k1 ?/ t4 V3 w
  返回: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 B2 a$ I1 |8 }# t& N) g- }
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) % M% r  [+ i% g, i! l
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
% \; B8 I( s1 e. L2 g, D     NULL(UIN为字符)
5 Z+ j+ D2 W8 c2 Y  p  说明:关于MT:
" Q" n* x' m; M" q3 {0 d       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友
- ^" ]* `8 [6 x! z     关于MG:   p$ A' ~$ f) ]- P# ]$ N% d- M
       当MT=9时,MG为用户发送的消息内容 2 R# B: N2 @8 l0 E& E
       当MT=99时, 9 H3 K* U& T8 v1 S: c  r
         MG=10(QQ_STATUS_ONLINE)表示对方上线
. n$ G/ `0 e  K- P: k         MG=20(QQ_STATUS_OFFLINE)表示对方下线 9 L1 X% z% R! }! \2 {
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
9 U7 ^+ y0 B1 Z5 L' C       当MT=2时,MG为对方请求你验证的信息
1 M/ D% `+ {5 {$ _0 A       当MT=3时,表示对方通过你的验证 4 c$ ], U  u- i* t6 n
       当MT=4时,MG为对方拒绝你理由
. v2 I1 _7 p% p' J" ?  x7 E  }& ~3 q4 y  T4 S" n* y
(10).发送消息 2 n2 c; j  I% P; ~
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 ' i& q" z- l9 Z9 v. O, `8 h( o

( s% [% ^: E$ T  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) 7 [$ n) s% i4 y3 T$ r
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
% d- L7 ]: p! |0 D& R     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) # T+ K1 v: W& Q, ~3 k
     NULL(UIN、UN为字符,MG含非UTF-8字符) " p' t0 d" D; e; c. ?1 `9 H5 e
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
3 K6 E1 I! p$ X; s       你俩互为陌生人,且对方没有和你说过话 $ Q: j; K# Y5 G' `! H- h5 a& [9 i+ Z' V
       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
6 Q* e, R3 y4 u+ `. \     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
$ n$ z. Q1 l: H( c     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL * F1 K; K7 n& `  p( @( y1 e3 X8 b

' P  ~- u5 d* _6 X% Q% q(11).登出
* M& y% q* ?: m# t( p  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
6 v: N( `; y, e0 ?* ]3 j5 y: q9 k) F
+ p+ K5 S2 F) c! m" H  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) + l% V6 R% B9 ~2 ?
     NULL(UIN为字符) - Q/ ^! I+ f: c' ]1 E$ W* c

1 ]3 D5 T$ V6 g8 Y5、总结
+ x) j; @7 {4 A- t4 l$ I) r4 ]
5 r, d1 ?; K0 Z: z  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
+ h2 D  c' K. ]9 |8 \* o( ^  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 $ Q( ^/ E% ]" w
  本文撰写时间仓促,难免有误,希望各位不吝赐教
, K0 A* y0 k) o! q5 X. \
3 N" b; d" b$ K+ y* T. v3 \; E! J: }5 b5 c, I, V
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-15 02:05 , Processed in 0.024310 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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