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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
' X* W' ~1 w+ \5 A日期:2005.8.21凌晨
0 c! [+ I/ U( a* \联系:QQ:106814 Email:hackfan@vip.sina.com # ~+ B; |6 s$ L$ n% L, g

/ s9 E! {* t  E! N: l1、研究说明 7 ~+ y: f  I: b7 o" P

5 T$ ~: |3 i/ D. x  ?+ }" T# n  T  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 2 l6 @9 O5 S! u" u* [
* s1 C* k( l/ z: c
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
* g. _1 h. K9 H$ {" q/ |+ c# l8 `5 V  d$ r1 x
2、接口说明: / Z. R7 ?4 y1 m9 j" H1 ~+ v
* R" h" Q) {: F
  接口位置:tqq.tencent.com:8000 ( M) h3 _* e$ z8 Z% A1 k
  通信协议:HTTP / s& x  c; I1 v: N2 ~
  数据传输方法:POST ( f; R9 V$ A2 C" i  L3 j6 ]
  HTTP请求格式:
. Q) e2 x+ f  F' I- Z& q$ I: i
5 X# V; s7 l& P5 \" v6 F% VPOST HTTP/1.1 ! N! t0 ~" r. Z
Host: tqq.tencent.com:8000 7 a8 ]% d7 C4 N- Q7 @9 s0 k" E
Content-Type: text/plain; charset=UTF-8
0 y; Z4 a- M/ C# _; a2 `Content-length: 长度
. `6 |- l' ^9 ~- o( M$ C9 B; nConnection: close
1 c& O1 s- J0 A1 a+ M+ l' O( I. T+ |) a  k+ s' D; }6 R& r# M  n! t
数据 4 n/ }- Y5 g% M$ Q8 h$ y" J, l

' ]4 i* M; q% O' @5 D  其中长度为 数据 的长度,数据的格式: : ~4 L. f6 E9 ]/ |$ O1 z) F9 M" g
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&....
( k# y! u9 Y. l5 O/ U6 h3 N, q- `1 X7 h- I
  以上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还需要不同的参数,下面我就公布我的研究成果。 4 ~0 f; Y0 K) g; w
$ F5 i; S+ e4 y! K) O7 ]! R# D
3、研究方法: , B6 c2 _9 k& g  i: [! F: w
; L- K: _& Q5 a- u6 {
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 : k" m2 N4 B7 H# {# W3 x* G
  下面我公布我探测的代码(PHP):
  1. <?
    2 m* b( G. R) a, s+ ^
  2. $uin = "QQ号";
    0 Q0 O0 a4 h; w9 ]  l
  3. $pwd = md5("QQ密码");
    8 a$ n+ j9 r9 a/ j+ p% g1 K# l
  4. 4 u# X9 ^& U  Z4 N0 A) f9 B
  5. //登陆测试
    1 S1 }9 l9 ?- X4 P: k. }: C
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; ' K8 |& T" [2 d0 ^9 t/ {* C# g
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 ' F+ A. P( x. v
  8. /*******
    % U' a$ x4 \) r" I8 {
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    0 D( a# u# Y4 y) n+ ^9 i1 {- o
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    ' s. d' z$ o/ U+ X; |
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
    % r6 |0 D0 o! ?+ ]" q; e. n) \
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    & \' @. J7 O% E( J- R" f
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; . @. a3 [1 w+ u( N
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    7 x. Q6 m- f! T1 R( c* Y' C
  15. *******/ 6 ]2 v$ E0 V$ O5 m5 e9 ~

  16. . l' p7 v& S5 F7 ^

  17. 0 I* c" H3 _5 J! Z+ I
  18. //得到好友列表 % g1 g  F( l7 c  P# F3 e2 N% l7 ]
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    , L" `3 i8 S( `- P* f8 m
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    0 C+ g( s# r4 e* N' E5 P7 R# s! p
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    - a" F# `& _; l+ E9 ?; e5 u
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    2 s% r. |3 L* M* u% k
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 5 k; r: g  K  p- W5 Q" H# @$ Y
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; 8 z! L3 R* |* x% V0 g7 U
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; - N  C3 j* `5 ?( E% J2 `- u
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ) a7 v: a/ t1 ], s. K4 w
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    / B/ I/ J; Q- Z
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 9 \& b/ n- }, \: I+ g( e
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; + o% G* M0 p. f2 X1 b$ X
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    2 c+ g. a) b* o6 P) s, l  C; K6 @
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    5 [" N5 V. H$ Q! O
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); + ]% H- W2 \% |- J# N9 v) Y
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    , k: r/ P% w6 X! ]  a- @* I% |

  34. - S# M' h3 Z& t$ m4 T$ c
  35. //得到在线列表
    $ V7 l$ m, v4 @* f3 d, p5 L, ^
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; 1 R, W& X! @. S1 O4 i6 r
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    # L* M7 h- P& W( I
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    , ]( E' Z$ f' q8 B! a
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 4 n; J# J! ?# j
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    $ j! J3 F; F0 P/ W9 k/ H8 D. H
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; ) e& `! O. E) P" a( W5 T
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; , Y; q3 I9 u1 i! \) b2 Q
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 5 V* \  e6 o0 v
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ' n' [' X& A+ d# {
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 2 l5 X) E7 P6 s0 e  }$ W/ x" Z
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ! S6 e- {( I2 i
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ; S( ^/ n4 H, Q' q) O! f6 \
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) H5 L& p# @0 q+ L) }
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 4 W9 M' W+ T4 w6 K! L
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; ! E: U2 G2 T+ e9 d2 B* Y
  51. 7 Q) }8 M  ~2 f( C' X; Z
  52. //查看好友信息 . D2 @4 e5 m- }4 Z) Y
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; 0 z' }) [9 `0 V2 V# h
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    . H0 J! e3 n5 O# I: T
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    7 X+ R5 U5 K1 G" T' q$ A( L
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; - X' b. l2 g7 N- v
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; 9 o; [! g: i1 U; k- {$ s
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    % A* k' q3 c4 ~" W. f

  59. : G7 c% L" l3 M$ W& j$ g) t; o
  60. //增加好友 : o. u0 s; [- _* H4 y, |7 \
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    : d& M$ L- @0 V2 D: v
  62. ) |6 V; c" q3 ?, x% q7 ?% k0 K2 Q4 W
  63. //发送验证 ) S, e- g* A( F+ l% H- S7 H
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; 6 X4 p5 n) `: c
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; 9 c9 [* D: V0 D- Y$ E& v
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    % M& u9 k2 m2 Q& J7 x; H. b6 y
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    " `6 d! c7 l0 ?) W
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; # f) G# w# U8 p5 ?2 \! Y( H8 a* u
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    & Q8 B' |) ^% P8 }* k

  70. * r6 h$ Z% \& g
  71. //删除好友
    4 u0 N7 Q, d8 D4 a' d* j
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; , Z7 g& ~' W9 f! S" H1 R* s
  73. 9 }6 i0 d! K) O: Y1 X
  74. //改变状态
    - S! g9 ~% ]6 U/ J& D- N5 `  n4 I
  75. for($i=0;$i<=60;$i=$i+5) + R- r# ^4 D, @* ~2 \. V
  76. {
    ! ^9 e2 U! ?8 m( U8 h
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; 8 _  d8 }: b2 u1 t
  78. }
    * O# A' v& j$ o" |2 c7 L. y& B

  79. 9 z# _8 u5 S. ?9 E' H
  80. //获得消息 # A' S! d4 E" l4 h* ^
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    2 ^$ _3 f+ P5 O
  82. ) W3 ]6 t9 \- ~. I0 x/ m1 W* t- y
  83. //发送消息
    8 l8 ^# B8 B6 e+ T& a' s
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; # Z, s5 e2 p4 B* }( T4 [* N0 v! g/ b

  85. 0 L9 e( R0 `5 e. v- S
  86. //登出 0 c0 \: d# r# e1 ~+ L+ d# {
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; / P4 A" J' S5 I9 K" U& u1 R5 F

  88. 9 E7 t$ g9 }) h7 B
  89. $file = fopen("p.txt","w");
    3 p; I* Q8 ]8 K  `( `! m4 z% P

  90. , Q+ O9 {! K5 m: ~1 m( j
  91. foreach($poststring as $k=>$v) : ^  C0 I, C* {  n7 N9 T0 c
  92. { & L' z" _. k$ @$ O
  93. ss_timing_start();
    " }: C( ]% Y+ P
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    , J! v+ X/ @) ?5 Z' y
  95. % k5 {: w! R) _' a9 A
  96. if(!$fp){  % g9 o3 \) t$ {7 t0 C
  97. //error tell us  
    % G8 q9 i  A8 V
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  2 g/ e% G  c( T: o
  99.    
      c( `$ H; Y- B2 s
  100. }else{  
    8 X1 G: }) F5 \. R$ r  O" U. T( G

  101. 4 _& M, i! b- n' U
  102.   //send the server request  ' f  L2 H4 ]. B
  103.   fputs($fp, "POST HTTP/1.1\r\n");  1 m4 {' ?$ _5 g. V. k* l( G
  104. //  fputs($fp, "Host: $host\r\n");  2 o3 I" B9 q5 i5 E% ^1 K" k1 T
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    5 F0 Y) K1 Y0 C5 m  d5 s
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  : n- Y8 D3 K& [9 p! \6 C
  107.   fputs($fp, "Connection: close\r\n\r\n");  7 B6 I! {2 n2 R; D0 `
  108.   fputs($fp, $v . "\r\n\r\n");  
    ) v- i1 ?6 ]% W+ p' J$ \
  109. 7 X. e, ^% d9 s2 `' Y3 L4 }
  110.   //loop through the response from the server  4 c* `! Y& M3 I
  111.   $res = "";
      {7 \: I9 I( s1 O; d5 H' F
  112.   while(!feof($fp)) {    h4 k6 R( k* C) l! l
  113.   $res .= fgets($fp, 4096);  + ~; {2 n  m2 \
  114.   }  & K3 c( W. [5 z' f' Z/ {$ z
  115.   //close fp - we are done with it  ! R" V; u) Y# R2 i
  116.   fclose($fp);  , `$ S: Z& H! }3 i

  117. ( x9 N" n( B: X: R
  118.   $content = $v.chr(13).chr(10).$res;
    2 O2 G9 x( n3 j' C6 u% {
  119. }  " H& H% q& A5 V1 H3 [7 Y# G" N
  120. ss_timing_stop();  $ d# U; Y9 n. [* D' c
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); 4 m# b* m8 D8 T4 p9 u# S
  122. fputs($file,$content);
    0 m+ a. ~, R6 r4 f* t9 K( E6 \
  123. }
    / ]5 H3 x8 v$ c5 c; q
  124. fclose($file); * {6 W9 y. a8 |8 l
  125. ?>
    , _) Q1 D: x) Q+ L, j8 D
  126. <? 5 L& `2 m3 _$ B4 V( u) }& H/ d
  127. function ss_timing_start ($name = "default") {  5 [$ H& `4 C& F! ^/ |8 ^
  128. global $ss_timing_start_times;  - L' |, L4 j$ _8 n% l) f# k
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    5 q0 c, }1 j$ Z( b
  130. }  
    2 Q0 Z9 d8 J4 g
  131. function ss_timing_stop ($name = "default") {  
      N! W5 P; R" [1 a
  132. global $ss_timing_stop_times;  
    1 a$ Q/ p$ I/ u8 F! Y2 r
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  4 \1 @% C# m- _4 z; W+ Q# d1 I; D: I3 G  |
  134. }  $ @% ]9 T2 c* V/ s, l7 z! f6 M3 m
  135. function ss_timing_current ($name = "default") {  8 m' u6 |+ g- I5 C& m/ z
  136. global $ss_timing_start_times, $ss_timing_stop_times;  1 I8 m, k+ U: G5 ]2 R0 d, `
  137. if (!isset($ss_timing_start_times[$name])) {  
    * Q2 B2 q7 J3 X/ x
  138. return 0;  7 W* Q! O" Z+ X  i1 Q/ M
  139. }  / C/ s" f& U: r$ i* D3 d' R
  140. if (!isset($ss_timing_stop_times[$name])) {  4 [2 V" k, S) c  c  z0 K  T  X( g
  141. $stop_time = explode(' ', microtime());  
    6 c; Z( i1 B" K. f. d  a. Q5 |
  142. }  
    2 `( f; p+ Z- X. E+ Z2 K
  143. else {  
    / h. Z/ W; U; i, q; w1 [
  144. $stop_time = $ss_timing_stop_times[$name];  . i$ H% }+ x9 T3 i/ o. y" l  G, z
  145. }  
    , c1 b* i2 }% ^& [5 L1 W
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    9 `+ E% e2 E" q! I5 E7 ~& S
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    : O, Z3 {, Q5 j4 P3 w1 K9 p
  148. return $current;  
    % P) a3 n6 a6 B
  149. }  
    4 Y, |+ p& P4 y* k
  150. ?>
复制代码

' C6 l$ K6 O4 ]! x7 y# [; E4、研究成果: 2 w+ }; E# B+ e: K/ M

' a6 G, _! T3 |* [5 e- n(1).登陆 ; q8 c  j; ]( b8 [  i$ Q7 ?
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
* T/ r, \; I# v. F  l" J  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^
0 b! X# D  A& x0 C% S( [) U$ l4 y, F( ~- y& I2 z; }& S
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
: f$ p% F6 W5 G% j0 |  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; . ~/ o' N* B% ~$ f/ m! S
     M5这个参数的作用还不清楚,但最好为1。
+ Q. C. I* ?1 y' z$ G* _     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 4 m5 P" _: E, i# B
4 d" V8 W9 O. e: g9 ?8 R3 L
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) * r+ G7 h+ U9 i, L
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) 1 C' H1 |; y# G: a7 d7 a) I' y/ R
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
/ I) \5 ?+ s" s) A3 t1 ]     NULL(UIN为字符、PS为空、LC错误) : D/ R3 a1 A$ i! U) |# B
- ^8 }( f1 a6 K  q( e. u
(2).得到好友列表
+ _2 Q1 b+ s' v0 u* f7 t9 u  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 2 U( Y5 a2 J4 S
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
. u" k: ]6 s5 `( ~8 U7 K
2 c1 R9 v. z+ o4 _+ v  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) 9 H$ G% T( {5 Q, n# e
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) 8 A1 M( E7 L5 T& c+ d" I0 M( d
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
6 S4 w! \* E8 c2 e& B+ l2 a     NULL(UIN、TN、UN为字符)
* X+ w1 x8 f% h
; d5 {6 |) V* ?; g* }* Y4 V(3).得到在线好友列表
- N2 T" c+ P+ |  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 : ?1 Y1 I/ P8 ?: Z' i2 S; Y7 S
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
% R( H$ R  T. [' ?0 A1 f  \5 D
* F, k3 h* @  s8 e  返回: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的值用','分割,分别表示头像、状态、号码、昵称) % B5 _0 o$ f  e0 ~
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
8 k7 ?- m' r+ r( i' E     NULL(UIN、TN、UN为字符)
1 q& C* n) S+ g0 Y  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
; x& q9 D& z. k     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
1 L* E- |5 Q" m. @) Y( \4 k, }
) W' c, s" S" j4 a3 b1 K( a  特别说明:当参数TN=0或不存在时,服务器返回:
& R  l! i+ e& K) b2 j! MVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
9 W" V$ H9 B7 A* a4 z) G3 _% sHTTP/1.1 200 OK
4 ], e" p3 R$ _7 T& uServer: tencent imserver/1.0.0
& F4 B$ h, G( c6 f8 Q( S+ `Content-Type: text/plain; charset=UTF-8
* N+ [. U* }9 b+ x6 b5 \2 g( C" G: PContent-Length: 56
; X, G2 E9 H3 `4 a( W
) S9 o, r. i( L, {VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
) F/ ]( x3 J" J/ H& iHTTP/1.1 200 OK
4 [- L4 j* X; G2 u4 sServer: tencent imserver/1.0.0
% u( i5 k/ L6 k7 F, kContent-Type: text/plain; charset=UTF-8
2 F, @  {! [+ y( ^' kContent-Length: 77 - k% a9 f4 J1 I6 R' G  m6 s8 e1 p

5 r( v& i6 P6 C- O. AVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= : I: }. J( f8 k/ n% Z! R
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。 ' L& ]- A* M; ?, d% n; s. H& ]
" {9 I/ x( b9 g/ h9 v; V- L8 j1 A7 r/ {
(4).查看好友信息
7 Q, S9 ]- g$ U# s! W" b+ ?  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 - x0 |4 f  K7 Y. |5 @
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 9 r6 f% v" j. W# {  ~
% z- ?+ g0 V0 C1 k, m
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
" o, T! ?7 F; C) \! m, a$ 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=学生
: a4 h& X, H- F) x2 [- t&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  8 Y# v4 f6 o' C; ^" p
好(普通查询) + s% ^6 \* w2 j) R2 X# T1 W
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
2 m1 V3 O- {5 K9 f% ?&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  
0 _/ P* G+ J0 Q$ y$ Y1 Q, zupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) 6 D6 k9 }% I, w3 v. X4 }3 y
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
# L; ^$ z( h9 ]. W     NULL(UIN、LV、UN为字符)
, }& U3 d7 j. a) g5 V5 y9 f+ |# W7 L. R- Y, B: _. u3 S. `
  说明:AD为联系地址 8 B$ X+ i) A$ j5 N+ |
     AG为年龄 % b) U  l; q4 _& l7 _
     BT为血型 $ z4 J; B' R: B: C, z3 M
     CO为星座
5 o, c. {5 A/ M+ r* t     CT为城市
8 w( W3 v% `2 f# C/ v     CV为未知*
9 C. D, `' w( V# M! f     CY为国家
9 ^) w9 }0 `% c' t* ^4 D     EM为Email
1 l8 m6 m9 z) l! C: h     FC为头像
6 m2 Z  W9 g/ R/ r. E) z0 P     HP为网站
0 h8 M  n2 C. i- g     ID为未知 ( d. I/ k' L: A# C
     JB为职业 , _3 [5 H) t& X0 t: o+ G$ t
     LV为查询代码(就是发送的LV)
2 q+ k- k( T" Q     MO为移动电话 : {: A. J, w4 G6 V! b6 K2 @! ^
     MT为未知 / n& F) j6 Q6 }  v$ Y
     MV为未知
* O! T/ K( Y1 X1 Y. Q# _# G     PC为邮编
1 W! M+ ~$ f9 b" U     PH为联系电话 5 g# ^( Q2 P/ l" b3 Y/ q: f2 [
     PR为简介 ; W) h+ _4 I* {& Y4 O+ G
     PV为省 ; ~. ?3 W* p/ U* Z: M
     RN为真实姓名
  P) `% S+ k7 @4 J( T/ Q" K) C     SC为毕业院校 & [& r+ U' S# s, d- x( O# _% C
     SH为生肖
) T, T0 o* Y/ Q& z     SX为性别
! U( k, f4 z! V7 Z% P3 E, l     UN为QQ号 6 b, ?' c2 l& k( g% P. g1 y: }1 f9 b
     NK为昵称
: l6 J" T( [8 z8 q5 k4 n
+ l" }8 {/ b' c' f* [     血型:0 => '', * N' X  ]. G' j+ a& @2 c6 m9 ^9 F
        1 => 'A型', ( n* b  V& i. B: u
        2 => 'B型',
: S* x+ W, Y) P7 |2 Y! v  O6 u2 Y& ?        3 => 'O型',
) M0 D& r$ ?# a/ o& U        4 => 'AB型', . w1 T4 Z/ Y5 U; a& h
        5 => '其他'
/ \9 q% n$ p  }; H  A; x% I1 V4 H: G4 _7 V& B5 S, X9 P  }

* f! J1 r  c8 |" W     星座:0 => '',
/ W+ O( R1 F& y! z, ]        1 => '水瓶座',
3 o" F/ R! O1 k8 o) F" ?( |        2 => '双鱼座',
9 I2 p7 \3 e% C! B        3 => '牡羊座',
6 n0 C" {" h, ?1 x$ }. G% d& Q        4 => '金牛座',
1 ]. P) Y* O* ^1 f2 g        5 => '双子座',
3 ^! [3 {! F" K/ w6 x        6 => '巨蟹座',
; E- S6 H; y! K        7 => '狮子座', 7 n; F3 `0 d. f
        8 => '座', # k1 D2 |: H; w2 k- t* R+ b* y$ I
        9 => '天秤座',
8 \( a& i& j$ J        10 => '天蝎座', 0 n1 a6 F( Y. \0 N
        11 => '射手座',
3 T, B: v, f3 o0 l6 a9 \        12 => '摩羯座'
9 E: F  J. i1 Y
( Z/ ~5 H" K# J' }/ t* B     生肖:0 => '',
" B5 h1 H# k2 v5 T        1 => '鼠', 0 j* p$ T2 B: N. k6 ]
        2 => '牛', 8 c. s) ^3 Q. i' i& G/ ^; o( _+ E- V
        3 => '虎', 4 r# K! \' F7 a6 t6 g, B/ A
        4 => '兔',
. W, o8 L6 ?5 ~' S4 m( d4 I/ ~        5 => '龙', # u( s; C9 H" j0 y
        6 => '蛇', ) j2 b3 y) _5 |& C0 ]  p
        7 => '马', 3 C4 [' _& I# t% i0 @# x
        8 => '羊', + _' |- D* k( y
        9 => '猴',
% l/ i% v! h7 v9 f7 f2 |& M        10 => '鸡', 3 v1 l5 L& z0 G  m0 h
        11 => '狗',
$ n5 P+ c+ J. K  H+ {9 E9 t( l        12 => '猪' , E6 \- Z) w+ n- o
+ K" E! i' z+ A
     性别:0 => '男', , P4 d9 @" G9 x+ x, U$ |) F
        1 => '女'
0 m) Q  b3 f) I9 ~( D6 I# _: H( H
: l  |) u+ c5 z- z' V1 O7 M(5).增加好友 4 Y4 K) A& T' U5 ~+ c: U
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 0 k% {5 H& q, G' M; V9 l& h
6 K* f- n+ j. `/ p" S0 X+ t" J
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
# H8 l/ o+ U3 x4 ~4 W* @     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
! U4 p1 z# H- ~1 T4 E7 _     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
1 i9 m& e" Q2 i/ K: E     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
0 h8 D- ^" K" l  t     NULL(UIN、UN为字符)
# C: ?7 e0 @# I# Y. l! r8 d9 i
(5).发送验证 $ e( A" _) u1 B% ?, B0 v
  说明:1、如果你加对方为好友,你需要发送验证 / C5 p9 `4 m4 a' W4 A" ^
     2、对方加你为好友,发送了验证,你要通过或者拒绝 ; ^/ z, |) Y: r% z$ U
     这2种情况需要发送验证消息
* x: c3 ^( w' t1 L* |* b3 {/ ~0 D0 I- l7 `, n* o
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
' C6 S7 \1 `* t! @- h- }) a  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
2 r$ _( c2 Q3 M/ u/ _$ i: |8 A1 D: V2 L, ?
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
/ \+ T1 ^# h( t( g7 f$ n' T; ]+ n     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) % i8 N/ ]: q8 Q2 B5 B, W
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 J0 d( [% ?: R- v# E
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) 4 M- S( I3 P& y1 I( b$ M
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
9 T& B' b" V6 h/ i5 C: m
& `8 |% c" i4 u1 a- C8 x& U' ^(6).删除好友 . J( h  G* ]/ x# ?# C7 l
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
$ {6 |2 ~! h7 C9 c' w3 U
( _6 m5 p8 _6 t7 i& b* l2 t- d4 p  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
! p! \  P) i- ^0 i     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) ( I) w6 u- r7 F9 h5 V) N: B8 o
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) + j$ F" H3 P6 \
     NULL(UIN、UN为字符)
. _: m7 A* ~0 K# O3 Q
# Z0 i2 D' _# z0 \. y- b( r(7).改变状态 % o( j5 L4 p7 P8 d% I8 R: d
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
5 [( ~5 ]% @. \. \  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 ; N0 E1 u* x( D+ u$ B) v
# B* |  Z0 c0 |# e# D
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
/ Z8 }# l$ S0 y3 M8 _) @3 p     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) - u% H% f2 K# Y( ^
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
, a! o* g! o0 ~, e( C     NULL(UIN为字符,ST非法) 8 C* t# |/ ]4 r* e0 w3 Z( R

/ p* E1 H  \& f6 j, s* b0 Z6 S  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 + U1 H* ~/ x& E% r
       同理,当你的好友改变状态,你也会收到一条系统信息。 6 w7 d: f0 M" {$ q  ?3 V
$ o0 v0 q$ U$ X4 T! d
(9).获得消息
2 j* F- ?& k  `. {, M) z' b  |  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号   Q: C" p( R; L1 o; i

- S+ `9 O, }) J+ q) j8 o  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) * \+ C) y6 K. K# H* v6 _
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) # |4 b' u9 u9 [- m/ p" _2 l
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) - N( F7 E7 r7 U* z* \
     NULL(UIN为字符)
9 i% h9 a/ e3 j  说明:关于MT: ( n& M4 E- C3 f; A
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 1 C. h9 s' y* Z6 m& B; i8 b8 w: }
     关于MG: / B. Q4 o; n  M- g$ E3 C3 l
       当MT=9时,MG为用户发送的消息内容
$ p8 c3 _# g5 u3 ~* @: z       当MT=99时, " F5 S+ n' F" G; c8 _: B( V4 T
         MG=10(QQ_STATUS_ONLINE)表示对方上线
! o1 l! ?' ?( Z" D: d5 e/ V         MG=20(QQ_STATUS_OFFLINE)表示对方下线
- t3 A# Z6 p; W3 I6 C- c! i         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 8 b# b. ]: |; F' G, s
       当MT=2时,MG为对方请求你验证的信息
9 g2 k! w# Y* C# [  ?- G* K       当MT=3时,表示对方通过你的验证
) a2 B4 E+ k9 o, e7 S9 V5 t4 C       当MT=4时,MG为对方拒绝你理由
- F; T5 B$ w3 r6 D: y9 X) r: @7 |" G3 O- B4 y0 R+ {) O1 g; t
(10).发送消息
( Q4 ]5 s+ }$ f+ d( W0 ^2 a  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
# k% a$ J6 Y5 ~8 K. U+ A
6 E; O# }% N. j% E  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
8 J, p: V6 c0 U5 p8 B     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
" F- C) N1 \& {* }5 D  I     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) / \* E# X% u3 _* ]6 B- c0 K
     NULL(UIN、UN为字符,MG含非UTF-8字符)
- p$ @  F) U( P7 p# H  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
; U8 V6 u, m) Y/ n  l7 |+ C4 M       你俩互为陌生人,且对方没有和你说过话
3 m' p9 b: \, U       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
# a$ m. `% N4 f5 |+ @6 g6 A     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
4 \. w, ?% g5 Y5 B- f8 K$ o     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
6 d4 c; _* l) J) w6 s3 v$ }8 W% t8 _; z$ }, i( U
(11).登出 ) d0 X! }) r) h% W$ T/ P
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号 0 z& x; q/ I1 `: j5 c3 l! U
$ P0 ]# Y+ s/ o( v
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) 6 t. I. Z4 {4 l; l/ t; T+ W* e
     NULL(UIN为字符)
4 Y7 z% I8 v7 A* T% |+ w3 o* Y4 x3 K2 J% g
5、总结
7 D# Z  o. N' K" w- a1 i7 X, E, u" w: d, x  p
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 4 a* U  k& [. A$ A; z
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
6 z( C+ m! E- t- c$ F$ {  本文撰写时间仓促,难免有误,希望各位不吝赐教
, b2 K" F' J5 F. Q4 i
/ q) j6 q) `# q. f$ D
. m( P6 G# f- S. H+ YTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 09:52 , Processed in 0.018492 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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