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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
+ y9 V% `- D) C4 j0 M& h3 f' p日期:2005.8.21凌晨
( o; @8 A2 c' K; z% j5 ?% K联系:QQ:106814 Email:hackfan@vip.sina.com
) d$ \7 u# S! z0 C  d9 l/ J" s# |3 z5 ~- |* M" h" p. X" f% L
1、研究说明
" O: R5 _' \4 l* E& ^( o9 J5 U& n+ Z' D2 s- ~
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
1 n* Q! k: p  J3 `: r* X6 g; o
% t/ d+ B8 t* }+ D! E$ N8 C  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
4 S# ]* u$ v* h) L* M# x
/ N% W7 d; t& T. J1 t' C6 y, d. f* C2、接口说明:
3 w. Y4 \: h- z. {" w; |9 N$ C; H  ^! z8 M. e' N& D; b
  接口位置:tqq.tencent.com:8000
4 V* u; `: Q0 |  通信协议:HTTP
3 T0 E) M3 K8 _' }. y( L8 W  数据传输方法:POST 3 P6 i5 H$ Y- e) a4 E
  HTTP请求格式:
3 r% o8 i; u  w: Q. e; r! Z0 T
7 Y3 j( N4 M1 P7 |POST HTTP/1.1 % ]5 [6 E6 z4 O* \! A$ G" F
Host: tqq.tencent.com:8000
- C9 }% Y: `1 {6 \) }4 O/ KContent-Type: text/plain; charset=UTF-8 , P# l& f. P. c% b  o
Content-length: 长度 ( j+ P6 w' R7 J3 b/ A* p2 X
Connection: close
( y- {, B3 c- {, D/ T0 T7 ?: e' x2 u9 h
) X# `! x& z( U9 _- P数据 . D, K9 ~* s8 e& u4 k7 s7 {

1 c! Q4 `, C4 F  其中长度为 数据 的长度,数据的格式: ! I- q" K; u5 F3 g  I
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... ( k2 g# L" c2 X! k; v0 ^# r

+ X; h7 W) ?8 |9 e5 c6 f5 p  以上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还需要不同的参数,下面我就公布我的研究成果。 ( g9 {1 v( y; U6 F2 ^

0 j9 ]0 e4 @' L- t3、研究方法:
. W! D% |3 o" u1 l
4 w9 e: F2 X. W  U4 A8 O2 r  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
8 K, H4 E" x* l% ]  下面我公布我探测的代码(PHP):
  1. <?
    ! ~9 ]. ?0 W1 {, J, L4 Y
  2. $uin = "QQ号"; & Z" d, ~0 ~, R1 `" J
  3. $pwd = md5("QQ密码");
    ! R# Z! S+ u  x/ ^/ ]- f# x' V
  4. . ^& P6 D) @8 b1 F
  5. //登陆测试
    4 _( ?: d+ N- e0 G2 o
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    4 }/ X; _5 k! P
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    + T5 Z- B2 H9 U& K, J& f2 I
  8. /******* , \7 a$ h( b( y" W1 v
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; / G8 y& n' \/ Q9 [( W
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; # S4 K2 \* ^" x' J- T" x: _2 ]1 V7 x3 t
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 9 e) T$ ^+ Q' W* \0 P9 q
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; ; C- g1 E  i) f; R' W
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    ; e5 j6 P, H* H2 ?- [: i% @/ f, U
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    ( g! q: [, ]" k  X5 Z
  15. *******/ " B3 i( q& _4 u5 X
  16. 3 G3 U7 t; f/ o  W/ n% s( `

  17. 0 N  K# ?& W8 {0 C0 g: X
  18. //得到好友列表 , K, h3 G0 g0 X/ V# I: g
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; / Y) T% |+ A+ A; }4 A
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    * y6 n3 `# Y+ g2 U, M, @
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    $ h9 D  Q) n& H' S
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; , E# C' S: v+ x7 l$ m: Z! [
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); $ Z6 S: n$ a/ l
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; 8 r% r1 y! j5 g2 Z
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 1 s+ D1 L+ b* z8 u) H
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 4 B& `, q* G" t6 n  b) L/ f
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    . J7 Y$ i8 @! D  D7 N
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ; E3 F  D$ [; o3 B# c; w$ O# c' h
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";   D0 f/ B, P6 n5 H5 }0 c
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); / o* D+ Y& U3 I9 P" W- K* T
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); # i5 u( s- C( f/ H2 g3 x. H
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    0 B4 g6 e  I$ O- U# E. J
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 3 q+ H# A* ~  ^  \' t. J
  34. & W" X! B2 c" h. ^3 h3 i  \$ m1 ]! w
  35. //得到在线列表 . t0 {; D: Y2 i- ^! K" `
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; 8 \* `7 m- n7 g% G
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 0 B" Z1 |1 N$ m$ |# |% n2 A
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 9 q: x. k, Z$ Z. d7 Z
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; : T# }1 C% `* C- M
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    7 s+ h* r! V. Q4 t, O
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; + X( z( O( G3 L
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 0 h) O; m  W& I( u! t" J6 [& n
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ; d6 ?4 R9 w# x/ I* D
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    $ p) V- d" L$ A
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 0 i1 `6 u. v3 y1 ]4 V' O
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; # X4 |7 Q1 f* Q9 v3 n
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ; K$ H! b* A% \; U7 ~) B: V
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ! I& D+ _( N4 [3 r( l
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    8 c6 Y% W: \2 \# U& H! {7 N
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    ! m, h1 i  C" G
  51. 3 l( l: C. i- g; Z# q
  52. //查看好友信息
    . Y4 h  X. y/ n; G& J* d5 V& i: I/ \
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    2 U* ]+ q- a8 g+ D1 }3 F( a
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; ; ]4 Y: n% M! @' j2 {- {
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    / g' A5 N8 w3 o, v
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; , S3 |! x. j: i8 z9 v
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    / D% d. n; n' I8 ?3 w
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; * D) ]& h- M6 c$ i

  59. 3 d$ Z: o* Y% s) L1 B" U6 e) S/ V
  60. //增加好友
    : L, g& s" [* ^9 B- G$ y5 Q7 c" k. C, g( g( |
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    + C3 B9 V/ l3 p/ X

  62. % ^) [9 p- ?' N5 S2 ?3 A
  63. //发送验证 5 ^3 Y8 s- x% Y% F
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; / }/ m# P# y( \
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    ; i% Y& `) r/ s" d
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    , }+ L. Q  r2 I7 ^" }9 s9 s  B; ]
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    " o6 E( G- ~' Z+ t' X& C' L% u
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    - V! Q; I# D+ u% b* [
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; # @/ w, a) d* w6 j7 ^& s5 Q
  70. ; ]$ C8 `0 J  e7 @
  71. //删除好友 2 \. _- ]- s6 I  \1 g% `: s/ [
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    2 h- m/ h) O2 j5 k+ \

  73. + g, m1 O8 U0 v0 t9 D. A$ N* N# n
  74. //改变状态
    ! g% S  n, P( R6 C; {* `1 }% u4 H
  75. for($i=0;$i<=60;$i=$i+5)
    . X( Z7 g  V2 x7 b1 F1 ]
  76. {
    " J9 Z7 e4 D8 |+ J" Z
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    8 L$ \4 c1 J; t( r; C% ]1 i/ b5 G3 `
  78. }
    ; z6 X2 Z6 S* W

  79. $ R; U) k" m1 z! Q3 H! \8 {+ v1 ^
  80. //获得消息
    $ [" O/ p$ @. @  I# A- \4 a3 W
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    6 ~3 j3 f5 `6 a, i% q# L, A4 Q' O
  82. $ z: t/ F# f) {2 g3 J
  83. //发送消息
    & H, m8 V# {/ z$ Y5 W, P
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    - I$ x+ h4 O: r" T
  85. ) t' ?! l* v+ W1 C
  86. //登出 ! S# r, |  D" y& h6 h
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; - J5 m0 T, U3 i

  88. * E6 n+ C3 C# b6 j, m- Y
  89. $file = fopen("p.txt","w");   S" M9 `1 F2 y  x  x
  90. ! T4 S. }; i& v  X# {
  91. foreach($poststring as $k=>$v)
    , E& q2 U, G) ~% z0 r9 Q
  92. {
    ' H- B9 \" x) E* X7 ?8 G
  93. ss_timing_start(); $ ~5 n, R0 H6 D  b; ^
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  * ?1 d  C9 B, [& U4 [8 O- _

  95. % _4 L* y( c% ^! D0 u3 ^$ S( [
  96. if(!$fp){  5 N! U- K: o* d, M
  97. //error tell us  
    0 K- F4 K/ O. ?# [- }
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  , T" g1 T. a1 Z/ h3 N1 h: y' B
  99.    ( |& m& ]- E- t9 y* G, m: L9 p
  100. }else{  
    . S8 u/ s5 s2 A8 h: e
  101. 5 d& q5 U: O& I  J0 m0 w. a
  102.   //send the server request  
    9 W3 Q; Q- e: ]& I. h. r' ~4 F
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    . P+ e9 \  s* A! o" V3 ~. T
  104. //  fputs($fp, "Host: $host\r\n");  & b/ m8 H% j: Z' |  n) R3 U' D
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  ( M1 T6 s" R4 w. L1 z: u3 G
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    * ^0 ~" |7 m& x; \
  107.   fputs($fp, "Connection: close\r\n\r\n");  9 N4 b; L- x2 K/ [6 s% A4 ~
  108.   fputs($fp, $v . "\r\n\r\n");  8 V5 f! `, p1 }( }  }# V

  109. $ s0 ?4 F. E* z# D1 y" K' T
  110.   //loop through the response from the server  % H- r$ P& X2 N- @& Y" h
  111.   $res = ""; " Z5 s9 [$ |! i/ T0 B
  112.   while(!feof($fp)) {  5 F5 i" N% W" j4 C! H8 ]
  113.   $res .= fgets($fp, 4096);  
    $ Y" w- h/ @$ V
  114.   }  
    7 X$ @; `. z4 z9 P  k5 z. u* ^/ w* e
  115.   //close fp - we are done with it  
    1 M4 W4 x* R9 J
  116.   fclose($fp);  
    & C1 W, S! E  b( {2 J# q

  117. ' X( F6 J+ v5 u' J, Y5 I4 f
  118.   $content = $v.chr(13).chr(10).$res;
    ' T. t! C# Q, @8 V9 d8 @/ F
  119. }  2 `0 J3 U% K% b- ^  z' O
  120. ss_timing_stop();  / P" D  ]2 n* w1 {1 E# n0 g
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); : {7 A1 ]& Q/ z! [9 W* ^
  122. fputs($file,$content); : W4 q- d& u1 L+ d
  123. }
    $ p3 I9 b. Z2 G" t3 N
  124. fclose($file); 5 X( P: ?4 g# g: J3 i6 `4 S
  125. ?>
      o% F( s4 l: C. p& }
  126. <? - J; R+ Z- d& x6 c; S7 E- [
  127. function ss_timing_start ($name = "default") {  
    / s2 u+ g3 D% s! Q  f
  128. global $ss_timing_start_times;  
    7 K/ Z$ Z& j; d7 Q
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    * m, ^  F* G9 n  d7 y2 ^
  130. }  / V  k7 g4 Y( R4 e( m1 z
  131. function ss_timing_stop ($name = "default") {  
    0 C8 |+ H! v8 _- Y; F
  132. global $ss_timing_stop_times;    e/ |5 t. t- S5 D
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  ; g5 V5 |: g" M1 ^# c
  134. }  ; C& |# X+ x/ \! S3 _% r
  135. function ss_timing_current ($name = "default") {  0 n0 h! x6 x7 ?/ p- n
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    0 f4 C" V9 }* I! i
  137. if (!isset($ss_timing_start_times[$name])) {  
    ( R5 R' |: l+ y+ {8 k; j; M# a
  138. return 0;  
    4 H6 e  ]+ |" u, m) x
  139. }  7 `, k8 ?' o- y' ~* l8 |+ L
  140. if (!isset($ss_timing_stop_times[$name])) {  
    7 t% O4 x& K( m+ O) H5 u
  141. $stop_time = explode(' ', microtime());  
    # M# a& [7 B& ^, z" |
  142. }  
    1 N3 z* m3 k! g3 i
  143. else {  
    7 ~" H* C! K$ l% @) o; r
  144. $stop_time = $ss_timing_stop_times[$name];  ( R; [* E4 \# E
  145. }  
      t  I& D1 d( n% ^& `% _" `% i
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  3 ~' `* }5 t6 F1 \' M: [' ?
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    , ^6 S' P2 E1 P+ T% D
  148. return $current;  / n% P; G7 F8 C" M
  149. }  ( z& _" B& v" G! |- ]
  150. ?>
复制代码

( e" R" o! I* [5 I4、研究成果:
2 I/ Q8 E* p6 a6 o# m% m* ?3 [4 `4 B% d/ S0 d5 U* |$ |
(1).登陆
! z, w7 d1 b! j9 {  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
" l+ \) Q* t, a$ P0 C  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ 5 T! @$ C' }2 X" ]! k  c: F2 E3 B
& `  \- O$ S9 O  r8 k) L! H
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 2 P# p2 p3 p0 p- p" y
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; 7 V. U  ]* c2 }2 I" z6 k
     M5这个参数的作用还不清楚,但最好为1。
1 x9 `7 e* I/ g     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
! a0 \4 O6 r  i9 ~# Q: v% C! V; U$ M
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) ( @- x1 J# z4 R4 I8 s. A0 `! A. ]
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
) s# D3 y: b7 `     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
" \4 t4 k6 w4 d. q- C     NULL(UIN为字符、PS为空、LC错误)
( ?. l1 E/ y9 Q0 r! w9 q. m8 X, C$ M8 \) V
(2).得到好友列表
( Z. z, s0 \( T  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
$ _) S3 X- e. x" Z  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
' y2 l+ p1 G" Q' x" c
+ g, n; A, U' t8 Q: M$ x  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
% e* H& D. ]* X$ |% J+ \     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
# L: l* m+ n' p' s) K, J- B     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) , s: u) N: F0 J4 P$ n
     NULL(UIN、TN、UN为字符) 4 p- P* D5 s: a
6 Z* Z7 M" w- i
(3).得到在线好友列表 9 \2 X* |4 X5 _
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 , r  B* B6 \3 D" U: Q
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 3 G6 ]7 N; n9 L
" ?# @) I8 C) E" \4 p( M* i
  返回: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的值用','分割,分别表示头像、状态、号码、昵称) . x) A7 \5 X) [' P% }; P! U
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ( R$ C0 o1 @/ k% H5 ^* |) |5 y
     NULL(UIN、TN、UN为字符)
% Q% n% e7 }4 V  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
5 }$ W& d* P- ~& I     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; 7 T/ z9 X& z; j: \$ c
1 i5 d1 i6 b) e; o, j# {
  特别说明:当参数TN=0或不存在时,服务器返回:   {  T2 H8 C/ ~2 f' }6 T& `
VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 8 c% L$ L# y7 d" C! }) z% P
HTTP/1.1 200 OK 0 {9 j' [7 Y: @4 D% V8 n
Server: tencent imserver/1.0.0 & i! [. E% h9 V! E# a
Content-Type: text/plain; charset=UTF-8
/ b/ E  n+ C( JContent-Length: 56 ) `) o/ g* a, v4 V- r* ^, F
, P- f6 Y/ I3 w
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 $ h6 c9 C* x! J2 \
HTTP/1.1 200 OK ' t* u& h# n) r$ ~+ b
Server: tencent imserver/1.0.0
: \  Z& u; e+ X* t. WContent-Type: text/plain; charset=UTF-8
- y' ^% g6 |6 R% b! O* CContent-Length: 77 ; }& ~: R$ k9 T! f( d0 k

  X% @/ f- [( G+ M$ k# H2 FVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
& T9 P. k. [. E( M# n; q0 l) M  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。 9 G9 `" v" x$ t  {7 ~6 |( x9 c* k  ^

+ H  r7 {- F! L$ J(4).查看好友信息 $ R+ O" J- H; d" R( e, q+ g9 {% ~
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码   [/ Q5 N# M# F; D  ~' L
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
$ p% z6 t. b5 I( J9 i$ ^( r: C3 r2 F2 D3 C
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) - p+ N3 n. p$ M* h( y5 J- k  Z
     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=学生
) [- M% C* r1 {- E# ?&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  ' e$ b7 w. X4 [% g; S( C8 F
好(普通查询)
* ~8 y) c) B  ^* Q     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
) m" R# v; v! |( W% b&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+ G7 |0 H' {& @; y) j
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
5 j4 n2 X7 W  Q% ]/ |6 P; B/ ~8 Z     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
5 I( G) O9 l. p+ V2 L6 Z5 ?     NULL(UIN、LV、UN为字符)
( k% h* m, j$ o' E, `/ H
# m# _( X0 M6 u' P% c, P5 m  说明:AD为联系地址 4 t8 F+ x+ }: j' t8 ~5 x
     AG为年龄
- s' K, U- Z3 ]. E$ y0 \     BT为血型 5 k' {7 _2 u. D2 ~( Q/ `) Y5 s
     CO为星座
$ C; h  ?  b- G% z, K/ v- F; D     CT为城市 - O0 B: \+ r% K; V4 m
     CV为未知* + ^0 }! B* V; F; Y4 Z
     CY为国家
0 c2 |, F( H3 l1 k. h  {; |; a     EM为Email : S: F! X4 ~2 [' S& ^: N
     FC为头像
# c7 C  ~! j7 W& p( ~6 G     HP为网站
5 ]  X- P) W6 C7 d- m6 c0 F0 x     ID为未知
- ^; H% y6 }- m- R  ~     JB为职业
% s5 J( \8 |  b' T+ b3 S     LV为查询代码(就是发送的LV)
% O; t6 I2 V3 A  I, d) q& _     MO为移动电话
. }# O; J7 ?; s2 H4 a, i# w' O/ w     MT为未知
9 P& h, Z3 m/ ]- r$ @- N     MV为未知 + X9 W( _5 j6 W7 O7 a6 y
     PC为邮编 $ C8 T9 f( u9 n: j1 w  R
     PH为联系电话
& x$ r+ n( W" T+ f/ c     PR为简介
& n% g- N* x. q" R- V1 r9 ]     PV为省 3 A- Y, l/ ~5 w/ M
     RN为真实姓名
( t# _$ s6 F8 E- _: V/ l! H$ u2 T+ i     SC为毕业院校
4 r$ X$ ?# n" s# K0 h     SH为生肖 " f# r: j% q4 P4 d
     SX为性别 5 I& H" c5 Q& J% \+ Y/ L0 U' r! @
     UN为QQ号 + H  c4 S$ t, s  N
     NK为昵称
: ]; f* A) ]9 U, x* r7 ~* O& I8 y, v4 X. K& A0 S  ~
     血型:0 => '',
! ]# F# u# W- W( u4 s        1 => 'A型',
* z2 D2 ^' J1 z$ A5 b: G/ t        2 => 'B型',
# ^4 d2 o- x. N$ ]3 u% f, N        3 => 'O型',
" d6 y: s! {9 p) z) U8 }5 Y& v        4 => 'AB型',   J3 e! o4 N, O, U" G4 {
        5 => '其他' 5 R& O, Y9 P& j" e5 |
" H  S' B+ {0 H/ D3 J

1 Q7 ?2 H5 P/ o; D9 x0 V2 D& p     星座:0 => '',
2 k: \/ o/ r  z1 U        1 => '水瓶座',
7 ^# b  p3 v# n. J* f        2 => '双鱼座',
! P9 u! V  s2 i7 m1 L- }        3 => '牡羊座',
. P, P" o8 ^, z2 h4 P        4 => '金牛座',
1 f6 ?* Q8 N1 K$ H2 b2 v6 g& j6 r$ s        5 => '双子座', - Z2 b7 H6 w7 l9 u
        6 => '巨蟹座', * y$ |  ?0 U! f* V! ]/ I% L" _* w
        7 => '狮子座',
0 ]7 q7 E! R' _3 {, i        8 => '座', 7 F( H8 e) `! Z+ _1 D. _& d
        9 => '天秤座',
1 \8 n7 t$ }8 n8 J        10 => '天蝎座',   n; P" {' n4 p
        11 => '射手座', 8 p4 w! u7 ]. D5 t4 t# A
        12 => '摩羯座'
' |7 {" }5 T3 @/ w
1 D5 m3 K& U2 Z0 j     生肖:0 => '', ! E0 T( ^" Y) E
        1 => '鼠',
0 a: Q7 R3 \4 {2 Y, F( O- s        2 => '牛',
2 F+ x6 O7 y& w0 g4 Q1 d8 O        3 => '虎',
; f& V5 j4 p+ e1 `3 j1 h        4 => '兔',
5 F4 |- x7 O- O7 @; p        5 => '龙', ) D# k" s( v9 N% ?2 c& `: P- g
        6 => '蛇', 4 v- W5 |$ N/ |  ~* O) P4 f# Q  X
        7 => '马',
9 V4 }( x! d% b        8 => '羊', & h& T( b$ t$ s1 `# i8 w
        9 => '猴', # T9 a- k2 T; E& P9 U
        10 => '鸡', , [, I5 a- R, l
        11 => '狗', 6 a* ?+ k' J0 I* W3 ?/ X
        12 => '猪'
" A& y1 |+ |; ]: {/ r
/ G% [: @! `  y2 p% O     性别:0 => '男',
4 O. Z( ^4 a/ I- Y( f, O$ s0 O3 }        1 => '女'
& k3 ?$ m5 `4 H( w+ c
# X0 ~* q  G! R# D% [(5).增加好友
; G" ?. N% T6 \  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 - T& V  ?" O" K7 X5 w( M
0 d0 A! a$ t- i( m& D. u9 z
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
' f. d7 Q( w9 x- W1 w     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
, _5 P. K" U8 o7 B; `     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) + m) A$ z6 W, B
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ) \: o4 q1 ~9 b; L5 k( B0 w
     NULL(UIN、UN为字符) & j: G5 N, v7 B' T8 _

( u( J. n9 V& J* l7 x0 y1 u(5).发送验证 . q" U4 j% Q- W9 {6 J
  说明:1、如果你加对方为好友,你需要发送验证
$ d' ]" Z# L- _     2、对方加你为好友,发送了验证,你要通过或者拒绝
8 q: Y" l- t, x     这2种情况需要发送验证消息 + F8 q' i1 b+ F' {
5 {! O. ^$ f4 k. d
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 % m. }8 |+ |$ ]5 T$ }4 c9 c* y
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 ( Q/ f7 w4 u+ p# m% s7 ^( x5 R
2 A8 [7 s# ^0 v2 l( K
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
3 e/ y% O. ^& ?/ u     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) $ e3 o' T+ e/ m3 R+ n
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
  s0 U6 G) @8 q0 S' ]' X     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) 8 z1 T$ D6 _4 _) ?  m
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。 8 @4 Y3 T, V- ^& ]

) q, l! j; ^2 V: `) z(6).删除好友
6 p1 K' l+ u+ m7 o% c8 Q  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 5 G/ a3 i: s- m3 V( s& F, S3 u; w! C

' ^( F: f# g- J4 X) x  O  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
6 N" w- W, j5 ]% L     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
; y: P% ?& L" Q' H. ^4 v     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& @* \( N" e8 M2 K( h0 G2 j0 e     NULL(UIN、UN为字符)
+ p6 n' u: S$ Z( g
% _' q. W! {3 g" `9 b$ C( O(7).改变状态
! L4 t+ l/ R% F6 N  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 ! I0 b/ j0 G+ X1 s- Z5 t
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
2 a, A! P+ }9 f) I( ^; O; Z( U, k7 n5 E  S
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) + L# f% D9 @. n' j8 Q8 B! D
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) 9 u- j( |" h* T+ g5 y
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
. a/ h/ _. b& ~/ G# {     NULL(UIN为字符,ST非法) 8 \4 d) ?( r! h4 ^0 U
5 v$ _+ b/ N3 b. T1 C
  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 5 Y2 u  g/ X+ |
       同理,当你的好友改变状态,你也会收到一条系统信息。
0 m* X" I- h6 g" R  ^( @4 n& e
: E6 i) D4 |. F! r4 {5 W) i(9).获得消息
( q3 Y1 c1 G; W, E  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
) S8 l- R* k/ Q- n1 v: f- g+ `0 J) @8 V6 N) 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的值用","分割,分别表示消息类型、发送人号码、消息内容) ; {3 ?7 ~, K7 l9 `0 s' I' d
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) ' F7 `* P5 P: y' X7 s
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 8 Y7 \- f5 y2 M- I
     NULL(UIN为字符)
7 v+ m* H2 |+ p) u% }- b  说明:关于MT:
# i2 i! O6 q+ Z! [       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 ' @3 F; m6 V9 z2 v2 |5 x
     关于MG: 7 Z& d5 _9 Q) B, f! ~. E6 \
       当MT=9时,MG为用户发送的消息内容 . a( M1 k- ?; m* v( h$ R
       当MT=99时, + f! K2 ^! V" [7 r' W
         MG=10(QQ_STATUS_ONLINE)表示对方上线 8 M3 Y" y8 f4 i- g
         MG=20(QQ_STATUS_OFFLINE)表示对方下线 0 E3 U$ e% A0 r. ~7 Y- g
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
: a  ~% s3 b+ D. {  y, ]       当MT=2时,MG为对方请求你验证的信息
1 ?) Y6 M2 _/ H  a) r2 w# \! s       当MT=3时,表示对方通过你的验证
! A, u- D/ d! s8 v6 x8 g- ^0 D       当MT=4时,MG为对方拒绝你理由
; u, x  V  k8 w6 Y0 |$ Y, q6 \9 j( O/ }' _( O% M( {
(10).发送消息 # d5 Q  H( L% w1 j( |- ~
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 7 u8 \, V" }3 F" g" {# K
' y; |. t5 M$ }- B1 ^
  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
" V! w3 Z; q1 F9 B     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) ; j6 O2 P; i0 J4 {
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) $ w) L6 P9 k+ T- B# |! H
     NULL(UIN、UN为字符,MG含非UTF-8字符) / T! G" `' |( b' ?7 a
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: % Y: x6 u6 h( V/ b6 h
       你俩互为陌生人,且对方没有和你说过话
, D) Z0 @2 w7 W5 Y7 @  ?' ^  m       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
* ^4 w* d% Z0 b8 G     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
& u" h, U' w" L7 m" w" s! _8 c     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
' U& R! [5 V& i0 t2 B- e
: d. k& `% r+ J& m& @8 G(11).登出 : d# a) C; W- M% i/ P
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
3 A: A7 W1 _) z" ~* I( v
' F) z6 h3 S) ~$ v; P: F1 _  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
9 L- C7 _; X4 q( @4 q     NULL(UIN为字符)   T: c: Y4 l0 U2 N) |" E4 v+ Q3 x
. a& {. t# Q6 D4 ^2 }
5、总结
- B; v2 @: n5 x3 N" l
- X3 t3 i9 e$ I) }* R8 u2 D- c  t  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
5 r/ k, `, [% J2 s! h  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
7 t3 M% D( o5 G# z( v4 j5 _: M1 _  本文撰写时间仓促,难免有误,希望各位不吝赐教
) g9 ]( X- R4 `
( w* a3 o  {! i/ b7 P
8 _( |" L, k( j1 L! R* a) rTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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