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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
# x! v9 J1 D$ C7 X* C- J, |& j日期:2005.8.21凌晨
/ y+ D* _2 M& z* k联系:QQ:106814 Email:hackfan@vip.sina.com
' b4 K7 l8 Q: v% B/ `1 D& d: X2 E# J3 ^2 M; q! E2 }6 X7 O7 N1 k# ?
1、研究说明 2 A/ X& q1 t- E# X5 R5 W
5 _% P) o; C  P. o% X! G3 M  W5 d# `
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
  V% b0 e' I- J6 A$ g' r4 I! N* d- r5 t9 {
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 1 V- C9 }  E+ \$ U% w
: ?, x: q! D7 H, g6 K5 R1 m2 C
2、接口说明:
& m& O0 A1 b$ t- {, |, s9 Y, n4 ~4 \+ q; c3 L/ O+ A9 @
  接口位置:tqq.tencent.com:8000 $ D, N5 |. K7 E" T
  通信协议:HTTP
) Q' W5 C6 e6 L8 H  数据传输方法:POST
- }$ r$ S2 J  ?' v- |" S  HTTP请求格式: ; s- E0 |( u6 H5 d  N

! {% d3 Q8 f3 o6 E# ~6 `- x8 u7 s/ XPOST HTTP/1.1
. ~: O& E* p3 V6 J( C+ tHost: tqq.tencent.com:8000
% U7 J8 u# N6 ~1 X4 i9 W9 l5 OContent-Type: text/plain; charset=UTF-8
% e9 c4 `; b  g' }& eContent-length: 长度 1 T( T! r& e* j  a1 n1 x! Q' M7 U
Connection: close
' @# F8 P2 \, P- z" x; _) }- d( V
  I$ b/ t8 h5 S数据
& B& m. N5 d9 O9 K9 W$ R6 p( S5 d  H+ x7 s9 C4 i9 o( F6 S4 m) E& w
  其中长度为 数据 的长度,数据的格式:
( x# c/ V, A  i; G, i* h! Q  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&....
3 y# J3 j  u" H/ T1 G+ z) T
* S0 I: r' w0 w( u  U  以上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还需要不同的参数,下面我就公布我的研究成果。
1 o9 w. z# L1 N0 M6 ]/ W% y* i  \
# |5 P6 B* Q$ r9 z* H3、研究方法: ( ]: \3 Y7 Z* H6 e
, m  P3 F9 h- Q) z# ?
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
0 A2 X7 C1 f* M* I% x  下面我公布我探测的代码(PHP):
  1. <? 3 _; }2 x4 k3 g* o# o
  2. $uin = "QQ号";
    3 O- y( K4 d) F
  3. $pwd = md5("QQ密码");
    - f9 ~$ Y9 N. B- p  M

  4. ; \2 I3 n4 y0 x; Z' a% C
  5. //登陆测试
    # A% f  W8 k  a* ]% r) T
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; ( G1 i8 m% n( D2 `
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    6 f1 R" F* d5 D7 B; O8 l
  8. /******* % r# t. t! F5 [- k: h7 ~  g; k
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; 0 l1 m6 ]- O# S
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    4 V- r$ w9 P# C! L+ K9 o
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
    " _7 G% |# t% H( z6 {0 w$ L& j
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    , ~, M. p/ T0 o" j: g% v' H% `# `6 j+ h6 U
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    / \& g6 K( h2 K3 m- o7 Z0 g2 M
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    ' K* T7 Q) |. C
  15. *******/
    9 D1 J+ h0 q( |7 N; a
  16. 7 G$ y* H+ E8 ^! Q
  17. " s0 V% i* ~2 T% _( w- C0 j
  18. //得到好友列表 * V% n) p+ y  p4 h. m" \5 E( \- v
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ; q5 }6 n- s+ X( m
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    ; L: j& k. N1 _8 E
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; ' g$ O8 ~0 x, P$ w" J
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    8 M, s3 U5 |: D' e/ V
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); $ i" U* y3 L- n. w
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    : d( v8 m: c8 Y" G" s
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    7 V8 Z, V+ Q2 G5 s
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    : M5 W. W: i( l
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 6 Y; Z5 q# j, t, b
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    # ?2 W0 n7 P3 h! D( o% y- B
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    / D4 u% J, ]2 B2 I  d$ \: t$ i( t' N
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); / h' w0 ]5 l* t2 t4 \
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ; j' M3 P/ c2 F) n% ^# N% |4 _3 i2 J
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    + [% y  q% i7 n% r2 F
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 3 e$ c' D8 {# Q* d' I

  34. $ G' G. h" @4 `6 k  X
  35. //得到在线列表 5 u+ o* q: B( D% ?" b
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ( q' e0 d0 e+ B) f& f* K
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";   S, P% M+ J5 h; i; ^
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    4 h7 v5 x0 q/ |! P4 d( A
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 8 m2 D" s/ j/ D! o# {
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); ) r& t$ g" J# R( I5 m1 J4 w& W
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    ; a# e6 \. u" W6 P/ u! t( h
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; - J1 t0 F/ E, K" V) m
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    : [6 V$ g7 c8 r1 h1 f
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    # }$ E3 \9 S  F; q  i
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; . W* H. I  n% U7 e
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % e$ i- g+ k- G! o( n
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    / a% q# i, t- a8 Q4 L! y1 p
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    $ u. c5 B4 d  b' c: O
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); " p" B' y5 n# Q! C: F/ y
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; 7 h! z9 C/ N: Q% F% T1 s$ h" Z

  51. ( X* D8 d) R6 H6 o  n, d
  52. //查看好友信息
      M; P( u! q0 W% q" ?  I
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; 2 q6 `; i8 X! t# L- a$ z5 o2 T
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
      [6 J# @* W5 X4 y; [2 u
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; & I9 g" Q) ~# J, N( S
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
      G) t7 U: n% y: o- }5 m+ ]5 Z& _+ `
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; . A0 R( d5 f8 M- C( N. h8 X
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    # b. K- O$ M7 }5 u% [

  59. 2 {6 [8 T/ ], [
  60. //增加好友 & q* D- f+ u$ R2 s' _4 w- _6 Q
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; * Q" U! z5 Q+ G7 r  T

  62. $ r9 Y! s9 }0 ]3 I+ a( _! I$ G
  63. //发送验证 1 i$ D  p4 a& X& [9 \
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    ! U$ {/ v8 G4 o) u4 F
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    " m- @2 C2 S; }* ^: o8 u" \
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; 8 P2 k0 ?1 ?! g  B0 \: h! @
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST"; 3 j2 U  M; H! ~
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST"; 8 [3 `& w/ t8 b8 w/ `
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; 7 V" z: F, [0 a

  70. 5 Y1 D: j& N4 Z
  71. //删除好友
    8 F0 Z( v; d) c$ u" R- Q: q- Q
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    5 d% n. b- z/ d8 ?7 G
  73. 4 N/ G9 G$ x# d  n. ?5 b
  74. //改变状态 5 ~6 {+ k: G; w8 O
  75. for($i=0;$i<=60;$i=$i+5)
    , F* H' u' v# U) Q: h4 O% c
  76. { 0 E+ E! v/ R" Q. F1 j
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; " C$ c0 E; [( V6 c" L* }
  78. }   C' F# [) r" C0 Z  l- @

  79. & g% E$ D$ P0 d& F; P. S
  80. //获得消息
    , v. C+ n3 T/ `
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; " C9 {3 q$ S" @1 h
  82. 5 K3 o2 l5 E6 N8 J7 P0 F+ o# z! _
  83. //发送消息 : d% k  U  O) V$ A  y
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";   w, Z2 K( s! X6 L0 ?
  85. 7 d. @) b  o4 l
  86. //登出
    & w) O0 z& R2 b5 G% X
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    7 }5 ^4 f2 w% F2 s7 @, x. o8 d  H
  88. ! `& _( f! ~5 t- P' X1 L
  89. $file = fopen("p.txt","w"); # L4 g. X. ]+ X% N7 n" A

  90. 2 N4 K' Q" ~/ E2 e9 Y
  91. foreach($poststring as $k=>$v) 4 z" n( d% N# ^
  92. {
    3 ?9 Z2 b+ u8 `$ R5 ?
  93. ss_timing_start(); ; J0 g+ j8 V# [! a1 B% v( b
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  ) O4 b. V6 P* d4 \) Q7 S  l
  95. 7 @0 O) a+ f+ |+ n5 ?
  96. if(!$fp){  7 i- z4 l% J" t+ S: Y# |
  97. //error tell us  
    ( C; t* c& Z" b- G
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  5 X+ R1 C, b. X9 e
  99.    
    8 b: q8 ^! r& V) e0 y- H. I. S
  100. }else{  * \, _# G  {7 v2 m( |# S5 G9 n3 X
  101. ; r9 e0 O, [: ?  o8 Q* t3 D  y
  102.   //send the server request  / N3 Y3 J; c6 u+ G
  103.   fputs($fp, "POST HTTP/1.1\r\n");  0 @/ u' s$ p# ^$ f# J
  104. //  fputs($fp, "Host: $host\r\n");  
    : M" d6 w/ h3 x) Q- c
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    9 x, V8 J$ N+ ]* ]
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    3 c* d* p$ A7 r& o" o5 l
  107.   fputs($fp, "Connection: close\r\n\r\n");  6 w7 O  s/ v# `8 Q5 u
  108.   fputs($fp, $v . "\r\n\r\n");  
    4 j) j1 s8 }2 F9 ^! {) s* K

  109. % Z6 E- m. `2 h
  110.   //loop through the response from the server  9 P* H0 u" i/ ~( _& b9 e
  111.   $res = "";
      N9 i  M8 O* T0 \; Z5 Z
  112.   while(!feof($fp)) {  & N" k# r8 P  q% S7 I( P
  113.   $res .= fgets($fp, 4096);  & o" \. t2 C) ~* Q( _
  114.   }  
    0 c7 f4 _; l2 W% w( F0 {
  115.   //close fp - we are done with it  ; I% h0 u- L9 M$ e1 R4 p
  116.   fclose($fp);  $ u% U: g  Y' v8 {7 c
  117. 1 B& p; u: L  X: o4 h/ K# k' u
  118.   $content = $v.chr(13).chr(10).$res;
    ; _9 _& o; U& h) d) {
  119. }  
    7 T" j& V; i- s
  120. ss_timing_stop();  3 O( a7 O! e7 M! z% J# |
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    : Z/ w& I% F4 a# c4 O
  122. fputs($file,$content); / l' b; }" [7 r
  123. }
    , V+ Q4 Q2 S5 ]3 ?) u; l1 \
  124. fclose($file);
    % R( X) X0 o; G
  125. ?> 7 C8 b' @+ A- }  |
  126. <?
    8 ~" T, t& m( G
  127. function ss_timing_start ($name = "default") {  ' H( V8 c# i4 r& {. w# b0 W
  128. global $ss_timing_start_times;  
    5 F: T1 A% @( r9 l
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    3 {3 M* M3 f7 ]0 Y
  130. }  - O$ T1 w  G. c$ g% b+ }) Z# o
  131. function ss_timing_stop ($name = "default") {  
    ' q5 J0 N( p9 `! T9 \
  132. global $ss_timing_stop_times;  
    , q$ W1 S8 v# H
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  ; b4 Q3 q2 G# I5 p$ G
  134. }  , U5 H! T6 s# {
  135. function ss_timing_current ($name = "default") {  
    1 V; J; V6 ?* ]% M4 E  d9 _% e
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    - b  E" Z& H& N* C9 h
  137. if (!isset($ss_timing_start_times[$name])) {  2 f8 b9 B( l8 E6 o
  138. return 0;  7 B1 H# M- B5 o  T
  139. }  + n0 A4 g2 Z/ {+ e/ }
  140. if (!isset($ss_timing_stop_times[$name])) {  
    & _/ k6 E3 @3 \8 u: S  s7 a  i: G
  141. $stop_time = explode(' ', microtime());  
    + S, U, U8 D  \5 u
  142. }  
    1 g% m! R2 v* c( H
  143. else {  
    9 `, S; k# i% v( n4 r0 l
  144. $stop_time = $ss_timing_stop_times[$name];  
    8 e1 M. i; Y# h! Z( a. M' E
  145. }  1 T* E8 v, x/ R- s$ u- j
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    / X, M/ v. `% Q+ a  T8 y
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    9 O: V* k  X5 n6 s; ^# L; V9 u
  148. return $current;  
    . K: E5 T& {- c% X
  149. }  
    + ?' L# c. a* g1 l0 k: E0 `- {
  150. ?>
复制代码
; G8 b) e1 g/ }6 X3 b+ h8 ^
4、研究成果: 0 ~6 n+ p' q% @

. p) d! v& M9 i% z: D; o(1).登陆
0 W/ i5 B2 d- U! h9 t  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 ; h8 H" ~1 G5 x7 Q* E2 H
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ 9 P1 l6 ^; |+ W- m) c

8 S, W: O! `: R7 ~  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 ; b7 x& v3 s0 f8 T6 q
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; 1 F1 T0 r1 T! j8 t$ X3 E: i, E3 F
     M5这个参数的作用还不清楚,但最好为1。 9 {. o3 T: d1 D7 k
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
; t7 l5 ^& q% q! H; a! k+ M+ L8 w& D' O' {* z! F( N
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) , l& d1 Q/ H. \6 x
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
/ I% s+ F+ |$ A4 e* [     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
* K0 b# L4 c, ?, q7 W) `8 G, S% k     NULL(UIN为字符、PS为空、LC错误)
. H9 K1 I9 Q0 h4 a: }
8 K. o2 ^5 E( l$ n- _; Q(2).得到好友列表
- O# _, `) m+ k; }  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
6 Y( [3 ~: j& x  Q  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 " A4 @& f# A, `2 g! [7 l/ m
- R  t4 i3 f' o/ a2 o$ v5 i
  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
1 a, O6 B- S: }  C; J' b% O     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) * Q* d9 |/ {, f
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
- j& j4 @2 O" t$ J9 ?* q     NULL(UIN、TN、UN为字符) 3 ~! K) U4 H1 j) J9 c
% U4 N5 w: V4 x6 s' u
(3).得到在线好友列表
; _" C& o+ w# ?! }+ j1 H  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
- @' ]5 q! e( X0 f  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
1 c! |6 N0 i: E5 P5 I! H# F3 x( ^. N' Z- p
  返回: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的值用','分割,分别表示头像、状态、号码、昵称) 8 t5 R8 w" l: c* S
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
, I, M" T' X4 v( a2 }     NULL(UIN、TN、UN为字符)
8 C( Y3 U8 ]$ i- |) B8 n9 [  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; 0 x/ T" G% s7 g" I9 Z
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; % z5 H2 n4 I% M6 V2 k
" I3 d& K. {" c0 T9 D; I& Q( q# y( W6 b/ U
  特别说明:当参数TN=0或不存在时,服务器返回:
2 g$ w8 k. r2 H* m$ hVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
. d/ o' D7 }' P; L) eHTTP/1.1 200 OK   D: f0 p% I6 o3 {  f* t
Server: tencent imserver/1.0.0 * ], K5 o! f0 l
Content-Type: text/plain; charset=UTF-8
; b. _+ t; g- Z7 rContent-Length: 56 0 `( ?+ L. r  U* S

  C( k6 `* b( V! E8 oVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 9 R7 F- Q) Z. V, q6 o
HTTP/1.1 200 OK
3 m2 B5 H: l0 |2 z" k; LServer: tencent imserver/1.0.0 5 N- c5 p0 ?) D4 J4 @* y5 @
Content-Type: text/plain; charset=UTF-8
9 E) E5 ?3 ~. j+ y; [Content-Length: 77 ' i$ |2 J" Q$ E4 N+ b- \  ?
( l/ `2 b6 b4 P- R3 G$ h
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= 7 s$ g/ e7 {) e6 w# t
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
# Z0 f! E+ z! N. z! f
; i- P: s/ B1 i' n( G4 n& [+ Y! C(4).查看好友信息
9 _' R: x! Y* T8 g) ?  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
5 H; q; @6 m% B0 r! ^8 O9 ^+ \# R  Y  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
( W( |, o! M! j6 x) \7 u& A, p* s4 N2 Z5 D
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
* y, O+ P6 H% O     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=学生
, r. h! p5 I4 a&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
; L5 e, ?* j0 f- h( O- `4 d好(普通查询)
( R: K7 Z' G7 ^, C. p4 B2 P     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国   p* R2 M: F! I$ S  m, X! H4 n  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  
* r0 `) f( g3 n4 J$ N0 A1 s2 B0 G! Hupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) ( t& O. N' g  c7 ?+ l9 G
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 6 T/ g9 a- d6 J+ x1 t
     NULL(UIN、LV、UN为字符)
7 V# A6 y' N6 ]9 ^
* Y1 i$ R) N9 V4 r  说明:AD为联系地址
# S6 F, v3 n* j# x; E" n& c     AG为年龄 & B. ]3 S: J' Q8 I) V' v
     BT为血型
  Z+ o5 k8 c6 X. I( g     CO为星座
2 c0 z- w3 A4 J     CT为城市
, i& ~3 k7 q, R- @* ?' M" `     CV为未知* ) z+ Y1 i. s7 v" ^
     CY为国家 8 y/ c* }/ g* D; z; ]5 v
     EM为Email
3 v4 R  o, |/ W+ ^% i' T* }8 v! Z4 L     FC为头像
1 G9 W; h3 D7 b$ z     HP为网站 8 N5 P$ M) r3 I9 g* C0 E: d8 {/ q9 R! B
     ID为未知 ) i7 h8 b. `7 _& q
     JB为职业 9 R" a+ c- n) g. l; X7 O+ M
     LV为查询代码(就是发送的LV) 6 G1 [9 v) r% t1 Z
     MO为移动电话 " u3 \9 B  s8 A
     MT为未知
# z" F. ]! D  {  ]+ q) a     MV为未知
+ V7 r6 ^/ C* M. v, O     PC为邮编
: g! F! ~( y2 m5 O- E, N1 ?     PH为联系电话
' J( }8 L% w7 B7 J     PR为简介
; D! ^) c6 `% v# b: l# E4 X5 a5 Y     PV为省
& z& C! ?1 k- h, ~& P     RN为真实姓名
1 V/ D+ q6 `( o. j3 X# P     SC为毕业院校 # }& ^1 b/ x2 F  r
     SH为生肖 ( A$ f" ]! l4 O. i' E: E
     SX为性别
- [& {) p+ u# }     UN为QQ号   E4 S7 G" E9 i5 b2 x, {
     NK为昵称 " c. Y/ f' d" p

% p2 ?1 b! w% w8 k  T! X     血型:0 => '',
. A5 E  u* L7 I; y* c5 t9 L' h        1 => 'A型',
, U) o) E7 f, c* q( }8 [        2 => 'B型',
( J1 ?# P' }( s) x        3 => 'O型', $ `2 E! d2 |* q3 Y# s5 [) S8 `' p
        4 => 'AB型',
$ b8 g$ n# M$ j. f- ~6 {, p/ u        5 => '其他' # u, f  Y+ p; C  B6 G
5 v2 X1 j. \+ R8 ^  p
6 c& n8 d# s7 i) C$ \0 U# e
     星座:0 => '',
7 I5 T/ Z- [/ M/ l% K        1 => '水瓶座', - e: u3 M1 D- Y1 Z6 ]6 k
        2 => '双鱼座',
3 m( Q/ a: }0 O, f. n( x- I        3 => '牡羊座', 4 u8 Z, O% B5 Q( U. m
        4 => '金牛座', 6 k/ n. L, f1 X0 @- f: s5 i
        5 => '双子座',
' O$ ~2 x: N( n0 Y! K        6 => '巨蟹座',
) X* Y1 K( h  h& [, G        7 => '狮子座', ) @0 G1 k2 y1 Q  A' r5 ]
        8 => '座',
8 K8 K; O# s5 [1 q; N3 t        9 => '天秤座', 1 g3 [- H% J5 G5 W4 g' g
        10 => '天蝎座',
- m) u0 l' ]2 v5 _- e4 l' G        11 => '射手座', % E! f& w0 p1 b+ r: g2 I) o
        12 => '摩羯座' $ X/ L* U& v0 w. r. B

# z' i! a, u# w" ~5 C     生肖:0 => '', 1 Z, w% [4 H+ i' Y! o- h% M8 y
        1 => '鼠', & J% E# E! N5 m0 `4 I1 r5 k
        2 => '牛', 2 v* N4 Z- j* t( |4 e
        3 => '虎', * \3 ?/ b* y( j7 {7 g; [: d% }7 b  d4 h8 S/ ?
        4 => '兔',
7 Q. L- B' i: N6 y( {        5 => '龙', 4 P! X0 [, V0 b" l: W, o' G# R+ K0 g
        6 => '蛇', 8 f1 m/ X$ g' v
        7 => '马', - C6 C: h/ J  |% f
        8 => '羊', . [8 t' }! p& x) D' c$ A: q
        9 => '猴',
2 Z: a1 ^  o  r8 y; R        10 => '鸡',
- C& {7 V. g) g- B5 e  [7 ?        11 => '狗',
8 Q! R( a$ _4 d. _! @: R        12 => '猪'
2 A) [, I. ~0 t+ s& _6 z5 @: ^: t. k2 U& l+ ?2 [7 D
     性别:0 => '男', 5 ]8 U% B. a3 q
        1 => '女'
  k. f4 d1 m$ y8 ^3 A# ^2 `' a% r/ H2 M
(5).增加好友 3 L1 c% z7 O& R
  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 ! k/ Q* B* Q2 e' m0 Q
$ _) p# }; M  [9 d; t# Y9 L
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
5 ^5 Y2 U3 c8 t! A2 c     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
$ m  _& V$ P  F5 M: \6 n+ E     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
- k$ q0 a$ t3 N1 j) h) P     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ! T1 M  J2 W' q- [4 U" r
     NULL(UIN、UN为字符) : @( C3 t+ d6 E, C- H3 Z
, g* _$ E' Z0 `
(5).发送验证 5 e' B8 {, G6 h/ i
  说明:1、如果你加对方为好友,你需要发送验证 ( F- ]8 h! n4 P) }) ~, G
     2、对方加你为好友,发送了验证,你要通过或者拒绝 - ?, x# i1 z8 h) e4 B2 f+ n
     这2种情况需要发送验证消息
0 \; V7 x! R9 k2 m# F
6 O! G) i) L3 U! J2 Z. F1 c  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
. o4 B5 g4 L5 i3 p9 K3 e5 V  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 . v! R7 z! t+ d$ L0 f+ U) k' Y" s
2 H/ x9 P. ^+ o: ?+ o
  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 6 W! @  ?1 o: {- w) c
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*) ) t8 ~7 C. m# x8 `% ?2 s/ [0 H
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)   w* L4 f! q- p6 \) Q
     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
  ~# ^9 I6 K# }  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
2 i" A1 b- i. y+ _8 z+ Y& X9 t+ z9 b1 U# m4 ?8 e6 y
(6).删除好友
) I3 A: d4 U- V, ]0 Y6 J  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
1 I  _9 T0 A" U) d! c+ X" U* I7 T, Z( V% f2 H5 K! v
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) ; ~# e& ]1 Q0 g; o& G0 J& T8 a, R
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
* n' A! `: F6 x; Z  k, w     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
# r" w& b; f; T( z6 ~     NULL(UIN、UN为字符) + _. |9 ^( c2 m! ?5 t+ i; b
6 f$ N+ v" }2 R8 m
(7).改变状态 3 l# i4 u0 {( F5 ?$ y$ t
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 & F: A# H& M6 q- Y5 t* r
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
7 t; |' C1 B4 ]: p# c, G. g+ T
# }0 i. k7 J7 m: q1 r  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) / k  g0 X4 A$ o) j
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
5 a8 R. [, r9 k     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) + _0 h3 C' s1 X6 m. p) F: k
     NULL(UIN为字符,ST非法)
0 C9 e( I4 {  |7 [& `" T* y7 ]
: ?) S% ]) @2 j- C; V  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。
* F% O3 ~6 t$ `4 l# _       同理,当你的好友改变状态,你也会收到一条系统信息。
0 J% I" e. r+ T; r/ i) Q4 l# [2 q* @4 p9 B/ l
(9).获得消息 + h8 I0 E8 m8 X! S2 N7 g# k
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
3 {. X- D; H% R" _
9 [' e8 J/ M2 A/ h, e  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容)
8 J+ x% A/ P+ K0 l1 }; [# h     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
. k0 C% O/ N8 H* K4 A     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 t' E, F  _8 S6 A3 _0 y! p' R( L     NULL(UIN为字符) " i. S* k6 K' J' ~9 i5 r6 F; @
  说明:关于MT:
6 H4 I, J9 I3 J2 v9 Z       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 # O, {/ f7 S) T( M7 F  ~
     关于MG: 7 a  y5 G/ q3 c0 |) i8 |
       当MT=9时,MG为用户发送的消息内容
8 r( ~7 x/ M$ R/ L1 s1 Q       当MT=99时,
1 }0 F- R: S) o% Y         MG=10(QQ_STATUS_ONLINE)表示对方上线
  t" r8 W7 P5 d- o: s7 j, S7 I         MG=20(QQ_STATUS_OFFLINE)表示对方下线 . o* B/ I& v& ]* Z2 K
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
) Y. ^. E: l9 P1 a# w! Z       当MT=2时,MG为对方请求你验证的信息
, K9 U2 M9 v) @* A       当MT=3时,表示对方通过你的验证 6 U# I: P2 ?4 n- @
       当MT=4时,MG为对方拒绝你理由 / m, f& t/ g9 \/ K4 l, }. j( k

3 g4 ^# P; C8 |/ S1 J2 C(10).发送消息 , G& T2 Q! f% _% x3 d4 Z
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 1 g3 D! q4 z1 a1 |9 H( Z; x

) o; e8 g/ a- |  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) # o5 ^- g9 i! v+ E' @* ?. a# V4 Q
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 1 q! o/ M" [9 W; H* H
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) : L* D1 L+ w( B: s' L( S
     NULL(UIN、UN为字符,MG含非UTF-8字符) 0 ~( l5 u; @: m9 u
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: ) @2 \5 e1 R1 S- _
       你俩互为陌生人,且对方没有和你说过话
( L; I2 Y: A# u* `$ O# {+ o       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
8 q* `$ P: B' s# t7 ?" z     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
( D) B; l" r+ i9 k) ?" [& U: X! m6 o     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL   ~/ K( B. T* `1 J/ k7 |$ t% x

1 L! F" a) j: B(11).登出 & V3 o8 B. L' W6 g4 W
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号 " r5 I; F) D; t( o6 D3 A

. v) w% y1 L* X- U! k  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) + f" Q# p1 _- ?: L  [. l
     NULL(UIN为字符)
( K, D+ Y/ x, {% F7 s7 T4 S6 Z) k$ s# |  n8 G0 r
5、总结
$ D3 f' _! y7 r' U& G0 E) @
& E( X, X6 G, ]' W  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 8 G3 m$ h2 I6 d+ H' a2 h
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558 : t' X3 o& i; |) h
  本文撰写时间仓促,难免有误,希望各位不吝赐教* B) {1 e# H6 B6 U0 d
! h. v, {" F) [

- l0 D$ f- v8 D  ~1 M: H" _. NTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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