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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan % U8 {" r; u8 N$ E
日期:2005.8.21凌晨 ! h7 ~" n- u  i7 l& i
联系:QQ:106814 Email:hackfan@vip.sina.com ) H5 G+ p9 C0 L' y) B

* B0 _1 k7 {5 d& O$ O1、研究说明 * C" K6 j% i2 F! N
' D  V9 I# ]8 U, V; t8 I
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 2 v( v8 p8 e; }2 b2 R
1 G0 i0 S; E, Y7 [& H) z
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
7 F8 j6 L! h; U) I4 A: a8 h/ R6 o' u, o; _% K' U, a+ Z
2、接口说明:
+ i% X: V) M5 d6 E! q' b; L  v  G9 b( j2 K+ p9 Y+ K0 e" ]
  接口位置:tqq.tencent.com:8000
- S9 r' B. @0 p6 _& y3 h  通信协议:HTTP + O  z& B4 _) Q% L
  数据传输方法:POST
, M- G2 J; }. @' t3 z  HTTP请求格式:
' s- S9 P5 R6 V2 k1 Y
) N5 o; J9 S5 }: X. ]: S2 hPOST HTTP/1.1 ! a/ Z* c  @! w8 I- m/ L
Host: tqq.tencent.com:8000
: d7 A$ B* K, R. y$ [, E8 yContent-Type: text/plain; charset=UTF-8 9 R0 J  i" _. M7 F! V* j% C& b
Content-length: 长度 9 j; x" h# z8 d' A9 Y
Connection: close
- b0 Q+ L4 u' o5 [& O2 K( c
, C  L6 l: K5 G8 b2 s' U数据
- a' i- K! s: Z6 F% b
2 ^) s  C" M+ K  v! l% g4 U) C: e5 l  其中长度为 数据 的长度,数据的格式: # y4 T; }, P0 Y4 g" L( P3 v
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... ( L. R; M* n  E: Q6 r7 `
% D+ J: u8 B6 f( o3 s; f9 |
  以上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 q4 ^1 Z6 F: p; _; C% l" `
  }: Q+ u- h* Q) R* b$ L6 M4 Z' v3、研究方法:
' L" _2 U% z, f1 F2 B- [6 i
  z6 v6 D+ |+ v$ r0 C  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
' l, i+ h; x5 v. Q0 f  下面我公布我探测的代码(PHP):
  1. <?
    + J) e5 C( p& t. b
  2. $uin = "QQ号";
    ! ~, S7 t4 c# K! s0 q, |
  3. $pwd = md5("QQ密码");
    - L/ U3 O4 T3 n& M
  4. 6 I+ G' A4 y- `& `( [) d
  5. //登陆测试 2 y  V6 ^3 E/ `) i
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    # M8 K7 X5 r9 S2 {4 X, n+ Q/ l
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 # {& u0 {5 k5 e; D+ B2 A, i
  8. /*******
      \% x( w0 E3 z1 y
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";
    # t: F, f6 S4 q' k' X* n4 p
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    1 ^# u, }4 n1 |; P, W
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
    8 j8 w: g/ p4 s4 {5 b3 d5 {0 T
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";   v  X% K# `1 b, H5 Y7 `
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; 5 N# z4 l2 w6 K: {  I& P3 A; r# n# d
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    5 S/ ?9 A: D' N+ g
  15. *******/ % E# V$ J2 V, T0 \3 R$ ~
  16.   n$ j% m4 m( r5 d. M( u0 s( R
  17. ! L6 I4 T) O& W6 Z1 Y+ X
  18. //得到好友列表 % ]7 z) }' w/ Y. w% d) d
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;
    0 H  }5 V# {$ o
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; / F% F. R- D: I
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 2 I. o6 R4 T2 E
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    / x$ e% Q- f  }" b. \
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    : [! X  N$ Z7 I7 I! `
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; : T8 m* r9 Z9 Z! e) ^6 Q8 g: D
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    9 J1 o* c( }. J9 L6 H4 b
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ) [6 E7 @; Z* ^- i  [, X
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ' O$ C4 n2 N2 r* O
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    . P: e% R; P3 _8 D& o# ]' y
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % |! C4 t. M! {  e
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ' r3 p4 \( K4 ^
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 1 g0 Y" P* V- B/ s
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); # y+ B: \: D: s6 R
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; # z( a3 ~& r. t2 I( n, j

  34. ; G; n' K1 V  M4 E
  35. //得到在线列表
    7 \$ w0 o# d" \8 K" y- l+ f
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ; ~- @* I, X. t9 J  I
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    7 ^7 L; R! |- N  O3 ?& O/ F5 z- C
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    ; ^& v0 @& U+ ~7 m
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    5 I) ?' Y7 p6 z# G
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); $ r8 J! _/ a" [3 r: O4 s
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    - f0 _' g9 I) k9 m" R( ^' i
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    8 P5 ~; B- m: O0 o9 |2 ~6 p4 F/ ?* F
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    - A$ N7 F+ n6 a. C( U( p
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    " c  ^' g6 [; g4 s+ V0 ]
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % p5 k1 y0 j3 \  d0 C. f3 x( w
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; $ n9 v2 x- x8 V# J: Y7 W# N
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ! }8 {* {5 D; ^9 _2 i3 |
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ; O/ D( P7 `$ W# t1 ]3 V! N; F
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    + {& M  X8 K' }! |' D
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    9 O# _- t* B$ k( r" j) H

  51. , e) h, V4 p0 V7 r* G
  52. //查看好友信息 8 r6 V! R2 L2 D, K- a
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    ! w" a2 u6 ?- u- l
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    5 r9 L0 j. [1 W
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; . B, N! u  o+ ^; y' `, C' q# S' v
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; ; v+ `; v5 j- ^: H+ i0 V2 H! F3 [
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    9 Z) [9 V3 |9 Q; H; m+ U: n, E- B
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    # \9 q# H* \9 S, a
  59. ( R* H" A. E1 Q- V# T9 L
  60. //增加好友 " u9 k! o4 M8 L0 _4 ?: S
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; ; c+ e3 x1 F4 k( X- b, _4 c! q) Y
  62. 9 p% K" D' L9 s2 K- k; x# l4 ^7 {& H
  63. //发送验证 ! f  g! F1 a) h# ]* d. ]
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; 6 _  |8 F" M+ `: R) k
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; 5 M, P7 ]4 ?6 Y* p( W* P
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; 8 ~- A9 l- f  \6 i+ N; t8 v% \+ t( K
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST"; $ c% {$ [( N. i' k5 r
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    1 {( O2 V" Y2 O0 f% c) R" Z
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    6 P) `2 T3 X. F+ M

  70. 6 K1 H, o5 d" _- m
  71. //删除好友 * e' {0 M- R! z& f# C4 I1 @
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; 2 q: W0 X; O. P% U- W( ~) b
  73. 5 @$ I1 T% {" m5 c% l' ^2 F
  74. //改变状态 1 H' r) H9 p, x2 x$ P) A# r
  75. for($i=0;$i<=60;$i=$i+5) 0 h# S" X; ~) [0 y7 z
  76. { 7 V' T/ S/ c! b/ U. p( W
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; 6 ~& b- s! y# I, K, ]$ b+ f
  78. }
    3 |% o# ?9 `7 t# K7 V

  79. 6 F) ?( q* ?( K3 B
  80. //获得消息 ' Q1 ^( N7 e# I' Z! w$ N
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    - T" I" j* \; I; n) v
  82. / W2 w8 w8 q  A5 h% `9 u6 ]/ ]) F
  83. //发送消息
    % @8 ?) n) I1 Z' N, m& d& c- f! x
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; $ i0 P3 t$ B- C9 L# c
  85. 7 T0 q& ], Q% u" h) O8 ^
  86. //登出
    9 J6 i: q. U: z: d- \
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; ' g, L3 J9 v9 n$ _  r/ i4 |
  88. # a) i. T' O3 `8 q& o' z
  89. $file = fopen("p.txt","w"); . m* {5 v2 o: f! `# p
  90. + f" S0 r* Y7 I, w3 z/ }
  91. foreach($poststring as $k=>$v)
    + j9 \+ w5 v8 ~9 h
  92. { 9 C& B( {6 l" x, d! R
  93. ss_timing_start();
    & E7 i0 a3 g6 Z: f! Y4 p
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  $ U5 o: v6 r1 c$ w& {& r

  95. ! k4 K/ }0 ~, K) Q4 c$ C) U
  96. if(!$fp){  ! ^$ w, x2 c6 ^( v, d/ J- a* ]
  97. //error tell us  
    / l  H$ v$ w. j; m( P
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    + v2 X/ |  T  @1 [" y  }. d2 L. d: {9 F
  99.    ) c1 `8 J4 w- w9 f% }
  100. }else{  2 w4 C( \8 g# s2 A; F+ C. M
  101. 8 j/ ?2 I, d" Z6 E! z
  102.   //send the server request  
      Y3 ~0 G" m" r4 x  o1 M0 X
  103.   fputs($fp, "POST HTTP/1.1\r\n");    z/ R% ?7 \& z; [
  104. //  fputs($fp, "Host: $host\r\n");  
    9 n* \2 W! [3 ~3 K; Y( N0 ?
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    ( X" {; U+ ?1 M+ p
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    * \( l# P4 m+ V/ I4 V' S
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    9 H5 u& w7 `  {" _2 V
  108.   fputs($fp, $v . "\r\n\r\n");  " x* r3 m9 m. M' p& r) S

  109. % p& K$ y6 X# B& k% E4 n
  110.   //loop through the response from the server  / x/ w: C" e& r# I3 T9 i
  111.   $res = ""; 5 D2 `: p9 Q+ O3 G8 s3 Y1 I. \
  112.   while(!feof($fp)) {  / c% R  I# o4 b, `# Z/ c
  113.   $res .= fgets($fp, 4096);  8 P/ C: v7 z! z, ]& l$ A9 G
  114.   }  6 e4 Z) C: |4 T
  115.   //close fp - we are done with it  * j: x, g. i+ G; t1 f- z6 S/ ]1 g- S
  116.   fclose($fp);  + G0 g; U) Z) @. @: w5 x' w

  117. " m0 J) r( z# @) v
  118.   $content = $v.chr(13).chr(10).$res;
    : J2 q. f; B6 y4 w9 F( o) R- L
  119. }  
    % F( Z/ i# S/ P
  120. ss_timing_stop();  $ p$ V( J' @8 E
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); . b8 U4 E( @8 Y' D
  122. fputs($file,$content);
    5 ], m  c8 m0 ~8 y( O; W+ M
  123. } 5 h. @* e: |$ @
  124. fclose($file); 8 k9 `! T0 u9 ]* Z8 T  e; w
  125. ?> ! ~$ Y; C( v6 S& o& `8 ]
  126. <?
    4 o3 G6 ~0 B' F6 _2 Q' j
  127. function ss_timing_start ($name = "default") {  
    " S. U( D; @2 d( j- s
  128. global $ss_timing_start_times;  0 T1 \& J* P! I  W9 z* R
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  & Q3 K1 T- R" W# [3 u
  130. }  
    0 z1 f' R" U+ b/ Y
  131. function ss_timing_stop ($name = "default") {  
    7 e5 E/ v: M5 Y+ G, Y7 }& N: m# N
  132. global $ss_timing_stop_times;  
    , E  t+ c# B/ H  }1 c; h
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
    : d. h+ B1 g  f$ ]9 D4 O1 O+ @
  134. }  & q$ Q# ]; W# t* }, c- V8 _4 l+ a
  135. function ss_timing_current ($name = "default") {  ; t: h- h, w+ S  _* e  D+ R  c
  136. global $ss_timing_start_times, $ss_timing_stop_times;  % Q/ {! F$ Z3 c' p7 v7 w! w& v3 d# \
  137. if (!isset($ss_timing_start_times[$name])) {  
    1 a5 e5 i  S3 F- `$ X- m
  138. return 0;  
    & D$ Q+ N' b0 r- x5 e5 f
  139. }  
    * p: V& w, y" g' f; G5 d
  140. if (!isset($ss_timing_stop_times[$name])) {  
    ) ^) e% l. @* ?1 }. W
  141. $stop_time = explode(' ', microtime());  1 }& l6 g$ t/ z" v& s
  142. }  
    * Y" t6 H1 M0 S) u  i0 g) H. W
  143. else {  
    ) `" v& z& p7 F+ d! d' i- E
  144. $stop_time = $ss_timing_stop_times[$name];  
    : }( d3 I6 U5 }; y
  145. }  
    ; A, C$ m+ r" P) C
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    . s( r- o; {7 D+ I* V" o2 p
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    / v4 u  K" `- b
  148. return $current;  9 a4 r" E2 i% G
  149. }  
    % k+ l! }" a5 y$ L
  150. ?>
复制代码

6 O  y  y5 C* h: z4、研究成果:
  g6 X& C( ^) k
1 z. R. \  ]( F; a6 ~! w( k7 ?8 x* a(1).登陆 2 |9 v+ @( u" ~' |3 k2 D
  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
5 x! _, m4 ?- _8 A- g  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^
6 L4 U9 a9 K& d& E4 d: ^5 P+ }' D+ F
4 x0 E8 [1 ^1 J7 S  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
! K4 k8 J& K3 t6 I* v! _5 X" Y2 [2 B1 R  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; ; T* i" D: ~* o
     M5这个参数的作用还不清楚,但最好为1。
9 |; E$ u7 S# m" v: u( @     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 8 V! c& J8 m) ^( R( z3 @% l: ~2 _: l
) o0 C) K8 U4 A9 ^' X+ g, c
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
2 b+ W7 n4 s8 W) @" _     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
# d) M( R" h% w; u2 Y1 T4 B% ?     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
, W8 K0 w* c9 e4 G& B6 ?: e8 r     NULL(UIN为字符、PS为空、LC错误) 5 q0 r5 k6 k* @$ q2 t
3 K" W& y# ?+ P6 a- J- w
(2).得到好友列表 ) T7 ~# s2 x) j5 V
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 8 @8 ]( T. O/ b, u1 W
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
" y' D) i/ h/ f$ U) S, p
0 g) S5 c8 \& u3 W& U: {/ T8 J  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
" q( Y. Q) }4 H9 Y& G) ]1 `     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
' p# H% w5 G. }  q+ q0 H" n     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 9 j' \  s0 A; ]0 S6 |9 e  G
     NULL(UIN、TN、UN为字符) & `. E* t2 ?9 g) S+ k8 {. @# ?

5 Q& f0 u- E. i8 \(3).得到在线好友列表 $ Z3 p! E8 W0 ?% b
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 ! x* O. t: l) ~' t, j$ b
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
8 ?" }; I4 r. D+ h' I
! W; t; Z8 I& A% T  返回: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的值用','分割,分别表示头像、状态、号码、昵称) ' [3 y9 u' _  _' y, f
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 0 K" v) h, m6 O
     NULL(UIN、TN、UN为字符)
$ @* ~4 G0 t5 K+ k8 O& f' ~! Q- x! G  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;
: \$ _& g8 e. ]8 y8 e0 H     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; ! K) B+ g' N, n! w4 q
0 p! n5 T# L% ]$ `. e9 h( e3 O
  特别说明:当参数TN=0或不存在时,服务器返回:
/ b1 }" w% o  ?) EVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 * p" s! J5 u6 D" r) e: F
HTTP/1.1 200 OK
) M- q; ]4 j; E( e" GServer: tencent imserver/1.0.0 & o1 d+ p9 o) @( a4 ?6 u+ s
Content-Type: text/plain; charset=UTF-8 * q7 Q2 O" `5 p) Q
Content-Length: 56 8 a! l8 _# c8 Z8 K; {6 n6 O8 |, l

5 v5 x1 b" }' Q5 Z4 L1 |' DVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 & p0 `0 z( Q" y5 ?. S
HTTP/1.1 200 OK   n) h3 d4 F! Z1 F1 S( R$ B
Server: tencent imserver/1.0.0 8 M5 @2 @1 K) u/ g/ f0 f2 @
Content-Type: text/plain; charset=UTF-8 . F* B# n; A5 c4 c3 h
Content-Length: 77 8 w8 ~5 C! L- u! }

" I* c7 p' m- ~. x" ~1 z  b: n( h" {% WVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
; \7 a# L8 W0 \7 ^( r" C* C. H  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
( m8 l9 p) [) O' Y0 j1 A6 g' ]1 ]+ w% U% t$ D5 S
(4).查看好友信息
7 `# n& A" _* x" {, ^8 w+ W  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
; K" s  f2 F5 B. Z  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 5 ^2 N$ k* d  d6 n9 t% e7 D

# H( x$ T* t+ H3 H  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)   J. A. Q* G8 h4 Y( Q  z7 o, h6 a
     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=学生 9 ~: {8 I7 Y: E1 a
&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
7 t" u- K+ z( r# K/ z: b/ k  e0 V1 s好(普通查询)
9 y9 g9 N& w" X     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 7 W. \* ?9 j& |, ]0 j4 w
&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  8 l3 L9 d1 K/ _( b1 r
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
8 g9 `8 p7 h: A( n8 W! h1 Q     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) * c- i) Q3 I; M: }4 h* y% I- D8 }
     NULL(UIN、LV、UN为字符)
$ o' R4 p$ @% H5 [6 c. ~, m( ^
0 P6 w% ?$ y5 D6 t: X: ?  说明:AD为联系地址 % P9 K' r1 g. J! D. s4 n
     AG为年龄
0 h# U8 Q2 b* l( |! S( j4 ~     BT为血型 1 }8 r# F/ J( _  ?8 O& o
     CO为星座
4 D( ]" q, X( l/ b( g2 n' `     CT为城市 & Q8 B  g. o  C2 s& f4 E4 x2 W0 v
     CV为未知*
. i6 _! i6 `' ~     CY为国家
* S% Z4 q% p) X/ Z' ?7 w     EM为Email 5 p- N6 a0 z3 V0 |. f1 C
     FC为头像 2 R5 R) O, e/ `5 `% s% s7 S
     HP为网站
9 G; `1 _! m9 H7 F* E2 l; _! T/ z     ID为未知   @- v  G3 z; J; m; t" ?2 a3 v
     JB为职业 1 t- ^2 f1 I3 ~/ Z6 i
     LV为查询代码(就是发送的LV) * [3 N0 m0 q$ N; ]' r
     MO为移动电话
1 q4 @0 Y1 K$ x& R     MT为未知 / [0 w/ A' s4 R2 G
     MV为未知 # B: J; O/ }$ t$ `7 E3 S
     PC为邮编
, W% P2 c2 x/ v' }( M     PH为联系电话
4 u2 Q! ?* F2 m' m     PR为简介 - ?% Q: X' ~# d4 G; ~
     PV为省
% G) G8 b# Y" h, G. k& o  J     RN为真实姓名 % d& s+ D, U/ r/ z
     SC为毕业院校
- u0 {4 D3 W8 ~. L4 d( |     SH为生肖
4 c6 M! B) ], d9 ~6 ^. j/ ]     SX为性别
) d% `& j0 u. i0 r6 V     UN为QQ号
# O! _. h9 _$ \( ~3 f     NK为昵称
1 u5 a8 W& ]9 Q8 B% W+ z! ~9 K3 m, A& c8 G
     血型:0 => '', ; D+ a0 A7 a+ x' ^, M" V  {
        1 => 'A型', # w! ?6 E, k6 K! q
        2 => 'B型', # B: }2 Z5 w# L1 z) y
        3 => 'O型',
$ I$ i$ {, a) A: t5 u        4 => 'AB型',
% M' a8 ^5 `# {4 |: h, w        5 => '其他' & K2 Z9 o4 W. o! Z1 ]

9 j* x# n- N7 D5 e! S
, c9 Z* H% A' A6 L  }" C) N     星座:0 => '',
8 W8 b7 ^1 P- Q& p: U" F) L1 ?        1 => '水瓶座', . q  Y, r% ~3 m
        2 => '双鱼座',
! R$ f) X1 U5 D" P$ N        3 => '牡羊座',
$ i9 _  V4 s/ m! [        4 => '金牛座', . ?  ~1 ?$ d! I2 V
        5 => '双子座', 8 e# V; b# Z% i) r8 W) e+ b
        6 => '巨蟹座',
: Y( S( |  b0 A' y! Q        7 => '狮子座',
* l, f1 c) Q* b/ d$ [2 S% S& L% Z        8 => '座', " e; P' M' N2 V6 b7 `( P
        9 => '天秤座',
8 S( l+ u2 A# G$ q, \) W        10 => '天蝎座',
9 |  o6 f7 b* w! x- n. B8 J        11 => '射手座',
/ {6 P; a: Q. _$ t* Q/ j        12 => '摩羯座' 8 {+ \8 X6 h/ O* l7 K

3 G/ N; G; ?$ H, `$ n" M     生肖:0 => '',   e( h/ j0 z: M; q' i$ i! T* }
        1 => '鼠',
3 G7 U$ A3 D7 d5 {        2 => '牛', 6 Z7 N: x* H( k5 u( f5 x
        3 => '虎',
$ q4 c' ~4 q  f) I- _        4 => '兔',
1 H; X5 a- W5 N( H8 H$ p        5 => '龙', $ m1 C2 P) |( _/ |1 h
        6 => '蛇', 8 A6 y+ x' A' Q4 a2 R6 P+ d5 |# p
        7 => '马',
" N+ Q% ^! @+ U' f0 `5 E" m2 }4 D        8 => '羊',
) O8 q9 S) E' K        9 => '猴', ' J1 p& J. y6 p; L$ B* \" ?9 d
        10 => '鸡', ( s: c! w+ H+ n1 {+ w9 S! a
        11 => '狗', * z6 E7 P2 N1 a: L. G
        12 => '猪'
* \' J* ]! s" p6 L/ |# Q* f9 M
- N( T3 P4 E/ H- T6 S     性别:0 => '男', 7 n( k: ~# x4 z0 @, U2 n
        1 => '女'
; _& M- Q+ L& E; o' K4 F% ]4 ]; q1 P8 m* M% t1 [) G
(5).增加好友
4 i, k& k# o- ?; |  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
$ N0 t  }; Y( L4 t( ^
0 Q. M* I5 `1 ~1 G- J" a8 ?# _  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) 2 I' [  |0 j% Y/ O: h6 G- ?
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
# Z: r7 d, s4 I0 {1 c7 l% W. P     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
5 p  ?6 }9 Y& j: ?( ?     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
8 i$ H6 N: `& l0 C9 a     NULL(UIN、UN为字符)
5 ^0 V, X  R  H7 s
+ i9 t- E' W1 Z$ J* P# x0 b) A(5).发送验证 8 i& `" R# U( m# K& i/ E2 E
  说明:1、如果你加对方为好友,你需要发送验证 % Q0 x( L1 U/ w+ G( Z3 Z
     2、对方加你为好友,发送了验证,你要通过或者拒绝
1 [0 D* `7 i: f* M     这2种情况需要发送验证消息 3 q  R! Y: b$ b# @- Y

; I' ^, e+ o2 w8 i) e3 ^, H6 G  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
. |1 C0 M5 N' q7 g8 O% t; o, J/ K  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 ( D+ w# C8 s2 ~, A* u8 w/ @

2 c& f. Q8 \5 Y  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) % t; A) v4 I: }2 E
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
+ H8 t& H) z' x4 G* X; T     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
" K  }+ W1 d+ q     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
1 A2 L0 T$ A' C# C  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
/ ^( B1 f2 t4 E! v! q3 n6 a# w6 O( d6 g, O
(6).删除好友
0 B) s9 S' J" D/ D0 r' P* T  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
+ G9 f9 N3 l6 o5 v4 k& M7 k# I2 h9 ~
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
6 ?) m. ^: S2 c( H) `8 `0 s     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
8 n/ }; I8 I" p% H' k4 @' h, n     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 5 ]9 }( T6 n- w3 {( w* V
     NULL(UIN、UN为字符) : C4 q/ q! z% W# l1 G

& c6 q* z0 J. z6 Z- x5 s8 G) t(7).改变状态
8 i4 L( {$ T5 |$ M4 O! Q& R8 H8 |  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 - @* F& |- s: `' H
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
$ _' k" |: l( U6 I5 A9 {' @
/ Y) ?6 |" n3 Z# T' x' ^6 P  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) ' P0 x2 h/ I7 b" Z* Y$ ]9 o! c" k
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) % B+ {% T0 J! t/ V  Q( Y+ O
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 2 b0 r$ J. H7 e( w% J
     NULL(UIN为字符,ST非法) + ^3 ^  D3 c6 E) X" j

; O; [: I: q0 u, o6 u  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 / [+ Z( u" E& r+ e$ t5 `
       同理,当你的好友改变状态,你也会收到一条系统信息。 2 o5 l# D1 k; c( O) h6 ~

* P% x( }% U5 {4 B' f(9).获得消息 # P, G* a, p3 s2 T, s8 C/ y* |
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
% m# H. a$ L, [$ H
3 B9 x- x* n; T- K) K2 Q  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容) ! x, Q$ i! A: ?
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息) 0 k* w! m" b4 c8 J# n
     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
# S0 ~9 `2 c5 s3 |) |     NULL(UIN为字符)
/ N6 g3 S; u. e  ]( G, w1 {, V* x: p  说明:关于MT: ; r; H/ h8 Z8 t, \' Q  J
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 6 `: D$ u3 x/ m; H) v3 G; D0 D
     关于MG:
- C  K& T- `) e2 k  v       当MT=9时,MG为用户发送的消息内容 ) Y2 K8 n3 C1 _7 ?' R
       当MT=99时, 3 [" n/ H9 _, x8 J
         MG=10(QQ_STATUS_ONLINE)表示对方上线
: C: ]" X& G9 O( T         MG=20(QQ_STATUS_OFFLINE)表示对方下线 5 h# t  W7 ?3 R  k6 g( K6 s4 D
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
+ P2 |7 K" c) O7 ~       当MT=2时,MG为对方请求你验证的信息 + s2 s* R8 o& C2 j
       当MT=3时,表示对方通过你的验证
  D3 H4 y& _& _3 C* x5 f       当MT=4时,MG为对方拒绝你理由
9 w; P! D, E6 [% w9 u# a7 B/ f' L+ K: a1 u1 X
(10).发送消息
; _4 B- J/ v& X# j3 f  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
- r0 a+ ~4 i+ W2 D0 L# ]
* {3 w7 K4 V) p1 P" W  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
" G: ]9 T$ W6 Z/ P     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
. J2 J& s. p6 o+ w     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 V$ ~6 H' f8 ]) i* i
     NULL(UIN、UN为字符,MG含非UTF-8字符) 0 ~" B" d' x7 `0 J
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: ! X. l2 I, D, l' P4 Z9 Q% u
       你俩互为陌生人,且对方没有和你说过话 7 ^2 ~! G6 Z8 j$ x
       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
/ \0 O) h5 u" v: E  j6 v/ q% T" d( P     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s # h" B' N' g# ]" h' N7 b
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL 2 T2 ?$ e1 Y  c

# D: U" l1 g1 K(11).登出
+ t$ j- F) b) T9 ^& z5 ?, ?  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
; e, }& y! g, {3 B% U4 D: {. r0 b5 _6 ^+ v6 b/ V% y+ b+ Q$ V" \
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) ' f  L7 o, a; a' f$ O; A6 i- {  A$ f
     NULL(UIN为字符) 2 s  K' d. M) _  ]' t. O0 b5 b

- O, d- B# L! w1 Z5、总结   Y3 v: _. ^8 {7 P2 ^9 W

, Y' j4 \$ j: J  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 & d$ R0 B) b- d% ?0 ]
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
& K3 v4 p3 e$ W8 u6 Z6 @2 d6 t  本文撰写时间仓促,难免有误,希望各位不吝赐教
0 q% S( m% ^  L" ]. e
1 ]- G% Q1 `1 I8 h/ i" j/ ?
& D: j' x' ?6 ITrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-15 06:33 , Processed in 0.020645 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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