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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan / q) F8 K% ^" P
日期:2005.8.21凌晨
7 |7 b$ R) H( Z' U- F; E  h- D联系:QQ:106814 Email:hackfan@vip.sina.com
$ M6 N  l0 {' l' S! X/ u0 B! c# [' l* e9 N! O0 b$ D/ A
1、研究说明 ( D3 x) v" F% }2 A  [0 |

" c- l/ O4 e5 b% B& k4 S. j  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
7 }5 J4 O* m9 h' A
! b! Y0 L0 A. J! m( ]$ {4 r  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 / {/ E5 S$ F( K
3 e4 j5 o% I  I9 n% |* m* D
2、接口说明:
4 b, `4 a; Y" h! v# g7 t- {& X% L" _* I/ P  P9 R3 H3 }* A9 v
  接口位置:tqq.tencent.com:8000
4 V; c0 M. D( }" W# ^  通信协议:HTTP 3 O1 V* z( c4 A/ d5 R4 D/ x% v8 V
  数据传输方法:POST
7 Z- i8 P, }% d- T% o! |& N  HTTP请求格式: 4 U! [0 x3 u5 g
5 S0 l( X3 b6 S
POST HTTP/1.1 3 C2 ?' |* W+ X  x" a2 p6 ?" Z
Host: tqq.tencent.com:8000 2 V1 }2 Q- M5 d* c5 h
Content-Type: text/plain; charset=UTF-8
8 _6 @$ t2 S& a& ]* }7 |# JContent-length: 长度
* U" e* J8 w* }. Y+ d: aConnection: close ( B/ T: I2 \+ M4 Q4 O2 B

8 [4 o+ o4 R( L, o. Z* d* w8 w数据 # k0 N. G6 Y: \: e& O
. T5 u; w. r# y
  其中长度为 数据 的长度,数据的格式:
* t+ m2 j: C; D8 I. @; s  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... % x" S! \: _+ }0 a

, F4 x7 X: q6 Y0 R$ 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还需要不同的参数,下面我就公布我的研究成果。
+ }8 }, R2 z0 [8 h* V8 m. M+ L+ m- }6 D* W. v
3、研究方法: + e- v9 X: M! d- e" c

: V/ E+ q: V# |+ t- m  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 3 _3 s+ y( n9 T9 ?% u& z; |
  下面我公布我探测的代码(PHP):
  1. <?   \) b# p7 A. {  `% J7 t$ i
  2. $uin = "QQ号";
    1 d7 E$ K/ O: u2 I
  3. $pwd = md5("QQ密码");
    * a3 ^( j' _. [' Y2 T6 _

  4. / q) b4 i) q- Y; Y" M' z5 g
  5. //登陆测试 5 }# ~& z( S& }+ c
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 7 }7 T' l* ?% b  d
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    6 |: G# J  G5 U* A: V0 L+ Y! X
  8. /******* 7 h1 n; r. L5 O; r1 ^! R) X* ]
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; , @4 u. X* A7 ~0 h" `3 f
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    . }- D' p- Y/ M7 s
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 2 P/ z0 l# C0 v+ n
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; ) j9 @+ s$ k) Y* x# X2 G& p
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; + C/ J0 l; x- I% u5 |4 P- Y3 n: ^
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; + N0 j9 X( F% l$ C6 J
  15. *******/
    7 Q$ z/ h5 {+ G* n7 I) ^( e

  16. / V3 j4 m. I9 V; P% h+ U5 [6 `
  17. 0 a: \7 u7 t, Q# Z
  18. //得到好友列表 6 g- z7 t7 Y. L  e1 b) k# X" B; s
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    % y- k$ X3 w  m; C" y* \# U  e# |
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; ! E4 I, X; b' n2 m( X' p' E# C
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    . f) T8 U/ I$ }6 m! h
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; % Z( o- N% D; O  ?; f
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    0 S) s" S5 {0 [
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    . O  I+ `# [+ h' T
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; " e( a6 Z& o* q, ~7 E2 E# B5 I6 z
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    3 a, @! g0 c+ _
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 9 G) d; g" B" e! A( g
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; % L5 y7 y# m5 \3 K( b+ G
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ( v  v5 `5 b! H2 F+ j
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    2 o0 V- l. [$ ]0 z. z  g
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 3 H+ P! s. u3 w3 C* x
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    6 T; J+ I$ u4 S4 ^
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 4 u' @+ H6 f  ]6 x
  34. 5 n% e) o: G% p5 ~5 }+ \0 U+ `1 `
  35. //得到在线列表
    ( Z5 B3 Z4 f) X  \
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; . c$ C( q1 e& p$ j! U- e
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    * p( l& p5 G; _0 c7 `) x/ N$ ]
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; / ]$ y* d8 x" m& i! m' u+ n+ }
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    : O- }; g/ o0 |
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);   `  W/ w6 Q7 C* ~
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; # Q2 D( D$ A4 P1 e0 H
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; . U5 G) [$ j. s
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; $ a  \* S# d$ G
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; : h8 E9 M* F4 \' p) X
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % K7 v  Y! T2 ~0 f
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";   e: d8 e; K% }6 ?$ p
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    - g$ [( V& T: H& h* H9 Y- R
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    , a0 h# \2 G, y2 ?- A2 Z
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ) ?/ |  d3 B6 d8 X
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    1 `- P& f0 z1 W& D3 d

  51. . O; U; e; r+ V! `; r
  52. //查看好友信息 3 a3 k7 k) `, k
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    ( |: A  x1 K* d- q" s9 f- z, o$ t
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; ' V+ i# k7 R8 E7 H7 C$ ~( l
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; . m$ M8 Z' L& i
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; . h' b: t9 \' F
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; 8 _* T0 }6 {8 x+ [1 ^
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; # a$ a5 s9 o& R0 n7 H3 S) ~
  59. # v; t! C6 t8 [' Q$ h0 c
  60. //增加好友
    & ^* j3 i, T* t3 b
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    ) g3 B3 L5 ?1 v- n

  62. $ u4 {9 c& c  u% r% p) R
  63. //发送验证
    , I( B% e4 E& S; \, {5 ~
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    # J6 E, _5 k5 {! I- R# ~( u- \
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; 2 K7 _2 D4 S: S) ~7 c3 r$ W2 r
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; 3 a+ e" N2 {5 r- E
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    / t4 ~/ T- `) v
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; 5 \0 v# W9 J* r  W, r( p1 y
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    0 p1 s9 ]+ O1 b, ?( a

  70. 8 h, q9 T/ j' F" t1 f- C- |7 q
  71. //删除好友
    / J) V2 V( f  {2 g4 W) @8 N; ~
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    & B( g: ]! v( w# J! r, M
  73. # y$ b& k/ p5 o) e4 z! Y- u
  74. //改变状态
      I3 r$ G0 E6 x, _. u4 |
  75. for($i=0;$i<=60;$i=$i+5)
    9 z9 ?% \1 l/ O! F8 _1 }& T, l6 P
  76. { 7 O( w; j5 G0 c3 A
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    2 Q9 F. y' r( }7 d
  78. } ! }( ?" ~# ~( a, D) P4 i7 `

  79. , \3 f& \) W! e+ x
  80. //获得消息
    9 }4 z2 m6 \5 C8 u; K
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
      H. w. J6 E- t' r% _. w

  82. - z1 W& s; ^' `4 |$ H
  83. //发送消息
    % J0 Y$ d- Z* I7 H6 o
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; * q/ Y0 U+ B( L( J$ E

  85. " K+ P9 e5 b. O) I1 G  t
  86. //登出 1 r+ Z: e( K( `! p9 d$ Q; m" ]
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; ; y8 ~1 [: G( t6 v$ @: o0 x1 h
  88. 4 I! c, f9 U0 M
  89. $file = fopen("p.txt","w");
    : T, G$ O; Q! i! c
  90. * J- f  g; r. K# e+ m
  91. foreach($poststring as $k=>$v) 0 o4 [1 ]5 E9 z3 v+ I% [
  92. {
    2 [; @$ P9 N2 V9 N( w7 z5 c
  93. ss_timing_start(); 7 Z" B8 E" b9 h
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);    d+ c5 b$ @) ~+ G. H" @

  95. 9 o0 F5 z+ \' N0 \/ R
  96. if(!$fp){  
    ; D# f' j$ J1 p& p8 c
  97. //error tell us  % c' P8 Z9 K: E+ Q( k
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    : e1 n2 L% v  T
  99.    1 n( p9 M" W- L4 S. ^) W" {( B
  100. }else{  
    , T, C1 Q% o; j. C

  101. ; z; ]: K9 q/ [' E; D- m6 `
  102.   //send the server request  5 Y+ m) C% Y9 H, w  e& i. N4 y
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    ( N# Q2 B# @" F3 z+ z
  104. //  fputs($fp, "Host: $host\r\n");  . u" U( p) A1 }/ r
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  ( h0 a1 \+ k" X
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  & M* b, ~$ d' a' v
  107.   fputs($fp, "Connection: close\r\n\r\n");  ! ?  |: H' V. l* ~. Z; z
  108.   fputs($fp, $v . "\r\n\r\n");  
    * ]; s- l! ]) x0 u

  109.   X5 s" R- o# ~+ ^
  110.   //loop through the response from the server  8 O) |; ^4 V8 p: g* @% b
  111.   $res = ""; 0 j7 q  w, F; M/ C+ [% A
  112.   while(!feof($fp)) {  , u% M1 b. n5 v
  113.   $res .= fgets($fp, 4096);  
    * \; G- j  o+ h! |4 j# M$ x
  114.   }  
    7 y7 |& m7 S2 D
  115.   //close fp - we are done with it  * r( e: y9 H0 M/ D0 J3 A
  116.   fclose($fp);  
    8 }! J% c+ ]$ ~; D9 B- g
  117. 6 E# w$ B0 z8 J3 p" ~2 C1 p
  118.   $content = $v.chr(13).chr(10).$res;
    2 q# v+ ^: B8 u# v0 q: Z1 `" e2 v/ H
  119. }  + l( A2 q; M4 w0 X0 o& i/ I
  120. ss_timing_stop();  
    0 s# C0 G5 W# K* I
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); - F1 g7 Z6 `$ D2 q' @) b0 \  l( O  J  h
  122. fputs($file,$content);
    / }: z" P" B+ E9 C1 a
  123. }
    1 U5 A( p! W7 V4 x
  124. fclose($file); ) [4 {4 J0 v% L: ~" `+ l: M
  125. ?> * ], W8 L7 Q; C/ D
  126. <? 0 h( X) i' M9 V* k5 z9 t
  127. function ss_timing_start ($name = "default") {  4 G1 I8 v) \5 C1 p# |6 |
  128. global $ss_timing_start_times;  
    1 O) I  T/ l  V/ H2 t
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  1 s, U4 S! e1 K4 i2 u% Y: x+ d
  130. }  
      ^" D9 u( L: z( E6 O& ?" C9 e
  131. function ss_timing_stop ($name = "default") {  7 |8 x$ S' {& P; b+ E
  132. global $ss_timing_stop_times;  
    . F/ h7 `- m* M1 s& Y  i
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  $ ~5 x# T% u3 a0 q  L
  134. }  7 q7 i  O2 {# ~. p8 q
  135. function ss_timing_current ($name = "default") {    E* S! O* e) c
  136. global $ss_timing_start_times, $ss_timing_stop_times;  1 f/ i2 q4 X  _8 s! }, m8 n
  137. if (!isset($ss_timing_start_times[$name])) {  1 `, B5 k# L3 B
  138. return 0;  
    # D( u' Q0 p3 Z" S- l
  139. }  ' Q2 M) [4 S/ G% r/ T- B, A
  140. if (!isset($ss_timing_stop_times[$name])) {  
    / Z6 L- I- g( R
  141. $stop_time = explode(' ', microtime());  
    * Y. q- d* W8 x/ C
  142. }  
    0 o, S* r/ K1 y# I
  143. else {  
    2 O* x6 D; P- V% z) V+ Y# T& O
  144. $stop_time = $ss_timing_stop_times[$name];  8 W& E, V* v! |! o1 O3 ]
  145. }  
    / p* H( p( d" Z+ Y' j- }
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    # h% T: S9 m# M4 g$ F3 o
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  ' F  R. p; `; i$ P- I
  148. return $current;  
    ' D# x) F3 i+ n: F
  149. }  
    7 b% [! ~  a- e) E; q' q9 z! j7 m9 S/ g
  150. ?>
复制代码
! T8 e' X$ U/ H2 i- \6 n& S0 x
4、研究成果: # Y1 h8 o# m0 f' i) g$ d& _: H
$ }! ]) B0 G. ]$ G/ E4 N  ?% z
(1).登陆 . ]. g& Z& q2 u: W
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 & |# l) p% Z. ?# w* w" p0 t
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^
/ v. L1 G& D7 M4 O1 E  i5 }1 b
6 o# y8 E8 h- d( T  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 * u: s: E, e2 ~) v1 m1 g  l4 U
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
8 F! O3 N* L5 v; u     M5这个参数的作用还不清楚,但最好为1。
3 t& V" P: Y7 Y! ^8 ?* S     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
; i' q9 }9 m! X0 z) i& \* F$ e- Y4 ?( G1 s
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) 9 L- p7 G9 f, l+ \5 B! S
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) - t7 N9 a' z5 B4 Z! y# v! |! x4 f! n
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) % \) W5 U9 H7 T! U, [/ z* c
     NULL(UIN为字符、PS为空、LC错误)
/ N9 O8 J3 n6 Z
" O# E+ n- v! D) w5 m/ m(2).得到好友列表
; e- k4 e5 c. W+ I6 ]  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 7 r2 W9 ]: k1 E8 B1 M  h) {
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 3 v2 {2 q9 {# h. \" K. d  v

4 S- t5 U  A* M. D6 ~" \. k$ W  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) ! R  o8 ]' d" ]& k- B
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) . G. v5 u% n: Q  J" W( i& I; j
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) - H3 R5 O7 C6 r* j
     NULL(UIN、TN、UN为字符) 9 D3 N1 ?+ b2 V2 c
( s, l3 R: Q' F" c  {: E
(3).得到在线好友列表 0 ]/ ?1 y+ I+ A8 U
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
4 |# L4 |4 J) ^& V2 r- z. @  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
" p5 s" r/ [( ^7 T( _4 I& U# ]- c) _1 K) U. I* L% \- f
  返回: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的值用','分割,分别表示头像、状态、号码、昵称) & m3 |; f, }/ \# w) e
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 5 {$ g# G4 Z# k! n5 g4 d7 x
     NULL(UIN、TN、UN为字符)
6 i* k8 h) [6 V" h4 H  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; 9 H6 B: m6 C3 w( F5 G% n
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
' W* `) x- t4 c- ]( `! @! d; i- @) j- D" K8 M1 [
  特别说明:当参数TN=0或不存在时,服务器返回:
2 A5 @* u& h6 t) nVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号   G  D, o* f9 y. b1 [6 R) C
HTTP/1.1 200 OK
& c9 z9 g& H0 v7 [3 s9 O8 Y" AServer: tencent imserver/1.0.0
# |, L% C+ G' V  aContent-Type: text/plain; charset=UTF-8
9 z7 x1 ~0 c1 ~7 v. D4 h# JContent-Length: 56 / v' E* w" U7 x& k. v9 v

* I: c( R6 I( X& B' oVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
- Q* b: _% r& \6 NHTTP/1.1 200 OK
8 s: F$ }4 @! X: A( p+ u0 iServer: tencent imserver/1.0.0
, |9 a+ t) s) [- c0 zContent-Type: text/plain; charset=UTF-8 $ Z( `* e7 T* a) `- A
Content-Length: 77 * \, G8 J" o3 O. l- C

/ ~8 ?+ b6 m  M$ r8 v# [% RVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= # g) F$ w& O% W5 e7 C$ q7 Q
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
  S! \8 {" l$ j0 I" p/ f; }8 U3 }9 j2 S5 M6 d
(4).查看好友信息 , ]( q+ o6 R8 O8 J+ y; @  s
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 - O5 \2 f. s* I' ~4 H% P
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
8 F7 L: c, u2 }' Y1 c8 N' @& G$ I) L) Y' k
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询) ' {7 N' [4 s9 v# _8 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=学生
! @" V: g; q0 r- M4 x7 s( h# |% o&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  ; {5 t6 k1 X; F. |$ V8 ]
好(普通查询)
" k  r. O0 W% |, l+ E  n( f     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 % L9 @! D, P8 Z; D7 A
&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 a' q1 d* z1 e
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
2 Y& m, s8 d7 [2 G. U) c$ B( N5 ^     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) & [1 f6 R8 V; V6 v6 J
     NULL(UIN、LV、UN为字符) , }1 i. n+ R5 P+ k& f
7 Y0 U4 c( X6 r9 d. E, j0 m
  说明:AD为联系地址
  |# i" \) V- x' u0 m     AG为年龄 & `2 P* r7 b2 D4 q- J9 }! L$ T
     BT为血型 ' }, e) n2 \0 c5 H' X
     CO为星座 7 ~5 L! d, v$ }& @9 j
     CT为城市 1 ?6 w6 r7 Z" I4 n4 u7 m. [: z' y
     CV为未知*
% Y0 m1 c& r  Y( C     CY为国家 ' z( I$ ]* y3 S/ L; J6 u
     EM为Email
0 e2 P' g% t( N  a: `# r     FC为头像
: D! q. D8 G& D  R$ P     HP为网站
  h+ v( W, Q6 L0 d' L# U7 J     ID为未知 & u1 b6 m( l2 k0 x5 G! ^( a
     JB为职业 6 A) X3 D! ^) s( I
     LV为查询代码(就是发送的LV) ( O9 _2 W, s1 H! i" I
     MO为移动电话
5 I8 E4 a/ D9 S/ Q: Y, y     MT为未知
. c* U5 d. D& L* Q     MV为未知
- \, p% |6 w+ i( |. w( }     PC为邮编 / s' Q  u! ]) T0 g+ Z) T
     PH为联系电话
  D$ v9 Y9 M2 E. v" M9 h     PR为简介 $ g2 ?5 |: e% D
     PV为省
" [# K# I7 L: }, ^7 m7 t) g* @     RN为真实姓名 " v5 C4 U) U" U7 f
     SC为毕业院校 $ c# B7 t5 M" C( H% r
     SH为生肖
+ A, v8 c& W% Q- ^2 u* A     SX为性别 4 Y6 p& `  k& u; `0 `- _/ ^
     UN为QQ号
+ G8 g8 j% Z3 H! k# _( F     NK为昵称
+ z9 h' ?% F! ]( e  r. u6 _! j) _, \- N
     血型:0 => '', 8 ?  t9 h' O6 d; M
        1 => 'A型', 4 E% W9 Q6 f& U; L% l7 n
        2 => 'B型', 3 j/ D4 }3 ^4 L( g8 l6 f0 }
        3 => 'O型', 5 s- n* a+ A" v1 K
        4 => 'AB型', ' A2 H+ a/ Y1 B8 j' X4 n0 m  Y
        5 => '其他' + U( F% K2 r# v6 i& }( h! `% i" B
  t9 U/ K+ x+ R, x

9 b: n4 A, z$ P/ e/ n     星座:0 => '',
4 C" N5 V. z6 C5 P        1 => '水瓶座', ) F# J2 H- B% d+ ?  P& H# P# m. j
        2 => '双鱼座',
4 W) Q) Z7 f. q% L& t        3 => '牡羊座',
( g# w4 t: }+ j7 y* ~4 ^9 C. r3 ?        4 => '金牛座', ) _- N0 [; U+ [: c0 R. E) s6 r/ a
        5 => '双子座',
* T; B" V& T# r# H5 y3 S. {; \' T        6 => '巨蟹座', - V7 z8 ~3 [* g* l. s$ v, Y0 N7 G
        7 => '狮子座', + s6 l: w2 W1 m# V2 E$ t% A; T
        8 => '座',
/ A3 x0 O( C, C7 _        9 => '天秤座',
# N& {# j; k/ _8 p( ]9 n        10 => '天蝎座', ( D4 C/ M: N) W
        11 => '射手座', # Z. H9 d4 B% H6 A) R7 o; t; m
        12 => '摩羯座'
; w% J7 N; W' K5 B8 Y% t0 `& J- D/ O* z6 g* L0 J
     生肖:0 => '', ' ~3 b. ~: \9 T1 C0 S  d
        1 => '鼠', ( i& N3 a. C2 I
        2 => '牛', $ U4 k* w+ V% i8 B; W+ f" x  ~" F! F3 F
        3 => '虎',
/ c- @' ?+ A) J$ m) o        4 => '兔', 8 {2 d+ ?9 K1 Z. y  s, I0 n! W
        5 => '龙',
7 Q  e* z( `/ c. d        6 => '蛇',
  |' [  O# w  X. O* y7 ]* N        7 => '马', ) J: V7 D: E* P* S
        8 => '羊',
; k. j9 E5 I# c% V$ {( J2 |        9 => '猴',
. }3 K8 P6 ]# z9 ?        10 => '鸡', - n0 c2 X7 I* Y
        11 => '狗', - w8 S1 Q( L, p0 T% I3 B' j4 p5 W4 n
        12 => '猪'
/ }* k8 {0 X  ~7 ^* U+ k7 o- L% c4 G; i, W2 \
     性别:0 => '男',
- M& a8 V8 J9 C+ u! Q2 Y        1 => '女'
( r4 L! P5 z1 U0 a0 b; i/ J3 n9 i( q7 H& \- o7 t
(5).增加好友
' O" X% \+ D: y* [% e' e+ K  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 ; e- A6 A4 @' Z9 x
% T  D4 ~+ B' X5 c
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) / C" x" I" i0 N/ G8 c
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) 0 z2 m* I. b4 T
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) 7 J, F, f, ~7 _5 a$ x
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
; C+ j5 P9 A/ N% g     NULL(UIN、UN为字符) % x) N8 {( t( R% q5 N9 I

! N  U# r$ O5 V(5).发送验证 & M: `0 {4 b& c/ `8 s, s) Q
  说明:1、如果你加对方为好友,你需要发送验证
& z5 l# C, [' f# l     2、对方加你为好友,发送了验证,你要通过或者拒绝 ; M" U4 z# P: ?9 L, [7 d
     这2种情况需要发送验证消息
: p9 P  k% g. |! B1 B# a' p+ z6 N1 h  @1 ~# P: j3 Z. \2 Z9 u# f! L
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
& _8 a+ {! q1 S! s* p( g  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
4 k) h$ M+ t: M. z' g1 f7 M
; f! k# X2 ^6 K4 r4 L$ M% S: l  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
: d9 U2 c. f& e" f8 S! q' M/ j     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
1 f8 L7 X: N# C3 V7 h     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 5 D6 f( R& [- @* h# `5 s' o  _
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
4 v! s7 \7 b* O9 y2 B  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
9 U' [* m4 ~/ X, x6 E" v! R
9 T; e  ?/ d+ \' A(6).删除好友 ( j/ i) p4 p5 m5 s9 w( r
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
  q. Q0 G1 t$ B7 p; ~) }+ y" G
% i' z2 V! A* P' ~" l$ O  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) & b/ D( T. [  K6 y) l1 p/ Q
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
2 ~2 H1 @& {9 _' H# n     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
9 |4 o6 e! P) g$ W" g8 w6 |     NULL(UIN、UN为字符) 6 U4 a) ?& @; A8 Y
8 A; \3 H! `8 @6 q/ n2 x8 x
(7).改变状态 # V& ?$ u: @* K+ |* ?+ B/ S
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 . F& `5 ]5 A! E/ w5 Q( {+ ?8 K5 [
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
+ M: F( Z; J& J# G3 H1 k. B  J% q: y" [0 Z+ @
  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
" O% {' B) l! p) i) e0 x0 F2 b     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) 1 m8 ^4 u3 f1 }% C4 k
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
6 E) y/ l9 Z5 f. G5 ?     NULL(UIN为字符,ST非法)
+ j) i, Q8 }* O( h6 A% Z4 l/ ~  i6 u+ x5 N) k  T1 @2 H0 Y
  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
! J* S" C5 T$ Y' z7 K7 T' e       同理,当你的好友改变状态,你也会收到一条系统信息。 / j0 G, ^6 q+ x

# O% E8 r. e' {) x(9).获得消息
/ ^7 s* g; `2 a/ K  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
! [6 [  K0 ]$ F/ c/ e8 Z8 a5 g0 T+ M; c
  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) 6 \8 ]3 O' Q2 F- f0 c- H2 i# G
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) 0 y# a% r5 ^9 @$ D5 A
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& b8 t& i- M5 x7 f  q     NULL(UIN为字符) # _( O) p1 i" i/ I# Q4 d+ ~& a# a* D% P
  说明:关于MT:
! r1 u5 l6 u& N; q       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 , Q) v$ W: o, ^, x2 p
     关于MG:
  i; E5 t8 n0 r- @" [* V       当MT=9时,MG为用户发送的消息内容 ) g, u! }8 h+ W8 y% J+ U" S* E
       当MT=99时,
2 I! W& P" l. v1 h7 ~% s2 |         MG=10(QQ_STATUS_ONLINE)表示对方上线
- y7 d( K; @: Q2 L6 a/ O         MG=20(QQ_STATUS_OFFLINE)表示对方下线
/ J4 S. r8 ]/ F3 E! M- u2 _6 h( f3 q! ?0 h         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
8 P+ V" j8 X- w, W4 i; q: w       当MT=2时,MG为对方请求你验证的信息 8 H* h# d& Z0 ?' y  N- k, C$ \
       当MT=3时,表示对方通过你的验证 $ Q$ U! b2 K9 L& H  Z
       当MT=4时,MG为对方拒绝你理由
* S! m% K, g" E1 q
6 j; |+ [: ^$ P, j4 _0 w1 S5 u(10).发送消息 9 @  ?9 q  J8 _$ R7 K- H6 m- z
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
8 P7 R& W5 r' Z) {3 s' K/ `$ \; k! C6 M$ u  W6 v7 [5 m
  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) + U6 C+ j6 n6 M
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
! h0 B- Z  @4 A/ A0 a' D     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
+ \+ k$ V) O: I9 r" H4 s  D     NULL(UIN、UN为字符,MG含非UTF-8字符) 1 A/ N; n, V3 z& ]+ V8 B* `. u( Z& l' f
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
, ?. J1 Q6 K6 u  H% I( `" o       你俩互为陌生人,且对方没有和你说过话
) b2 l, T4 ^+ p1 N* q" I# i       你在他的陌生人列表里,并且他没有和你说过话(没有验证) 8 {  z- J9 Z0 ?7 A/ ]
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
8 e. M; j/ [+ X4 C  w# s0 E% d     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
& h3 m! n+ s- o4 T' k
: v( m* x" R% W( p) M: Y(11).登出 , }  q& ?7 z7 S
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
* ^5 d8 A9 F* Z, a
! U! Z" r/ q4 h8 q  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
. ^8 }5 Q6 G& g% w0 H     NULL(UIN为字符)
, K- N( t6 N. ?1 p  Y2 X( A/ _$ B
: O' H& J/ x0 I9 h. h1 t8 `5、总结 # ~+ ~1 z, E& O5 a! v5 v) r- H- j
* f/ V5 y1 @$ I3 w8 M1 b$ C7 g
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 * W" F& ^# U/ A8 e& ?' p
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 " G; j7 Q' o/ P7 h  j4 a
  本文撰写时间仓促,难免有误,希望各位不吝赐教. z; k1 G' U4 ]8 P6 Y( ~4 v
- k" a0 R8 u& x3 {5 v
: k8 u& p3 ]/ D& N
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-20 05:08 , Processed in 0.037301 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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