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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
% g3 \: t: r1 I  F日期:2005.8.21凌晨
6 ^% D6 y# V+ [! i联系:QQ:106814 Email:hackfan@vip.sina.com $ p7 w$ w" o9 ^9 Z( }
" b# Z6 _, h# [- n" q
1、研究说明 % O/ ~$ _+ w6 Q: ~' H1 M5 ]

7 G2 q. s' z% A& L9 M, ?  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
% [+ @3 }7 y4 X3 `3 d- O+ w2 I/ K, P3 X& f- `; X* n/ O: E
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
" ^; N9 `2 [8 s7 X- d
# d  Q( C5 G0 h5 M2、接口说明: ! ]4 S! j0 E' I, K5 \3 D
4 \0 A2 p% z3 O4 q* @8 X
  接口位置:tqq.tencent.com:8000 # N1 ^  }% @8 G" U; s5 B' ]" }, t
  通信协议:HTTP ) [: |4 G$ }- f6 ~& g- x$ J
  数据传输方法:POST
. u- p6 i* A4 l9 b+ y4 Z  HTTP请求格式: ; x4 p! V& @4 F& A7 _8 U6 A
) ?( R% |! ~. Q6 x- u6 h
POST HTTP/1.1 2 x' X; A7 {3 O! u2 c. Z
Host: tqq.tencent.com:8000
/ p! y! z" Q9 ]: A- |Content-Type: text/plain; charset=UTF-8
2 V) k( u- J6 B& C4 n4 P/ Q. f( H2 OContent-length: 长度 7 P0 j# o2 G* Q; C& o* ^
Connection: close
. l/ m  u1 Z# Z4 S+ }
9 H, }* \- h7 {- B+ k数据
$ j4 E7 p+ P& \. Y) K
- ~- Z9 N$ f) p% J  其中长度为 数据 的长度,数据的格式:
) U  L1 P7 {8 s2 B  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... , O4 u4 [* r/ x3 |

; S- f3 N1 ~' P; j7 g+ ^* V8 B. a  以上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还需要不同的参数,下面我就公布我的研究成果。
% ]& B# a8 n% [7 v: e# r
  q7 f; d, O: d8 K3、研究方法:
! Y3 u" H& o, ~0 D
9 P1 M) h  f% e* s  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 . f, D  k7 r! ?1 R
  下面我公布我探测的代码(PHP):
  1. <?
    % E$ ^! n3 _2 z5 r' N/ P8 _
  2. $uin = "QQ号"; ; P7 o; F7 M; P0 d
  3. $pwd = md5("QQ密码"); ; D( |. Y7 e4 S- ^) [& I# e( m$ V

  4. # i) ]4 \, v4 k3 X$ t* v; x
  5. //登陆测试
    " k; D: ]) O( U; x# F) ?: _
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    1 V0 |8 |- {, F4 h: v: ?! i
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    2 H, e- i9 Q0 W
  8. /*******
    ( v/ Q- X3 G+ ?! M; Y) l
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    1 h2 J# h6 {7 C* M3 A: |
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    * ]3 Z3 Y; A9 I: A. P: c- ~
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 5 q! y# [  c# M- j0 G
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; 2 U7 [; [# v1 E8 a4 w5 E  t
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; 5 F5 s: L7 L* ~1 U( t: q
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    0 y+ ~- ~5 u8 H  F/ M6 I
  15. *******/ , V( f4 S* x  }& E" o/ f/ ~4 Q

  16. 6 B. T5 s* N, C% k8 D

  17. ( r- b4 n* _: ]; E8 z9 r  J
  18. //得到好友列表 % ~+ ?' Z  x1 A, M0 k( ^
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; 0 f( \& u6 t4 d
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; ! K/ h: l/ H' g# c, T
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; & O; o% o* T( R. G/ o8 q2 n' G
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; ; |& `& `% Q8 O' \, E1 S/ f# i" M
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    + W, e; R0 d2 k& S8 V. c
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    / p4 h1 {6 `* [: f7 x; M, T8 P' l
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    1 |' p7 E0 u3 N7 f/ M7 `) p
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    $ C: R" m1 b( {2 g# M4 O
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ' B% j7 T1 `' r; n& S$ P, n* L+ p, B6 i
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; # Y/ o+ o+ E$ e; R4 c- X$ D
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 6 }7 w! B' C# Q6 G& K2 D# T
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); $ q6 i  N  Q; ^2 U. F: c1 T
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ' b" K: T5 a+ g8 r
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); - q! c' f9 \# P: Q2 p
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 6 n1 \6 H- s' g5 H' Z

  34. 1 z! I' N4 ]! p, C! T, @
  35. //得到在线列表
    5 t) m( z; L7 b/ ?
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    0 b  X3 T4 }! _1 E
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 5 K: M( t2 N9 u; Q
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; + x- J6 R2 O6 P8 V$ t; _# K: h( f
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    3 D6 U2 P" C; H( N$ S: A
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    : Y. t. I/ |. M, y; v
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    4 }3 S/ U1 F" {9 O- [/ b( n
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; / @  b' _$ g6 Z, Z  |
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 9 A. Z. c: O8 l! J, u
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    " i4 ^% M* |& k" d% B& D3 _
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ; @0 R& J; y$ \1 J
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ! |/ \+ v5 j- Y3 L5 J/ l: C
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ) V/ H5 f: {  f7 v& P9 h/ M
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    6 x$ H/ c/ q  y+ d0 N1 l8 l! l# d$ `
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) ^+ {2 V' }* N& Y, c
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; : y$ n' N/ G) r8 a- Q3 s

  51. , e" Q- i8 H! ]2 \  T8 d
  52. //查看好友信息
    6 E$ O, ^6 X- Z- G. R
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    8 l& f0 G5 j" R7 V9 e1 W
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    2 F$ ^) ]+ F. x
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; & g- H% ?( |2 ^
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    # z, R# y2 U  S1 M. U4 x' _' N
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    7 c( z! J& n5 |6 u( P3 T
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; ( t- @8 Y/ K  S! q
  59. : d7 B) l& @( H: u7 c
  60. //增加好友 8 D- }; {% G; ?( e* X
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; + W, [' P& E& {' a$ Q: @
  62. - `2 q0 P! c: S6 ^+ y+ ^6 s
  63. //发送验证 % x. O- n8 ?/ U- x& m/ k- Z5 W" R
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    ' r# N/ J- m: O
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; - ], f0 }' e* s3 F
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    + O7 Y( j2 z! Q0 k. n
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    0 D& k3 l7 _9 x3 }' s
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    6 Y3 A& j  T/ w  X
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    ' y/ h& D1 i& x" M6 a

  70. # R1 ~+ h8 j; w
  71. //删除好友
    1 D$ m2 {/ l0 y0 X# I6 M
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; . Q0 n, p, i) L! k$ g

  73. * K9 I3 c( L+ P) A6 K+ o
  74. //改变状态
    ' @3 l1 ~; ]7 L8 o+ z
  75. for($i=0;$i<=60;$i=$i+5)
    ( l- t* n% E- D! l' Q, M' m2 I
  76. {
    . B1 I" `/ K: C9 i
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; 7 K. C* I' ?4 i$ G
  78. }
    / j6 T$ A/ Z9 v% f+ U
  79. 8 w! ~5 G8 Y: f9 e6 ?
  80. //获得消息 4 Y4 W) X' ?6 T+ x4 k
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; 8 o  J9 i. U7 W7 ?
  82. 7 ?/ ?& }0 G5 y6 [0 r
  83. //发送消息 % Q1 D  I# E" ^! S; c- B$ n
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; * P% ]* C+ N- |# w: ^" ?
  85. + E! K( o( U+ a
  86. //登出 4 }  {8 N* N9 C8 n# d% y
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    % I1 \& ]. n: A8 \+ ]

  88. 9 G: B2 |- p! ?/ ~% m+ x
  89. $file = fopen("p.txt","w");
    $ F; a' {. r" f
  90. & X8 \8 i7 M! e! \6 e
  91. foreach($poststring as $k=>$v)
    ! ~7 j/ ~( B1 c& j! h
  92. { , E: [! T9 Z8 _- Q; ]
  93. ss_timing_start(); 1 [1 A( r* O  {4 E% m# `1 {
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    3 T7 L) a9 \2 q( e1 ^. V

  95. ' D! x5 [0 X( L7 c  r+ H5 A: \0 o5 d
  96. if(!$fp){  
    3 `8 G, G5 N" w. P$ L% ?+ m2 d
  97. //error tell us  2 ?. a8 k0 L% L: l8 x$ j8 b
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    / y' G; z( E) u; G
  99.    
    3 ?( u; G! X" `# S( O3 [  P
  100. }else{  
    , h, H, s. ^9 t0 k. i& Y  Z" U3 S
  101. ) ]- D/ Z  i. W/ ?/ ~$ m9 n
  102.   //send the server request  ! E; x$ m- }) L# {
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    # T. y/ c  f/ w. Q
  104. //  fputs($fp, "Host: $host\r\n");  
      w+ \: a/ P, P
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    " ^- ^+ v5 i8 }4 W$ B0 w( f9 W
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  ) u. E' d+ |$ N) V6 A6 A) p* I
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    8 |) b4 l- y" h! N/ J4 M* D
  108.   fputs($fp, $v . "\r\n\r\n");  
    9 L. G7 h! H9 |' O5 z$ d' F

  109. ! t9 O; K0 C; `1 I* \5 o
  110.   //loop through the response from the server  
    0 @4 d1 ^) k4 Q$ @5 G1 _7 I
  111.   $res = "";
      e; r3 K% b, ^- S  S
  112.   while(!feof($fp)) {  
    * I! X4 j4 e: P' T; l  D4 I; ^
  113.   $res .= fgets($fp, 4096);  
    " a2 [4 M* m5 f- ~
  114.   }  
    1 g/ m4 v% c# H: E$ s0 E# ]0 J9 @
  115.   //close fp - we are done with it  
    2 i! S9 U' L  l6 s0 Y! P
  116.   fclose($fp);  6 Z) `9 e3 r; g' C

  117. 7 ?) @* m) |; i: L: Z5 F
  118.   $content = $v.chr(13).chr(10).$res;
    $ Z. w, g$ D2 e/ L) g
  119. }  " _) C( v6 h& T. [
  120. ss_timing_stop();  9 n; U7 r* Q3 p+ i0 y$ q
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    # ^$ x) f$ m/ u7 u7 y
  122. fputs($file,$content); ( j* H5 X3 L: v- s3 y! M% ?
  123. } & h* V  [  G; s) s' P/ b- I; m. U
  124. fclose($file); 1 ]5 C5 e5 {1 r3 _0 @. K' N: B4 b1 G
  125. ?> 6 D/ V0 Q7 R1 e; m+ @! C0 h2 {1 H3 L
  126. <?
    $ U' x  M4 u6 L
  127. function ss_timing_start ($name = "default") {  9 X6 n* ^7 F9 Z; x3 k& k$ l
  128. global $ss_timing_start_times;  , s* C9 t& q) R6 b. T) Z( \. j$ ~
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    7 L7 J* v" Z  z6 j, @0 N. W
  130. }  : A8 b1 a! ^: d# s) n
  131. function ss_timing_stop ($name = "default") {  / c( h2 a' ~$ {/ z0 @. H3 t8 y
  132. global $ss_timing_stop_times;  ' o- A  b  ~7 l5 {7 S
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  : c8 n& z3 A( G( p, }4 m
  134. }  % q- C% k5 h. Z/ }
  135. function ss_timing_current ($name = "default") {  + {0 y& S% c0 Y& E' |
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    6 N8 R! h3 l& h' j2 R2 [
  137. if (!isset($ss_timing_start_times[$name])) {    r+ ?1 `, @8 k, I
  138. return 0;  6 \! ?/ r1 l# M; l% P! f' q
  139. }  
    " \. q) E& X$ B8 o* ]
  140. if (!isset($ss_timing_stop_times[$name])) {  $ Z$ h. p' E- m9 r
  141. $stop_time = explode(' ', microtime());  5 _. D8 h3 C7 I  r1 n) \* a. l
  142. }  ' ?* K2 ~3 E- y: `9 J
  143. else {  
    5 {9 }0 v3 W% k/ [
  144. $stop_time = $ss_timing_stop_times[$name];  
    + r9 v/ G9 t: d, j7 m
  145. }  / ?$ M3 t/ ^" T& V0 q# D# w4 z
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  - F" Q( s( K$ _1 g
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  9 v& O- \' m& S1 {* v4 A- t
  148. return $current;  ) A, k9 R# A* Q2 \: C
  149. }  
    0 [; t7 c4 M0 N( ^
  150. ?>
复制代码

2 A' Q# H" Z) j: S4、研究成果: / p9 Q. V# a  h4 @
# \' ~* t! F" x, h" e5 s
(1).登陆 * M- L: r* _+ X9 Q* j" a) Q
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 " A: m, ?+ T( \4 H3 h# X' C
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ 2 A3 R$ w$ h& F% S6 ?& d) r

* s/ R5 B/ \/ Q- O) H  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
% R/ r/ e7 n/ D# C0 O  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
. Z8 e5 L: P5 S) O     M5这个参数的作用还不清楚,但最好为1。 7 N8 F( s) |; N3 r7 [1 M
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 ) J3 X$ d. k$ E+ t2 e. l+ x

' M% c4 ~" y4 ^' q/ k2 e  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
! U* v0 V# B, g" \  G     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) - M. m* e: Q  E8 L. y
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
" t$ h( }; k3 f$ Q) z     NULL(UIN为字符、PS为空、LC错误)
8 _0 G0 J4 N+ W- f# p3 r% _! ?% H) J1 K9 S& C* ]4 O9 k
(2).得到好友列表
3 c; w7 j9 v/ K4 Q' ^  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 ! @' Z1 u! o- m, b
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 6 B+ _4 Y: P4 q# U9 ~! k/ }

9 ]$ I5 c0 P6 L8 _$ H8 W3 U  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) 7 g& t( P) d6 X  ]2 D. e
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
/ v; X+ |9 G: \: I1 x$ P# S& s' d     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& M5 c6 q2 F; x( a     NULL(UIN、TN、UN为字符)
) ~1 \3 V! Y  f! J. v$ C
9 M% Q6 h" T# J4 g6 K(3).得到在线好友列表 ) e' [1 D1 h: p- d/ J
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
) e: E. s9 M; T! C/ _5 H, K  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
7 q1 K# ]  z% F
& o& W) c+ j: k  返回: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的值用','分割,分别表示头像、状态、号码、昵称)
- ^- H$ h5 l' \     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
1 m% y: H/ x# A( a6 J* K$ T# e     NULL(UIN、TN、UN为字符)
8 u  j8 j1 k0 Z/ c- O  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; 2 f" |0 ~/ W/ F$ X
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
  _, K2 }8 t. Y/ F3 e) X: B8 s7 J" ~- ~4 [* h4 p
  特别说明:当参数TN=0或不存在时,服务器返回:
0 u8 h3 ~( c/ F- a1 _VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 ( B. U) i- V3 O- o
HTTP/1.1 200 OK ! i( ?( R- n: `( k- x: L. j- ~% @6 ?
Server: tencent imserver/1.0.0
% }8 O+ Y' Y) x7 a  J8 |) O3 a+ OContent-Type: text/plain; charset=UTF-8
9 R2 {4 n& j1 B4 Z9 s; v' HContent-Length: 56
$ Z9 e2 e& C6 K; T& @, A2 b  l6 Z' F4 ~( s2 {* m: O1 N$ f3 y
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 3 t3 w# s3 e& [* h/ S0 X
HTTP/1.1 200 OK
2 c" W0 z9 m& m9 ?3 r  R& EServer: tencent imserver/1.0.0 * N! H$ v4 p- d9 N1 a+ B
Content-Type: text/plain; charset=UTF-8 / S8 g) W, f; ~  P. b% a
Content-Length: 77 + Z/ x$ N2 c# L$ g$ Q5 G3 `

+ X9 e1 d/ y: K" zVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= 5 l1 P# @+ o% s' `9 F
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。 $ ~# A% C  y5 H- [# E

3 Q7 D' c+ A% v8 M+ W! Z(4).查看好友信息 / s; G- K6 R, h& v1 d1 {
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
3 Z& s9 R% V/ ]3 e8 h2 K  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
$ r8 f5 C3 t" d( M" a/ j8 [  Q% _' q1 S
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) % u/ y0 C5 x8 R. n; h: T6 X
     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=学生 2 a8 i/ L7 `5 m% k- b
&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
% P- D: v2 C1 n- e  Q) }好(普通查询) $ _* e0 t5 m- N
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 & P# J& x4 H: }  E1 E
&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  5 E8 M! Q2 J/ M7 z0 E- o
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) " U1 b: ^$ |% q. ]7 X
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
8 X% ]3 f7 f2 T8 m' l8 r1 b5 g1 o     NULL(UIN、LV、UN为字符)
! j) f6 o* t2 f; E* C0 K  z- d& K, i; r8 g: c
  说明:AD为联系地址 ( e% Y2 S( ]' A- Y+ r
     AG为年龄
9 P* Y- }2 G0 H& [7 D     BT为血型
# @: T# z, N# c$ n6 h+ [5 I     CO为星座 0 E) D* Y! n5 ~7 t7 w
     CT为城市
$ k2 K1 p$ y' s  ?+ y1 t: q     CV为未知*
! n2 y9 O* u7 V0 ]     CY为国家 9 ^# t' g2 }" ]8 o2 R" ?+ n
     EM为Email
+ W4 U9 h, H8 _     FC为头像
* y% k& h8 m& G     HP为网站
1 p' e2 y1 q" Q3 `     ID为未知 # L2 y" M" v* V) m8 |% l
     JB为职业 1 r3 p+ {' p: A# w
     LV为查询代码(就是发送的LV)
: R. M6 v& T$ B     MO为移动电话 * D% X% E1 u  f: ^- e1 z
     MT为未知 # R: n# f) i  D9 e1 J- }
     MV为未知 ) s  ~6 @( I* m0 e7 _& }, ^
     PC为邮编
+ r+ D# m9 A) N, B& ~3 ]; S     PH为联系电话
: ^' t3 h+ j, [  v& M0 A     PR为简介
) M+ s4 |7 y. L7 }4 j0 [( Z9 ?     PV为省
' \+ w4 r: }; U' F     RN为真实姓名 / x. D- N) ]! d3 H& M
     SC为毕业院校
7 G  f  H- b4 S# N! k     SH为生肖 & {0 K) N9 d- n- \, M; c+ x; A# ~  ^5 E
     SX为性别 ( Z% Q% b, }0 H* i: e9 t' z5 ]( Y/ x
     UN为QQ号 ; Z; q( \/ }) i  j+ L! Y( Y( X$ H
     NK为昵称 ) o' w8 e. p* N; ~. A% D) g9 n
3 F: @, D! i4 `2 I* n
     血型:0 => '', 6 J  Y! m5 _; z
        1 => 'A型',
5 g9 I. W$ G6 F        2 => 'B型',
. M) L" z1 u- T+ n. w! W6 W1 p        3 => 'O型', % w( D: C# n) q+ ]) ~7 k
        4 => 'AB型', 9 d: h; j& L" x& x+ P$ R
        5 => '其他'
7 _# J( d4 O1 h! V' S6 A
6 H+ I) R. N+ d
2 @, G$ K, K" G" t. u9 B1 ^     星座:0 => '', ; S: s9 Y1 c( D$ G6 W0 t9 W
        1 => '水瓶座', 8 X0 y% q# Q& j+ G+ p. D
        2 => '双鱼座', . \3 d& Z9 Y* {2 h
        3 => '牡羊座',
' F; Q. E0 F$ G7 u4 }        4 => '金牛座',
' E7 G$ Q2 r, ]1 q" p        5 => '双子座',
1 U+ i3 w0 U7 M* ]( D4 Q        6 => '巨蟹座', 7 k+ u+ @8 {  }) B: _: E
        7 => '狮子座', - D: ?7 A* }0 B' r& \
        8 => '座', ' n  A7 h3 v. @0 g" |
        9 => '天秤座', - h5 l4 A7 A; `$ ^& l+ I
        10 => '天蝎座',
" G- F+ [  }1 N: K5 P3 K        11 => '射手座', % @# _6 G) Q( l  A/ o
        12 => '摩羯座'
2 D. t0 X8 O& x' w; p* U
! y7 T! s, F" }     生肖:0 => '',
. U; n+ o" K  O0 e; W) B        1 => '鼠', , @  X( S+ {3 @! b, h1 ^* [
        2 => '牛', 8 B$ D; A0 u' E2 p9 Y, w4 d' Q
        3 => '虎',
( |+ _+ I" f. O4 Y- y        4 => '兔', $ ~; |3 \. }0 E- l! @2 Y
        5 => '龙',
$ a4 g7 l  h3 G# i5 X        6 => '蛇',
$ Q& c, T9 D) q. L# @, h        7 => '马', 0 M+ C6 r5 X: [; X# W
        8 => '羊', - k* c) B& a1 N6 O3 i  e2 d
        9 => '猴',
+ v: }4 n2 v0 J! {        10 => '鸡', 8 D" A- }" d: o( t
        11 => '狗',
6 C6 M7 D, _8 X% H2 V        12 => '猪' ( _0 L7 }! l; B
, O) d, b, U  p9 f' R/ K0 t
     性别:0 => '男',
; \- ?0 s+ X9 [; k: u& q        1 => '女' 0 Z! x# r  a( T3 h/ P4 Y& \

% T' M9 U0 F. ](5).增加好友 ) ^# q, y3 P8 X8 X, ?/ {
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
5 u: e6 s4 q6 \5 E) ]3 [6 \8 l2 Z9 m5 v5 H- z
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
3 _6 P, |9 `2 |0 B     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) 7 D/ z& T- j4 x$ m! g
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) 6 G9 i) i  D2 W' F
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 9 s! J6 q" e# b/ U7 B; s* o# `3 J( `
     NULL(UIN、UN为字符) ; v( z4 N/ {7 k1 e, h
" k) ]# h8 b2 c( F
(5).发送验证 8 V1 q7 ]: w1 Y" x" ~' i
  说明:1、如果你加对方为好友,你需要发送验证 ' \+ M$ X" c8 c8 d8 k, u8 l& K% }
     2、对方加你为好友,发送了验证,你要通过或者拒绝
' u# p& i3 e1 P6 R8 `     这2种情况需要发送验证消息 ) k8 x: M! v1 F) Y7 R6 p! c8 V) c
0 _: e7 Z/ s$ h! i$ ]$ X
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
7 I% J+ Y6 B9 {  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。   L( c4 L8 a0 e

6 W, g3 L  ?# Y8 S, Q  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
" j2 |6 u3 C1 C  }. q/ U! Y     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) 9 V7 h0 k5 M! h
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ; i3 R/ Y: |: f) C3 D3 a" q3 y) _
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
: ]1 |" f* s4 x5 w& ^" J  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。 5 E& H" Y  N6 Z. @8 M
8 [/ N' h' B# _  M
(6).删除好友
2 s5 T  F4 P4 Y) D  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 # |- e& u/ _" A, _

- i+ o6 E1 l4 B  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) ( Z6 b6 ~* }$ B' `7 D1 d3 m
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)   X- a3 S; u6 t! ?2 |- t7 O$ |
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
; _; x8 Z' I1 K7 E! W     NULL(UIN、UN为字符) 2 }. ]- G7 D& F0 s
; W; Z5 T# `0 {: b' i$ A% E
(7).改变状态
/ ]5 q+ g: m' q6 i; A  ^8 j  n, W  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 2 k( w4 {  ]' h$ p
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
) b! r, k3 S# @$ \7 K4 J, e$ }2 s9 v6 w; s+ O- c3 b5 Q
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) 4 E1 s( C0 x6 _% T& W0 n* E1 C5 o$ p
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) 9 Z& ?. S. U: X3 A$ Z
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
$ N0 R) _: s* H4 E; R2 y- n  p     NULL(UIN为字符,ST非法) 0 v+ c2 C% D% X8 W

. s, M5 M- l* Y# e  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 0 D, ]7 F7 _5 U! P  y  b
       同理,当你的好友改变状态,你也会收到一条系统信息。 - d5 G8 K9 w2 I0 @2 p
$ E6 g8 O# n% v% M* U
(9).获得消息
5 p+ X9 s7 g2 ?0 \( i  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号 ! M0 e2 U5 m7 `, F* ?0 {. V
% d+ G, C! Z" R4 G  c" ?; P
  返回: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* f4 R2 D6 v7 N* q     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
  N5 b" E& d* L0 o( I# f     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 4 ^2 Q+ [, v+ q4 d
     NULL(UIN为字符) 4 N% f& c  s6 Z$ p; h3 o
  说明:关于MT: " X5 T3 Y. X, v0 i" ~+ R' m
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 8 Y3 i# ?; }; b$ M  Y! }
     关于MG: : C* w% i$ j$ C7 A1 R0 V* w, E7 q
       当MT=9时,MG为用户发送的消息内容 4 _: ~  R# e) f! z# f2 }, i
       当MT=99时, - j2 [! o) L9 H# \5 u5 E0 {
         MG=10(QQ_STATUS_ONLINE)表示对方上线
1 e: D* s4 q1 I' n& ^! W* r         MG=20(QQ_STATUS_OFFLINE)表示对方下线 3 x- @' f# V/ _1 }
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 & g" f- \  n$ I7 s
       当MT=2时,MG为对方请求你验证的信息
% p) d- ]  {" u# f, O) k       当MT=3时,表示对方通过你的验证 4 N3 y1 |  g* o( k
       当MT=4时,MG为对方拒绝你理由
" h- N$ ~" j) _* R" h
/ O5 X" ~+ z8 P8 d3 q& f0 F(10).发送消息 9 X+ ?  X" e+ u+ d
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 8 y. h, ?, L) s" x: J( ~% F: x( S

0 g6 C6 ]* H* w& I$ x  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
2 ?; b1 T# m: I4 f     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
& g; a( g) K# r7 o9 F, o     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 X: c$ L1 E- ?. e( w
     NULL(UIN、UN为字符,MG含非UTF-8字符) / R$ ]1 z8 e+ m( F9 H( N
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
- a2 @2 N2 w8 k- V- g  n' ]       你俩互为陌生人,且对方没有和你说过话
( J5 V, K+ K, r- Y) V1 K8 }       你在他的陌生人列表里,并且他没有和你说过话(没有验证) ! Q+ J1 {6 T4 @% ?
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s 3 l) z- d) w; ?" u# r" _  S6 f
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL " q) D$ i% e+ v/ I. a
5 n* Y9 H5 n2 x, H- `1 _' N
(11).登出
$ ?7 W6 d& R$ U% O- ^  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号 ! `5 ~: s. U- m( J* S" W  q: ^
$ F8 ?4 D9 x! U2 Y# I$ i! M, {) d# l3 l
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) + Y& w, d! b, z
     NULL(UIN为字符)
# z' A1 B' B  ]4 ^0 W) Q3 v4 \4 u% v" U6 j
5、总结 , e0 v8 `0 e( r1 O4 h8 j" T3 v
1 p3 i, [9 R4 N7 Z7 H
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
/ p4 I6 s& h, S7 g  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
8 A: E6 z  O2 b" F7 c; {  本文撰写时间仓促,难免有误,希望各位不吝赐教/ W4 b, w, s4 i1 o, }2 p" B

# Z" B  d6 b4 A3 V8 y
; ~2 g( X5 {# j0 qTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 00:20 , Processed in 0.019732 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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