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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan ( {+ h  l# ?4 {2 P% ]7 j
日期:2005.8.21凌晨
% A1 p% X& h; z9 r5 w/ @联系:QQ:106814 Email:hackfan@vip.sina.com
& y" Z; J$ u! n* l, X
4 L# ^* @' A2 c4 l: k% H, e1、研究说明
6 q& Z5 K" Y! q) ]
0 C; U8 i3 G& W% A9 ]" ?  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 7 P. ^0 Y; Y* b1 r2 ]
* F( b. v8 c3 M# q
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 ' W7 `0 Y, I! y: W6 D

* ~& u- N& f9 q0 K2 o. C3 Q2、接口说明:
5 Z& w. p& j3 D  g, L$ O" f1 i& v
8 a, B5 a2 s2 M+ L; ^. `  接口位置:tqq.tencent.com:8000 * Q9 b2 h' U0 G" P
  通信协议:HTTP
6 U( v2 z: @* L: U; s  数据传输方法:POST
9 _/ l" R* t5 w4 W1 \5 r" G  HTTP请求格式: 0 m1 H7 H4 _& Y; m1 X5 K$ z6 }6 I

; s% h# E$ [/ [& i/ b5 APOST HTTP/1.1 4 \! e2 l3 S+ V8 [$ h4 t
Host: tqq.tencent.com:8000
# P- i8 Z- J9 HContent-Type: text/plain; charset=UTF-8 5 y3 S3 Q- |4 Y' J$ I5 `  o/ _! p
Content-length: 长度
7 I6 ^# l6 r% a, D1 q0 Q6 vConnection: close
% \" L6 r- p$ q# y& \: `$ H
4 U& }' h7 l& h+ O: P& K+ |数据 8 i/ L3 d/ L' W! A! _1 G5 k6 d
0 R; r( F9 j& q0 h4 x
  其中长度为 数据 的长度,数据的格式:
8 x5 ~) j. ?8 @/ j1 W! X1 X  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... 4 ^4 o$ s$ ?1 Y$ V! g) v

& U9 x2 _9 h9 l1 @/ P) Q  以上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还需要不同的参数,下面我就公布我的研究成果。 - R" q. R2 @2 L/ k

7 `# m, x( Q. }, X/ [3 W; P! f8 `3、研究方法:
# @3 C5 J" T4 T' @' R
2 j- g7 w, ?( Q2 e6 U/ ^  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
$ _' i4 w& V7 w0 o! R+ a8 ^; g& X  下面我公布我探测的代码(PHP):
  1. <? 7 A& f2 p( @: r8 _+ _7 P, u0 w4 l2 f
  2. $uin = "QQ号"; 2 y3 E1 L; s. E
  3. $pwd = md5("QQ密码");
      c# q' p' B! c  g0 {  P

  4. ( ~5 j# q# s. p  m
  5. //登陆测试 ) l6 y1 ~, ]: K& B) a2 M$ u5 ]
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; : C- A/ {7 n0 U4 L0 g. F
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    " n4 j- H( J7 k1 i
  8. /******* # h. I' O9 C; x2 Q& t# G2 }: v
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; ; u* H0 X; }' ~) q* W
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    : I' P# a. }- W7 ?) J
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; ) G& L) }: N8 P4 y9 l6 j$ G
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    " X/ M% V. c$ e+ \" V- K+ F
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    & c6 |: {+ ~5 H
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    : s; Q9 ], g& O4 m7 c  C& p
  15. *******/
    ) @6 b# v9 D' S0 C  @1 _

  16. - |7 k* Y/ d  @1 C# e# S4 F! I. J

  17. 9 p6 {0 U" A2 c4 k) b- E
  18. //得到好友列表 ( W8 ~  Z0 _! k+ A
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; + j  D& ?! j" y# F( J6 O7 F
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 3 B+ L+ i; T# Q3 U+ D
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 5 Y: W' G+ Z# h9 V
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; $ N; K/ @) T6 i8 z' Y5 q9 a
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    ( t/ N5 E3 C9 K3 E1 I$ ]' d5 \
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; 6 a( p3 l- U) T8 S. U: q
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    / [' j* d& E! w. m' c
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ( N6 p/ Z' n3 `" ^! K, W
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 8 o: N  X7 L0 g! l" V0 _9 }% A
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; + ]* ]  P0 A" H- o6 J+ P
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    * F0 f& a' p. T2 s: w0 `) F) m0 M# V
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    . e! I2 L  Y4 m7 w
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ) w1 @4 v$ R3 g# q% B& [- u+ A
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 8 b1 ?0 N/ H# E2 X+ o' p
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    - p/ C- I- L5 ?8 O5 N3 P1 q. p
  34. 7 x$ q  C  C0 h9 d
  35. //得到在线列表
    : x0 ?& T- }: W4 {) m
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; 0 z& O5 r- v* u: W/ C% E
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    ; e; o. e3 J  @+ A6 ~  `
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    0 x7 ?& R6 u6 ~; v; i
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    / n" G3 s9 D# V8 @$ M' V
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 3 b$ N  T: \. z
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    ! V8 J  A/ o% U
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    4 h5 H2 J4 l$ H: |7 b# @
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ' k1 s* \6 M5 |! }; ~7 H- `# ]
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    2 R- `0 {/ _' [
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
      O# t" c8 O* R, m/ _/ \" B1 G
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; # F$ ]' w, W# \  }3 L  g3 X, k
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    2 c. |: K9 k8 o
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    - c% I; e" J3 V, Y+ v  L
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 9 I0 o: T+ z& @- d
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; . I' G5 ]2 h7 A5 L( s
  51. 9 y, Y' }, S& T5 c# O7 i: z+ l( d
  52. //查看好友信息
    ( |% ^  h/ R$ M7 L# i3 ^
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
      d+ I* F2 M0 V2 w; K
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    ; U; A- Y7 q% ?/ i! L( P' L+ a
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    , j2 ~, r& j$ S3 H% X- `
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; . J$ G9 m* o5 n" x' N+ w- ~
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    . d+ o" S* G  K" I. e. R
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; 6 C, Q5 k4 i# m$ X) |5 s
  59. . X4 v2 g2 F: K: X+ ^/ W
  60. //增加好友
    2 K3 I0 ~. w7 w. s6 `; s! s
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    * }# ]$ ^' O6 F8 U

  62. $ J$ _; N. Z4 D, M* {( x; V
  63. //发送验证 5 n9 P/ _% Z; H, e0 F
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    - j7 d1 B. J. a4 L1 I: d" |
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; 0 M) v; p1 c( P
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    ( k" q+ c$ D( K: e' `7 l# X# i1 t( U
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST"; . A7 C1 N3 g3 l% w9 q
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    2 Y1 @7 r) `& P$ [2 i- ^: Z
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    . s( A9 w- ?5 U  j; F

  70. 5 F" M, U% ]6 [3 j0 d, b7 P
  71. //删除好友
    ! U5 w( e- F8 V. o7 A
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; , M2 E$ E$ z- \# s1 ]. V# X6 i

  73. 1 \8 N" p" T+ m7 K' A3 N
  74. //改变状态 ' S3 w& ^  @. g5 Y& r$ ^4 a5 ~
  75. for($i=0;$i<=60;$i=$i+5) ; o, p) x& ?3 l* B' I' s7 v) i7 j0 N
  76. {
    + G, u* U4 r- T( q
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    ! P* G* K9 O! I. A: b
  78. }
    5 ?& g1 s) |# _; |: {

  79. 2 J$ e3 o  P1 z& P
  80. //获得消息
    5 [0 Q. [. G( f, ^
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    , D5 ~# I  n& _  e0 E6 ?
  82. / V+ t, `# L& Y. Z( d! ]
  83. //发送消息 $ J9 Q8 }! B' B# @; Y) L/ M
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    2 [' h2 H! A3 i( D, ]8 Y# B

  85. 6 s  x. F, N* t$ N
  86. //登出
    3 z. |2 j$ _4 {3 J8 r$ M% ^2 I" r
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; : w1 k& I2 j' e% q+ l
  88. 4 Q6 b/ g! L3 ^/ L3 r# g; G4 i) q
  89. $file = fopen("p.txt","w");
      m3 o$ G3 t* a$ M4 O# d7 C! x5 Q4 R

  90. / }" g% ~, c' ^+ {* [, P! p5 Q7 `. e$ \
  91. foreach($poststring as $k=>$v) 9 O; [8 s* v& Y- ?7 Y* A2 H
  92. {
    $ F2 G3 `# N* i8 ~* N1 O1 O9 m
  93. ss_timing_start();   Q! j8 @+ |4 O" B! I" @1 _
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    4 @# V8 V8 R  z: ?6 K

  95. $ t' J3 J/ W# F% D
  96. if(!$fp){  9 U" T2 u8 h% h- v0 ?' S/ \+ |
  97. //error tell us  , \! b2 L3 Z( O7 R: E, F
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    5 `5 u" X& o; n" `$ a) R+ U
  99.    
    2 D$ L4 t* G2 `% h& \
  100. }else{  
    : M. d: A9 a5 ]' J7 s/ k
  101. 9 d  V1 i$ H4 U) l
  102.   //send the server request  4 [% M+ {% _9 o' k4 \; ]' {
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    8 n6 A& V  F, @  o
  104. //  fputs($fp, "Host: $host\r\n");  % G5 Y! ?, e3 x$ o2 _" S( s9 T
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  $ i* j1 \+ a, T  j; T5 A/ m6 E
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
      l3 X* b4 X+ s" b- Y( f
  107.   fputs($fp, "Connection: close\r\n\r\n");  # T& F3 n. v, H' |; S
  108.   fputs($fp, $v . "\r\n\r\n");  
    ; j& Z% f- e, b, T

  109. + l3 n) s+ R3 U+ @) Q+ A+ a
  110.   //loop through the response from the server  
    8 s3 w. F, e' ~  X1 ]
  111.   $res = "";
    & t- V! _% l2 {4 b$ a" |/ }
  112.   while(!feof($fp)) {  ; K. o1 [( l. g5 t1 [% b
  113.   $res .= fgets($fp, 4096);  
    $ E3 i- S; \. X& l' u7 n
  114.   }  4 i5 n3 U/ h" Q) R# w
  115.   //close fp - we are done with it  
    2 F; k1 C. U& G( ^* v: a
  116.   fclose($fp);  / Y- a/ m; t0 q% J9 @
  117. ; G1 P$ F$ L7 L/ A! y
  118.   $content = $v.chr(13).chr(10).$res;
    5 |3 |2 t+ X& ~" \
  119. }  
    7 _+ z% h6 e  V  I; a
  120. ss_timing_stop();  
    4 L: q1 r. x5 u( U4 M2 `8 w  h$ p
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    5 Z: A$ b6 m' \3 O2 g
  122. fputs($file,$content);   E8 q. S7 s4 Q$ P* G0 B! ]0 ^
  123. }
    % w/ t" [# F9 ~( ~7 [! j9 Z
  124. fclose($file);
    ' B! |1 l, Y  I. |8 ^
  125. ?> % u; t* \; ^& h9 `+ n" L
  126. <? , a5 _5 N& u& f, x- M
  127. function ss_timing_start ($name = "default") {  
    . m0 S% |; }5 t" T5 V/ S
  128. global $ss_timing_start_times;  . F6 U0 M$ ^" I2 C; V
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    , }4 X6 ~3 N- y$ M" j
  130. }  7 f2 F9 j+ C; M/ J- U5 q6 |+ G: K
  131. function ss_timing_stop ($name = "default") {  
    2 S5 r. l" o+ p
  132. global $ss_timing_stop_times;  7 R% a3 D* K+ H$ Z) Z: Y5 o* i2 i6 |
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  9 ], i/ i/ e" m
  134. }  
    ! I0 [$ a0 G* {$ e6 k2 R1 T
  135. function ss_timing_current ($name = "default") {  
    2 i7 ?* G# r' f' h2 v
  136. global $ss_timing_start_times, $ss_timing_stop_times;  , j! O0 \& |. X( I: N' q, v
  137. if (!isset($ss_timing_start_times[$name])) {  2 }- K, h" c7 M. d
  138. return 0;  
    9 `: q# q8 s* E% m
  139. }  2 W( k& ?( G. `) [
  140. if (!isset($ss_timing_stop_times[$name])) {  8 E; I" k  G9 g) o
  141. $stop_time = explode(' ', microtime());  4 W( |9 a& J7 A2 S
  142. }  
      n# c& x7 o" _: [
  143. else {  
    + H; H- _* G. J; g8 [( f* T& p
  144. $stop_time = $ss_timing_stop_times[$name];  
    & P' {* j0 m( _) T# g8 D
  145. }  
    - n* x0 X1 @" T% b, j8 H' @
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    3 x" T- e& d6 l/ Y* ~( F
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    * r5 T- w: `- |$ W% y7 y
  148. return $current;  
    0 J( g, r  M+ r; P
  149. }  5 j/ d4 W9 b0 O6 Q
  150. ?>
复制代码

3 C/ V5 x( {0 n3 W& M1 }4、研究成果:
0 g; K) e& d' ~1 D8 {1 \7 P7 w
0 |; y+ M9 P0 d- u(1).登陆
9 B, D3 Z# e4 C5 Q" X+ n  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 ; }. C: W; U" b. R8 k0 y5 R
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ . l# t- H8 n6 Z6 c$ g5 R
" v2 `3 w- r7 @4 s
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 8 Z# A1 Q# k. D; H7 z
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
/ G. A5 k: f7 }2 g# J( k/ d     M5这个参数的作用还不清楚,但最好为1。 ' I. e, C+ c; J' c0 o
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
$ m. e7 O* ~( H% Y5 Q  u0 H0 R0 u/ l5 p8 w# O
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) 2 N8 k) Z" f% P8 X$ V9 ~5 D
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
  A. w* @: K8 l) Q# o% @     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
1 E1 R! O$ F' l7 Y/ e: f     NULL(UIN为字符、PS为空、LC错误)
0 f7 \- B, h  ]- s' l
% P1 {+ _* b, m) c2 r(2).得到好友列表
4 U4 c- ?. J5 S0 E6 N/ r& S, }. ]  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
! D2 W/ h+ i( D" C  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
' M6 H- [; P) i- F. I
- k& t* u6 v4 l8 Q4 C* @  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) 5 m* `! r# d2 a; J
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
! `, p# o9 B: O  j& ^7 J     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) $ N$ @- _+ v+ {% y) X/ Y
     NULL(UIN、TN、UN为字符) 0 M3 U2 A* ^6 x: a% A
1 m( o& M" p6 F$ b
(3).得到在线好友列表
& p0 o8 m( I+ e4 ^& @  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
* ~3 W2 s4 S3 I( {  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 2 P9 b, M. [9 A. ]  I8 C9 c* B
8 j1 k7 u% ~) w' `& \" q: I, Y
  返回: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的值用','分割,分别表示头像、状态、号码、昵称) , M8 l) x0 x. V4 a
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
0 t4 D2 H1 x0 s+ z6 T# J; f/ Y     NULL(UIN、TN、UN为字符)
7 |) U+ G7 g  }  \" X% S  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; : D$ A$ n" i* R2 ~0 Y
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
6 N0 g* G/ Q- J
7 W7 R! I1 W: v  特别说明:当参数TN=0或不存在时,服务器返回: # @9 F6 T( R7 o) U; y: R. W; U! z
VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 # S. o, ^8 o9 s7 h) R3 K
HTTP/1.1 200 OK % J' ]' x/ |3 \! m
Server: tencent imserver/1.0.0
1 Y" b; X" m! v# O* b( _- wContent-Type: text/plain; charset=UTF-8
8 n! @% ?# c) P( H7 e6 KContent-Length: 56
/ g; v; U; G2 }
& x5 ]1 ]. c; i$ F- MVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
& m$ V# E% L% T! h7 Y5 |, C+ EHTTP/1.1 200 OK 3 U7 l7 L5 X, R% u0 }; U/ ^" Z
Server: tencent imserver/1.0.0 4 u4 A! S" q6 x2 C
Content-Type: text/plain; charset=UTF-8 3 c! A3 }8 I. n. v  b( b
Content-Length: 77
/ n. x$ g3 N2 Q/ S( J: E; Q& C1 h: ?% T* y. C$ T8 w: J
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
( r" y/ `& z8 \) t: J$ d  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
* b% ~' P6 _, H- Q, C
# n: ]2 U( O7 `0 D: Q$ p! X0 ~0 x+ F(4).查看好友信息 ! T% J) S5 w+ ?) s
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 1 y0 j# V* F5 l: q0 F. S
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 2 Q+ t6 {  ~0 r7 z, E0 W) j

' E7 h+ B9 V# r* V" p, Y9 O  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
3 K% ]  {8 P' y- u# I" m7 e% W     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=学生
$ g# l- D3 m2 [3 y2 I$ \& W&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
3 i1 ?; O! Z$ I9 y& b. n好(普通查询)
! R& l* D1 E. R4 t     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 6 c( r9 `# g; S, ]; U" G5 N' I
&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  
9 V+ P# E0 X0 e# Lupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) ' V2 q" |! b. D! |% Y% j/ B, y
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 2 N& E" c+ @0 J2 u% {
     NULL(UIN、LV、UN为字符) 2 R1 K( X/ T8 u, j2 R8 T. Q- K" {
, `3 \; W0 K1 Y3 q
  说明:AD为联系地址 ' {' v1 e3 u9 u3 e
     AG为年龄
5 u+ M; a3 B/ c6 b4 J$ v. }     BT为血型 ! L1 L5 d6 D9 q' ^6 P- E; X1 X
     CO为星座 / n% i) G# S7 W8 g7 z
     CT为城市
; b  U4 x- c, r$ k' Z) |- q( `     CV为未知*   y0 `9 w5 g0 p" `6 f
     CY为国家
5 m+ V+ ]& i0 U3 N, z3 |9 x* S     EM为Email   U: n7 }- q2 K5 F7 [
     FC为头像
: F  v; R$ s% t4 ?1 }  p! [     HP为网站 ! c$ O! P" e8 c
     ID为未知
. f6 V# d% c+ z     JB为职业 , N) T$ _* a7 o1 B; K% ?
     LV为查询代码(就是发送的LV)
2 u( @! a+ c6 r. t+ p6 U     MO为移动电话
$ v& B4 }" b# F( l     MT为未知 * G* l# H1 B- c. w
     MV为未知
5 G8 A9 p/ @/ C' w3 }+ W' t     PC为邮编 + l  P# \! C6 [5 o9 H
     PH为联系电话 & A2 C/ \  e2 }% K) w5 Z
     PR为简介 - b" H; p" n* I' o4 Y. M/ o5 P. Y$ C( v
     PV为省
+ w! }9 y9 f, q6 S     RN为真实姓名 . N; k# I6 i' ^& [. A2 y+ h
     SC为毕业院校
: L) B, C' m  l/ ?5 E1 I     SH为生肖
! U$ Y5 k3 q% x! f8 u     SX为性别
6 B. N0 R& J* w+ k     UN为QQ号
- R# F) g6 m- y; F# T! g     NK为昵称
# P$ }8 @& I8 k* b8 G" q- E6 n, o; K% F: ~- y1 ]. m
     血型:0 => '',
0 I% P  V" i: Y9 x; _6 }3 j        1 => 'A型', . r) }" _& A- }3 G# Y) l  d, j
        2 => 'B型',
. J4 m! }, g' ?" n# ~) R% _  v- \        3 => 'O型', 2 ]& H; H2 M) }# H! K1 g
        4 => 'AB型', 9 z' B* r* F/ ?
        5 => '其他' 1 w  e+ Y$ G; u; j- c

* K3 Z" W; L# C. T7 k* Z: f; H
) c/ P- a* L# D- a3 s) D! Q/ v     星座:0 => '', ' J0 v) ~+ f9 j& \( F6 p
        1 => '水瓶座',
& E, o) M9 J9 k& {& E" B( [: O        2 => '双鱼座',
9 }% U5 M! {6 [8 T  Y; s* k$ p  H        3 => '牡羊座', $ D. c7 I: H: P* Q: L
        4 => '金牛座', 0 [. \$ J7 i& F$ V/ {9 _1 S
        5 => '双子座', ; M9 ^, ~: }6 L! G5 ]4 y) I0 d
        6 => '巨蟹座',
- s' u2 U  r7 ^& \        7 => '狮子座',
* O9 W3 ^8 G5 X7 l        8 => '座', . K* J' h% H9 U( s4 P  \3 j: J
        9 => '天秤座',
. [9 P# V7 U; V/ y* B' C; ?        10 => '天蝎座',
  R0 y) S2 G( x0 A        11 => '射手座',
- F# E3 Y( X. _( I! G2 O& q$ Y" L1 {        12 => '摩羯座'
* V1 z& P3 j! o6 }0 H. F3 L2 Q+ A' O" g, k+ m8 X
     生肖:0 => '', 3 O; |4 z- T! f
        1 => '鼠', 6 K0 V$ D: Y: T- g( l$ N
        2 => '牛',
0 B6 ]- {5 J1 z        3 => '虎', + u* L  M7 y6 @- D
        4 => '兔', - H1 |* s/ s3 g. k
        5 => '龙', , d' V5 @- k! z% w  L  `
        6 => '蛇',
- E* C" Z7 U3 b5 y3 w        7 => '马',
% I* U- u# u# ?: T4 i4 K        8 => '羊', ! D* c, N1 S  n' [
        9 => '猴', ( v, S; i4 z; U! w% i9 a0 n1 C
        10 => '鸡',
! p7 ~8 B4 ^+ |* v* n6 \        11 => '狗', - X1 f" u& U3 }0 ]( g
        12 => '猪'
- L: E, X) K0 n) M- q! d7 i2 {4 x  L! p" A* P. p
     性别:0 => '男', 0 b) N9 f( i7 s
        1 => '女'
4 s, I4 J5 F7 D5 c. t# \8 `0 o! d
+ O9 t- r2 }& A% R(5).增加好友
2 \9 `+ T/ u: J( s7 K$ a9 h  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
; A0 J+ S9 A* L1 x$ I. O$ w5 q9 F$ l1 {. X$ q
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) 9 f+ S+ U5 h1 t4 U* R
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
2 v5 u1 t& W0 P     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
  S, t0 `- p! D3 ?     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 P1 W. D1 U* r& J" a3 t& c
     NULL(UIN、UN为字符) 9 X6 P" y% }5 w6 ]; A

4 \+ E9 G' c: w( B(5).发送验证 & c3 _) E6 c: P  H
  说明:1、如果你加对方为好友,你需要发送验证 7 j4 f! m- m9 ?4 z) F
     2、对方加你为好友,发送了验证,你要通过或者拒绝 - P2 A) e4 }2 }# U
     这2种情况需要发送验证消息
8 t* }+ Y8 c2 S6 u4 I% G; t; O3 ^' H( w6 g' u
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 7 T# U6 S! ^1 D; m5 G) Y- o& s
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
- a2 o2 p- I/ a+ O, a8 _1 P/ |9 @7 w0 ]" a8 _3 l
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
+ f) \; G# Y; i& h; C6 l7 ?, _0 t! W     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) & u/ [% K, ~' l3 r- C5 W! \; O7 K$ k
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 V2 g# g6 v$ I; ~
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) ! q6 U6 S! [  D2 W$ V% I1 f) _
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。 0 A& j1 b2 u7 ~' n+ d

5 O5 w6 h7 j7 E! p8 X6 |6 P- T(6).删除好友
" f+ Q& h' ~, D4 F# W8 C! f  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
" a! Q7 `6 t+ y7 n" x4 F+ l& i4 F; d% {" s; B
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
% R# V3 f5 j- p4 c: P     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
5 X  V# G1 R# g, k7 ?# ~     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
$ ^( e- ?4 b. x/ v  f% ]5 H     NULL(UIN、UN为字符)
& M. b# G% b! C, O5 C: k8 h2 }
! P4 F; O1 [/ a3 m$ y2 w(7).改变状态
* z! _6 i. e- y: ]  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 , Y0 [1 }% h6 F
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
/ V/ |. D5 f& O6 J
( s/ f; X4 z4 u  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
' N1 T' F/ I4 ^2 L4 G* ]: q8 _     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
# f: u- N0 F9 |7 P     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
, Y+ |  o% M: ]" Z     NULL(UIN为字符,ST非法) 0 }5 ?6 ^9 S. d/ X

5 f5 `! S- x8 `  o1 x$ N+ A# y  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
5 X- k5 o6 ~6 L5 C- J) W       同理,当你的好友改变状态,你也会收到一条系统信息。
, d% E: B9 V; \& q) `4 P8 J5 v
(9).获得消息
! n% O+ L5 O+ F# w, C4 B# }  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号   N" v6 S2 P: K9 \

) |1 l$ d# O" T( F8 k# H$ O0 `  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容)
7 `/ q# R, n' p+ v/ ]; _     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
# _- u) G9 K; l1 o     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 R7 ~. P: l" R) b     NULL(UIN为字符) . H9 I. Z# D' t; d# y  S
  说明:关于MT: 8 i! r. c7 P# {3 e5 l: p) V+ C* ?) W
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 9 U5 k# h* T7 \. r
     关于MG: 5 [  A0 N. s' n. q9 \: r' ~
       当MT=9时,MG为用户发送的消息内容
3 k( Y& |( m8 l' n: w! r* [       当MT=99时,
$ U8 h3 B$ m4 t1 t/ R         MG=10(QQ_STATUS_ONLINE)表示对方上线
- V( T7 G- k3 y5 ~) ]: R* o         MG=20(QQ_STATUS_OFFLINE)表示对方下线 , s: e$ _" P6 t3 }
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 1 u7 m& S+ H9 B1 O  V
       当MT=2时,MG为对方请求你验证的信息
# j9 V4 q. z9 @  K- X8 z1 t, ~, W0 y       当MT=3时,表示对方通过你的验证 - O; X& |$ f/ n
       当MT=4时,MG为对方拒绝你理由
3 O! }; E0 h/ ]: U# L; G; _! ?0 A7 R' V% M# d
(10).发送消息 & \4 U! f) f* H
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
$ _+ G8 c( _5 g' C
; y: |3 q$ }$ R" \- y  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
& Y7 k* s' J2 J1 [/ H% d4 V     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 5 x0 U7 {" c. a0 ~; {9 u4 z
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
9 U9 B& h& B' F1 f7 _+ O! `2 l1 [     NULL(UIN、UN为字符,MG含非UTF-8字符) ) U( E% q2 r; H! l/ C% X! t- ]
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: 9 q( Q" ]- t6 n6 ]8 B
       你俩互为陌生人,且对方没有和你说过话
* a3 h) D& p, A: C, G1 ^. q       你在他的陌生人列表里,并且他没有和你说过话(没有验证) 9 ?3 S& ^) n2 A
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s # Q8 x# O8 w6 m, r( o  W
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
9 r1 j6 A+ ]) z% i3 p2 t: V0 X" M
(11).登出 3 j2 y, ^* s# k2 |
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
  r6 w7 J1 i7 E1 x4 J% q0 J: P. |- e1 O! g" ^+ Z+ d+ I  o5 W
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
+ }, G2 E% w! m! T6 G% ?' P0 O     NULL(UIN为字符)   X9 ^5 S7 s1 k

9 j$ c+ \3 q% Y! A" o3 Q, Z( V5、总结
8 a, z+ T9 Q$ `& F
( x) O) o) g: R8 E9 m3 Q" H  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 + @8 P. Y5 V) U: e2 i5 w% [
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 1 o/ l1 H7 p$ ?; ^/ @, r+ u5 I
  本文撰写时间仓促,难免有误,希望各位不吝赐教' t; b# S) s% v$ O# i

% d) b# H; q& P/ P+ E  ]/ V* c" ^1 G; u& y8 Z
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 10:12 , Processed in 0.018205 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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