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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
) f" h; ~4 N! C. x. N2 ?+ {日期:2005.8.21凌晨
; ^: y( p  k/ w9 f4 W% H7 c9 a2 g联系:QQ:106814 Email:hackfan@vip.sina.com ; j5 S' G% J# s
4 I+ @1 H2 C: d( g# N
1、研究说明
9 ^& v0 r& }1 j$ i. K9 L+ I! w+ f" a# N* |) J8 {2 K
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 / M' p) O2 [/ a4 ~& \

6 S- Y) ?* r% o  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
9 |8 X& ]# K, {2 V5 M0 n
' O! |5 M& r8 ?' K# k2、接口说明:
" s, `) ~$ ?. s% r0 _  C% W: \
+ b1 b  K$ V6 C4 d0 s% m/ o  接口位置:tqq.tencent.com:8000
  p3 g, U' U) c( ?9 S# ^  通信协议:HTTP
. B4 w, u5 ~6 H  数据传输方法:POST % i! w; C) X$ u
  HTTP请求格式: 6 p5 L3 I# t3 e+ n* J
) |- |$ s6 |7 v/ Z
POST HTTP/1.1
) a' C' E4 O  L. _" a* Q/ J: Z) yHost: tqq.tencent.com:8000 ; k. U9 ~7 N- O1 V
Content-Type: text/plain; charset=UTF-8
* c# S: a* E! V5 g. fContent-length: 长度
. U1 R+ u6 o. k  @$ Z1 ]) C+ e, ~Connection: close ; S2 U/ M2 t9 d, z# t& ^+ q( H" ^
/ |" H9 C5 t5 Y& }% w
数据 $ N; h6 R- |- s' Q" c$ |' I

9 M: _0 Q$ F+ V/ O8 F  其中长度为 数据 的长度,数据的格式: : u0 O/ x/ H& J3 W' Y3 @
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... 0 e* Q! a( j# Y- \4 j: W
9 _9 _; r  m: Q' Q# N0 ~& 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还需要不同的参数,下面我就公布我的研究成果。 : Q. u" s7 [! G) G" z
5 ^; u) K( P* v: a" b- T
3、研究方法:
# u( j* o7 \. K  m/ U2 j: D' }. l2 o6 w. l( ^; c& p
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 . D8 r4 K* m+ U0 }  l4 r/ {
  下面我公布我探测的代码(PHP):
  1. <?
    " u8 H: o9 D7 A5 P9 ^; |
  2. $uin = "QQ号";
    . p6 P2 O* W$ s" t! d
  3. $pwd = md5("QQ密码");
    ) O4 @" D: ~7 }3 i( G% z1 U

  4. . t0 V  i" [+ ?8 `4 _. W3 C
  5. //登陆测试
    ' V' N- V5 v8 {5 H0 `2 L8 |
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; / e3 Y' @, g- N' N
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    ! W3 I5 D9 s1 }) X& |+ j0 \
  8. /******* 7 o0 a% Z  n8 Y9 o% o
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    . }# ?8 e/ w* i6 h) F
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; - G0 y- s' p, H% R% {
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 7 h/ ^  d0 U5 N2 M# q/ D
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    1 Y7 j6 j; h5 |3 I' @
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; & H: D9 \! X! z; p* \
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    $ g( D0 N  i2 E5 `* V) S7 _' q
  15. *******/
    ; O  U: {7 F, o$ u

  16. ( ^! l3 H$ R, a9 _7 n
  17. ' T( w  x2 J& u
  18. //得到好友列表 + v/ X" ~3 {+ C7 q& q0 O5 _
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    4 n7 _+ w* o. S: }0 i1 L- E* Y, w
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    1 t6 U; S- W) S: u
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; * a! i2 d+ n9 Y$ c
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; % {. [+ H* I. p8 J0 Z; m0 H' `
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 8 r. y# W5 ?0 a: f" M2 k$ R3 i
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    4 X! E7 X! _2 {" g2 K9 S$ _
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    " B0 c3 \# V; X& Y& E- L
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    $ q) i. A  y9 j5 g
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    " S6 J5 o0 D) i1 L: i" z
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    * [) `2 c- b' R; U; _0 f
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    9 y" H- J1 Y& a% T) A* e, x' W% ^
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ; p& U6 `9 Q+ U# B5 |
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    : @# n& q+ e" k/ l
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 4 J5 I( p& R. r. J2 @1 J- [4 U
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 4 m/ {% {% G6 f6 @0 C4 C) g
  34. . r  t* G9 K. a4 Z
  35. //得到在线列表 2 g0 W. M$ U6 O  g4 C! K
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    , e4 ]! B2 ?- C  K* C
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    . ?0 k. A# d4 k# n7 ?
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    " g/ x+ K6 @' ?( m+ R
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; ) e: N' Q8 h2 v7 _4 s
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    + m" G& H, p" ]% a5 J
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    - G" M2 m2 @# L- x) Y
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ! f, t# k) ?; A
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
      ?2 }+ N7 N+ c6 f
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 2 i% W6 F3 m; o3 q4 v
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 2 u' d7 m. S% C4 K* m8 S
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ) Q! ?# E  X7 b5 k, j
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 7 J7 D4 Z5 l: P) q' L" n
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); * _9 U/ k1 Y5 ~2 ], {5 a
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ; i" [# i% X1 N, n4 Y! i9 _
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    " P( x( C1 M1 Z+ w

  51. * s) P8 B+ n. H8 G- P; Y2 }
  52. //查看好友信息 8 E/ \6 P8 N4 ^2 q) V+ I- k/ Y; T
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; & X) q9 @& Q( R6 k. K# L, E
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; 5 c6 P: c8 ^6 O' y2 W" p3 f: H
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
      Z; V7 b2 n% z+ d3 G1 M  G
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    4 X- t" ~/ p1 o1 Q( Q% W+ Z1 W) _
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; ' C( i, ]3 l+ H1 {9 J: e
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; : P  Z. R) u( N4 z( F4 d9 J9 v
  59. " w; M' F2 r' d+ ?, a+ l1 z% q
  60. //增加好友 3 _9 V- v- r0 a3 ^9 F: v! J1 y
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    ' d  W! V* ^, ]3 m4 q" R8 M  W8 ^* \

  62. ) n+ r- ]+ N% q' V+ Y
  63. //发送验证
    # v) l3 o, Q1 o, W' I
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; 0 S# e/ t( Q* J3 T% D& X- R
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    : B5 ]" O, n9 M% V
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; $ |1 q7 O! K0 m
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    % k: l& [  M& `& e. w
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; & R5 n+ S7 J/ ]8 s% o- C
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    1 ?- x1 g2 ~' s  p" K

  70. 5 ~& G4 h2 V! g; b7 T
  71. //删除好友 ( T0 L; \# [; V! i/ ~
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    & I: W% q5 N4 W3 t4 w

  73. 7 u' Y$ z0 B2 e7 P! n( Q
  74. //改变状态
    3 w' A* w) M/ I
  75. for($i=0;$i<=60;$i=$i+5)
    * P$ {/ @3 i8 s7 g1 S( D
  76. {
    # B6 W- i9 O' P' P7 `/ R
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; ( ~1 Z  J% p) p2 Z4 W
  78. }
    3 K+ ]" a0 k; q5 n: ^# B' t1 g

  79. ! E  d9 Z/ j8 B& K- |" u& n
  80. //获得消息
    4 v' F5 F9 I6 }0 ?- j) Q. S$ w  O
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; * @$ k6 e1 A; d: x& w$ q8 \5 t" {

  82. 1 K. f% m; i! A# Y
  83. //发送消息 / ^* _" _4 _* k
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    ( h! V$ O7 K" E" h% [& v

  85. 9 Z' I" H- U& ~; X2 p9 ?
  86. //登出
    # g" M5 D( i, p- I' P* G1 {2 L
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; 8 ?' E$ X5 g  }. P+ k- u

  88. , X. A( Y5 q$ [6 s' B7 ]- j
  89. $file = fopen("p.txt","w");
    % p9 ~+ B. A5 B" c
  90. 3 P7 y- V0 M- m7 G0 U7 C3 U. O
  91. foreach($poststring as $k=>$v)
    / X; A! g- {3 a! H/ B" _
  92. {
    $ I/ N, r6 N2 l1 |' z
  93. ss_timing_start(); * k4 Y/ g: }3 Y% E6 m/ l9 G# P  k
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  & T3 {: _% T5 C$ G- B& }

  95. 0 ~9 ]5 P* [2 r2 d4 Q4 X0 o
  96. if(!$fp){  
    8 h7 g1 _. w2 W" T5 s
  97. //error tell us  + B2 P: F7 u9 ^7 O
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  7 K+ y/ L& U4 U
  99.    ! z" f, F7 g2 m( ]6 w5 H7 x. I: l
  100. }else{  3 s0 a$ x+ j6 L; {  c8 `! e
  101. 1 E7 y) r6 u  Z& ?8 b/ t
  102.   //send the server request  
    5 L" A  _+ _! k, i8 l
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    9 u  Y. V2 e# P$ H  x. g  H) s' F
  104. //  fputs($fp, "Host: $host\r\n");  & O/ y- a' a: h9 D
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  3 S# m$ X: ~; V3 J
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    " i) q: B$ r' _5 C8 h& `: @
  107.   fputs($fp, "Connection: close\r\n\r\n");  , r$ Q& k$ E2 }$ E: y
  108.   fputs($fp, $v . "\r\n\r\n");  # f6 A0 q' O, e% G- w# Z( |" l2 A
  109. & l6 \' {1 K- ~$ \* S2 ?
  110.   //loop through the response from the server  
    + W9 Z* n" [! B1 R4 v, r. E4 S
  111.   $res = ""; 0 o8 N; {! c" R1 Q$ {
  112.   while(!feof($fp)) {  
    + S3 o. H2 X- k: e) k
  113.   $res .= fgets($fp, 4096);  ( g0 c8 N" e0 c
  114.   }  6 K/ Q+ p& S, @2 x* o" m- _
  115.   //close fp - we are done with it  6 I1 F' `( D, e/ s
  116.   fclose($fp);  
    ! Q+ U5 Q% |3 J1 N, v/ g
  117. # i/ X! Y8 q  N8 L: j9 p2 {, Q
  118.   $content = $v.chr(13).chr(10).$res; $ W( N$ C4 N6 y: w0 \
  119. }  " k. y) Q" a$ L4 E* t* d5 F
  120. ss_timing_stop();  ' l* E% w) t4 j# O7 y
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    7 b% f' p7 X/ K% L
  122. fputs($file,$content); 1 f$ W- g8 ?7 K0 T% v
  123. }
    6 ^, d+ ?8 t- p  |6 M7 U: V) N1 X
  124. fclose($file); , a3 ~/ s9 p2 [( O! ]3 D
  125. ?> - I* K% l- D0 b2 k: V! T
  126. <? 9 T' V, o( l3 r- Y
  127. function ss_timing_start ($name = "default") {  $ \$ I  Z) n, b9 R5 g( M
  128. global $ss_timing_start_times;  
    " }  M4 g+ ^4 O. V3 O. Q
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  7 m4 D5 s* |9 J. T$ t: n
  130. }  ' R9 e& U# y3 Q3 Q: \
  131. function ss_timing_stop ($name = "default") {  
    1 G1 i  {! [1 Z; G: g# {
  132. global $ss_timing_stop_times;  5 N) [( X/ t5 E/ z2 H; F0 N
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
    5 _9 c/ n, m0 \" _" Q1 d3 ^
  134. }  
    ; a4 f+ e- u/ R# d
  135. function ss_timing_current ($name = "default") {  7 w; T' w7 i1 @: |
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    ' u0 x. F+ t9 c9 d
  137. if (!isset($ss_timing_start_times[$name])) {  
    . u7 A: q" y% `8 M& u
  138. return 0;  
    4 k  P/ c: Z* u
  139. }  
    8 B4 c2 `3 m, K9 X
  140. if (!isset($ss_timing_stop_times[$name])) {  6 @% K) E! b. h, O6 p3 m
  141. $stop_time = explode(' ', microtime());  
    ! B8 j6 o1 b' _- |
  142. }  # v9 ?) b  X# J/ Q) p
  143. else {  6 Q# Q" Q/ v0 ]4 S9 m9 |
  144. $stop_time = $ss_timing_stop_times[$name];  
    2 L  B2 }2 X. C% D7 I
  145. }  
    ; k# Q# Z4 I& ]: n; p
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];    P- X( q6 m( C! C+ y
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    $ [& w, B7 P# w& `
  148. return $current;  
    8 O9 N2 B# r, K; ]% w
  149. }  # S7 C4 T& t5 e" t3 {. O! }6 b! @
  150. ?>
复制代码
6 Q, u5 L3 a# Y! A4 J
4、研究成果:
) n5 S& ^/ T+ f* B$ c
% r& m3 n3 v/ f- V1 J(1).登陆   A8 l) Z: Z: D. N
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 ; }4 p, C* E2 u3 {3 Q
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ + V2 n4 S8 M7 f: |) H4 Q
; T; x9 n% m4 }: F# r4 x. n$ ~
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
. J" R4 F, m4 M$ s! @  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; $ S) i# \0 o3 B2 j/ Q
     M5这个参数的作用还不清楚,但最好为1。 / s& N  U; D, U8 A3 p, T  \
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 4 ~4 J/ T) j8 F
- g2 b' e2 S4 ?5 t& f. P1 n
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
# e. g1 k0 {# p6 p  d  Z; S     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)   Y* C3 h3 Q2 l  W* x% L) o/ }. ~
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
2 M/ D. M8 z% Q1 n" @8 Q, M( @     NULL(UIN为字符、PS为空、LC错误) / ?0 o0 y; z1 T& F# h$ P# b% U+ u
. X# V1 m( j$ d5 c: j2 x4 W2 k8 c
(2).得到好友列表
+ ]: q; i1 R) a0 J* Z( Z* v  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 + v% `' n! O  o
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
0 b' ]( N& L& U9 w  z. p3 k# ]) J: P0 V* O
  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
9 `& ~, X& w9 p' y     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
. a" r. G! m2 }$ g. x7 {5 {     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
! X5 U$ M9 _' ]# L/ K     NULL(UIN、TN、UN为字符)
# n' q! q& k: v
5 V4 q" r. s8 n5 P$ I( ]- I4 {9 U(3).得到在线好友列表 * H8 j" N# A8 j* M6 Z# L
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
, r5 T% h2 ], t0 V) r, J  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 9 w* X( r7 c* S2 H+ ]( t

  `3 v& w# }, |- W/ x( g  返回: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 x2 W. ]; ]( \* s4 j6 M
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
4 D: i  d/ d0 O' d# k+ q( Y" }     NULL(UIN、TN、UN为字符)   S) r" W8 b! y+ M+ D% y
  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; 6 e+ t, U0 k4 J  x2 q0 S( |) o. [( i
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
1 K' `  }. k+ m$ i+ n8 U- }0 @8 ~1 E3 O7 ?3 `$ A7 `
  特别说明:当参数TN=0或不存在时,服务器返回:
$ ]  R% X5 V* xVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 ( Z/ X" o% I: x! r
HTTP/1.1 200 OK
: N1 M, H, H6 }  d4 k  y3 \Server: tencent imserver/1.0.0 + ]: e- A$ _0 Q; T; B0 N  ~6 M( M
Content-Type: text/plain; charset=UTF-8
4 H. e+ _$ w4 J. W4 u% DContent-Length: 56 8 k7 r, c, H- }% L' p# j

, X9 ]) ?; a5 e2 qVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 9 k" `/ h; t/ h& d* R5 _$ i
HTTP/1.1 200 OK
* o" f" N, H% G7 A1 A# B' k* ~Server: tencent imserver/1.0.0
! [0 m( i. T0 M. v  GContent-Type: text/plain; charset=UTF-8 & c* h, l# [0 w  @/ o
Content-Length: 77
4 e# |4 {4 E. t. \- Y) w9 k
& m+ O3 l% D! t7 a$ K( ?* c# XVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= 9 j$ f! c5 |9 O- b% c
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
1 ?1 w: t8 ~7 R* n) f" }
& }* v$ z2 I! |) Z. x1 V7 E(4).查看好友信息 * O. K  l. j5 u* o
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
2 G4 C" k1 Z2 {  f$ |# G  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
$ _- y1 m% v' B
/ j* b) }& t0 W: T  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) & j- a- x* t- k8 B/ C' [
     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=学生 ' |! X" r6 ^# T! Q5 X
&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
& s$ K- t4 q% a2 c3 n好(普通查询)
( P$ l+ P; Y* E3 q* j. v     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
" u% f6 m9 i( B2 A/ X: L4 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  
* U% ~; M" s2 Yupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) 8 ~2 T! f& I& T0 @
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) - {3 Z# }( }0 L& x2 g
     NULL(UIN、LV、UN为字符)
4 `8 O! D, g/ f! W
* T0 w1 B! B* R  说明:AD为联系地址
) q' H8 ?; H' V1 a# F     AG为年龄
7 f% A; u2 ?. q- g/ g     BT为血型
# H- Y. w  [, J) n     CO为星座 . s. F; o3 C" e9 i& T) P& d
     CT为城市 , C" C* W* a5 R  O, b9 h6 }4 R
     CV为未知* 5 @  F+ A' C8 h$ m9 y' J3 V( \/ U
     CY为国家 , y3 D" W) Y4 G. i& F
     EM为Email
# b1 q3 l& B* q- g     FC为头像 $ k7 B/ i: N6 p$ W9 d' }' n0 F
     HP为网站 . g- O$ }" W: w7 X2 p' w
     ID为未知 4 D1 a' Z8 `- G' [$ W) y! `
     JB为职业
5 {; T, U0 d+ b* b# n     LV为查询代码(就是发送的LV)
, c  k. D8 q' s  |0 Z; {/ t. z     MO为移动电话
/ v2 T2 B+ x7 m* Y# `6 W1 r     MT为未知 * I5 r- w% A0 n: a
     MV为未知
' c' s% `' S) |2 J- {* V8 X     PC为邮编
7 x$ m! J* Y2 `: [     PH为联系电话 ' j& z+ ?+ n( M' R; I
     PR为简介
  P2 h. C  M( `9 C9 S) H! K     PV为省 ; C" V; Q) U' r- v6 ^* v+ g
     RN为真实姓名 ' f7 @* h0 h% ]& J: m& n2 u
     SC为毕业院校 . D3 z3 `9 ~9 c6 d3 @9 a
     SH为生肖   I) [, S8 p* ]6 ~/ ?
     SX为性别 % t" h) l% l3 U; M' k/ \
     UN为QQ号
: E% |$ H7 v3 K& u* I( m- y     NK为昵称 + @7 m7 T9 T' {# K

1 X9 C( L' \+ _8 \4 B7 g     血型:0 => '', % W4 X5 A. y7 _, K# I5 A
        1 => 'A型', 6 l+ E: k7 f5 C: `
        2 => 'B型', ( ]( h: I( t$ g  {- k% H8 _2 \
        3 => 'O型',
* t# ]5 n8 z4 w        4 => 'AB型',
; {. C6 |/ }$ D7 d7 }" }        5 => '其他'
# D: N1 L0 L8 N! {4 v; a9 ~5 D
: l0 j0 I  z: ]  n+ c3 z
     星座:0 => '',
. K2 L0 u4 w* L5 ]' N4 y, N        1 => '水瓶座',
1 X8 A+ w* z% _2 C: y" ~        2 => '双鱼座', 6 ^; k8 ?7 J7 z% i5 }) O( F1 M! s
        3 => '牡羊座',
5 v6 ]  p" v4 K) d$ g        4 => '金牛座',
8 J. v. n) k) E        5 => '双子座',
7 o+ ]- h1 f' b+ _7 V1 F3 A% A        6 => '巨蟹座', 1 m( f6 b( {) g- o( k' Z7 J
        7 => '狮子座', 0 Y8 @3 q! y4 {! c( A7 d: P3 C
        8 => '座',
" i# k& N& F. ]8 B. J  g        9 => '天秤座', 5 |) @. V, ^0 D' `" E6 I) g
        10 => '天蝎座', ) X1 I3 u; M4 p$ m' h
        11 => '射手座', , _/ J: ]' S7 ?- }) J
        12 => '摩羯座' " A! K* h) }2 X* U0 R- t3 l, c

& a; {- ?3 r" |! S3 [+ \     生肖:0 => '',
* @: k3 Y1 B* k- i( K, u        1 => '鼠',
$ ^, ?) u* t: v8 L        2 => '牛', % |( r  f( O8 ~7 Q# I% s5 v+ h
        3 => '虎',
( j% l' T& W  J        4 => '兔', ) B. C) J% c8 f* ^
        5 => '龙',
- P! W3 z: [; _! Q        6 => '蛇', 0 M1 k6 n" f! q+ J- C5 [( @
        7 => '马', ; k3 ]% K7 a* n6 x+ d
        8 => '羊',
, h+ \1 ]) p) u6 A* p        9 => '猴',
5 ~: q% l% v1 _        10 => '鸡', ; P& s8 @7 ]9 M! J# e2 f% n2 B
        11 => '狗',
0 |1 j2 N2 G1 g* L( @' S( m7 D9 g        12 => '猪' ! C- m; t/ r, T
% s' r; K% f' W9 y
     性别:0 => '男', $ T; Z% I- L$ q# r6 @4 t& C
        1 => '女' . H( y9 n  C  y" Z: b+ m
, S: T8 v. b4 `0 T" f' N
(5).增加好友
, n- q# R0 {7 p7 W- B  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
, c1 `5 z; U# e- d2 a5 W( X9 o$ N$ o6 J5 [  j
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) & Q$ a! j+ S7 j& v
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
: Q7 L' J+ u7 a     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
' i% {! u1 o0 z, I  c3 o0 @     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 T- X9 C4 v: ~7 a. w% `3 O' _# K
     NULL(UIN、UN为字符) 2 I* c9 ~5 a! ~- {( x' I) B: v

0 u+ e4 ~; l1 p6 B; w- x(5).发送验证 0 L. w" {* ~0 k7 B. Z, @  J% c! ^
  说明:1、如果你加对方为好友,你需要发送验证
( o/ V2 r( q: F7 L( t- @     2、对方加你为好友,发送了验证,你要通过或者拒绝 . q& ?) T  t: ], v4 k; F" {
     这2种情况需要发送验证消息 : W& Z( @) c- J
  r2 u  W) I) q
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 $ O* `$ J# Q& ^5 g6 C0 d% }! w* k
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
" F; \; j0 k$ l( Q! i3 {! B+ Y
5 G3 s8 J4 x. L0 e5 k) X  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
7 F: b+ f# D# f  o/ u7 n     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) 9 K5 [/ D# g$ h4 B3 G
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) % k; D8 X. f4 w  x- i: m; F! d
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) ( U6 [6 a5 |2 g! s
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
; I" O) o" O! x0 E) e7 d4 e
/ C9 [, l0 Y. q) y, B4 h(6).删除好友
5 a, X" O6 A3 M: X8 g0 M  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 + i2 P8 x; S3 C5 g. l
' l+ i- U5 g. P( Z' p: c
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
( N1 L- ~4 g# U) P5 M5 Q     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
, J2 [7 K$ e; l     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
, j' r7 S' q& F- L" }     NULL(UIN、UN为字符) ' S% G5 k, E& Y! Z1 ^' N$ i$ C

5 I5 _4 ?% `; e  g3 ]. m8 T$ X( _(7).改变状态
$ h5 M! H* ]& I  R7 l  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
/ u0 ?- a1 `, }! I/ D. ~  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 $ h( g% v6 G7 W# y7 n- H7 @
6 ]6 g: V% Q5 @0 `, U3 k- m
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)   K; I! W  z+ i+ r$ T8 w1 u, k5 ]; C
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) * Y. u  }1 K' U$ c% w# q) A
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ; O; {1 Z7 D+ p* W
     NULL(UIN为字符,ST非法) 7 A2 I0 T- s$ [1 f! {
& l7 C* t( K. b- S2 \/ E- H
  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
  v1 r/ ~: R' c6 T0 Y( O' W5 t       同理,当你的好友改变状态,你也会收到一条系统信息。 0 J' f: k" D* o) y

/ P! W9 @3 O: j2 ^" E" S1 ~(9).获得消息
) d" {5 ?; G; V8 F- V' J4 Q  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
; ^' M9 I8 z4 \! ~3 Y$ F! b
. Q# K- e* E( v6 D  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) , p1 g; y! x: S( z4 r; i
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) ' I  r5 u3 o2 V' }: q
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) $ I" {' e/ j" ?' N9 S* m
     NULL(UIN为字符) 0 J" j4 ^6 A7 K- n" c
  说明:关于MT:   i8 l# m& a2 E
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 3 N: k- v+ P8 J# |
     关于MG:
- P2 }- J2 }, f/ [& G- y, g       当MT=9时,MG为用户发送的消息内容 5 P2 O3 G9 K3 E0 M/ s; V7 A& f! j  I
       当MT=99时,
9 R7 J$ |1 ]0 k3 O         MG=10(QQ_STATUS_ONLINE)表示对方上线 $ t0 g, Y2 ]' `- |9 B( g
         MG=20(QQ_STATUS_OFFLINE)表示对方下线
& \& Q" S7 m) ^% X" I& U         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 ; R# H0 A$ m# r, F0 c8 p* t+ v6 R
       当MT=2时,MG为对方请求你验证的信息
: r6 P; c  H( m       当MT=3时,表示对方通过你的验证 9 D% x- k- i6 w& u
       当MT=4时,MG为对方拒绝你理由
9 f$ B- |+ d( E0 J7 Q0 |. d9 O, M! \5 V- ^: ^" V
(10).发送消息 ) A3 [! f9 q+ |, }
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
; d" x2 L- F* J
8 a: ^; T3 P1 F* Z) {  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
. g$ }  i9 w. I9 {0 J     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
5 @  I7 h0 l% v3 j2 X     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
  S! x! \: ?' Q7 w( k3 h" ^     NULL(UIN、UN为字符,MG含非UTF-8字符) 0 K" B7 \, |6 G2 X$ X! w
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: # i# ^  {2 H( M6 w
       你俩互为陌生人,且对方没有和你说过话 0 w; W6 j" m9 J5 ^$ e
       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
1 l1 G7 M* g* ?( Y7 f6 p- V  D6 x     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s 9 d$ V1 A$ \9 d* r
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
+ }$ t3 ^( z) h2 ~% R  z4 K+ u$ Q& u* ^* \3 ~# X0 l  Y
(11).登出
# A0 d' o- G% A; W; q: m  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号 7 Z; p- K2 A4 @/ x9 g

9 S5 j* e) A0 O7 L  U! i: T6 I  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) + y* O, Q+ B8 H2 H5 v, e/ h* C: \/ A
     NULL(UIN为字符) # a/ B& m- y+ p" [, B# Z

: V; L& g" K) o# D* W5、总结
8 G# H9 y3 E2 S; J
! c& |% |$ x- W* M! u  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 % Z0 V; ~0 q9 }9 [* T& I  `
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
0 @% U4 A( p  T3 ]  本文撰写时间仓促,难免有误,希望各位不吝赐教
; ]6 d# }* X0 A" l. f- z
" Q, w2 ]/ O( ^" ~
$ t1 M5 J7 C8 x5 k2 o$ OTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-20 07:48 , Processed in 0.037015 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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