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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan + x* V' P$ ]; d) C# b
日期:2005.8.21凌晨 " M) C  q& i4 d  u
联系:QQ:106814 Email:hackfan@vip.sina.com 7 N! I. s3 U& u0 T) [3 C

0 ?8 f2 f+ G& H) A& |1、研究说明
: f) Q; _! H7 \" t1 b& |$ O, [# T& t& U' Z5 S4 u" i
  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 3 y' H( _$ K, t% A

+ ]5 l( \  [! K, _. j  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 ) E: O  Q5 q" x& o* U5 V
9 G! E+ I% E! A, L. Z5 j. v
2、接口说明:
6 b" g5 |0 E# c3 K" W6 Z0 e% G7 W7 y* g
  接口位置:tqq.tencent.com:8000
9 V: s6 v+ C9 R2 _" N; j  通信协议:HTTP ' }1 {$ R$ p1 Q: f$ E( \* x3 q
  数据传输方法:POST , e; S5 d* b% D$ F+ Z
  HTTP请求格式:
' v4 e% r5 C0 I4 A" X
+ {3 E) F' n) L+ k) ^0 mPOST HTTP/1.1 ' N+ P, b+ B" f
Host: tqq.tencent.com:8000
6 y7 S" R0 c* g  X# n1 r4 qContent-Type: text/plain; charset=UTF-8 2 ]9 f8 W& _- T# D# e$ M: ~+ W8 o
Content-length: 长度 " N8 Y9 a6 f0 W% R  J
Connection: close " Z1 j3 p* I( U9 n

( _# S# w. P; t* R0 g) x7 \数据 # T% ?$ R7 c0 I9 a, \: g
1 l1 Z* N+ d3 \( \
  其中长度为 数据 的长度,数据的格式: 2 B3 V$ D2 V& ~# E
  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&....
! M) O8 |: k8 d+ {
& ^. [9 R9 W" X, |4 a  以上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还需要不同的参数,下面我就公布我的研究成果。
2 M8 M- t5 |3 C! L& m
$ l" Y+ X3 w) K4 G9 m+ `3、研究方法: + r- T1 S5 w; [( c9 h  D0 D( m

5 R4 I% o  d+ P) v" o! F% c: v7 x  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 3 m5 A8 f+ ~9 U8 X! O5 \
  下面我公布我探测的代码(PHP):
  1. <? ! r7 c7 |% H5 T0 l
  2. $uin = "QQ号";
    4 E0 ]1 s8 L0 C/ e1 p5 A
  3. $pwd = md5("QQ密码"); ; O: f* `; D) w

  4. ; V# T# C& N$ u( L8 I: m4 n
  5. //登陆测试
    7 z+ K( M3 k& O: {; v) W! h
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 5 K! d1 `( k$ e8 k
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 + A2 |. H) h8 V- e/ w
  8. /*******
    5 V+ l2 m; n2 A6 D" l- J; a' _
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; - O+ k# n1 @8 m' l
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 6 o7 a  g0 \8 z0 J
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 9 [* ?/ B- U. f' D
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; 7 _) i2 B1 b2 H9 E
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; / u2 p1 Q' u- I
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";
    * Y  @/ d* ]- E) h8 {# T0 v
  15. *******/
    # |; w+ n. i! b; J
  16. ) v$ p) o) F( k8 y" {4 ?8 H
  17. ' b' R; G( `' z3 j, Q
  18. //得到好友列表 : S: U9 \. e9 _
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; ) `$ f' W' ~' Z6 l; q4 K9 V" o6 [
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    8 @* f5 |& y% F
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 0 ~3 O5 ]/ f2 i
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 3 d! B  y& L+ o" l+ w7 T
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); ) ?: X2 h8 e$ b; h
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; $ e. x& g! R8 D* j% i8 O6 d# y
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
      e  X4 q- r% g5 i( x9 k7 Q) F
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 5 v& I- U& m. {; w9 n% v, r4 u
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % ?6 A! j6 z* {0 E* X+ r: P% ]
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ( j; x6 P/ G0 O# l6 `
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ; b/ a& z0 N2 e* a/ d# o
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    8 e% B$ z# d( Z7 E
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) q4 E& Q4 Z! h) v) h  x! \
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 7 t" a5 V* d; h: P7 e8 u1 F
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; " C' V! z+ M$ Y1 I/ o. D

  34. 8 l- \9 x* {' l8 d" ?9 q9 {
  35. //得到在线列表 ! l! ~. ~: Y, c# {$ R) l5 N: y' a
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    ) Q0 ~8 J5 k3 r- `' ?
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    $ S+ h- T$ X' _' G0 X8 n3 q/ t$ _
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    - L1 E) c$ i, p; N$ C" t, n2 I
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; , O' W) e" Z8 x, b2 w! M" \  I$ V
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    ! x' {. J4 U7 o& A; ~" K' X) V
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; / K6 e# I9 P  J* T, y
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    1 p, K: e) j8 O
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 2 z3 J3 R. m; V
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ) L' t& ?9 O9 k" D6 o
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ; g2 a' P0 T, o7 b5 F% d
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; ; b# [* e4 o% D4 D2 }# [2 i: l/ |
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    0 z, J: g/ N. T7 A1 _$ i% ]
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 4 f  o- Z* g7 j6 m+ Y3 D& [
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    9 N$ |0 G3 z! w& {
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; , C; ?/ X4 D; M) w2 @3 \8 M( W

  51. 1 V) `. `+ y# y
  52. //查看好友信息
    5 _! T0 [5 c6 s: h% [3 w3 z9 _
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; ; Y4 L; v8 y. }/ F: S- E! G0 D4 l
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
    . \! p1 o7 @& N6 t+ [; G9 k7 Y
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    " M/ h9 H3 O$ x% D% E
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; 1 k6 J- y; ?6 n) ~
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    0 ~+ k& z1 ^  E, G  K
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814"; 7 Y8 A' Q, x1 }1 ]/ r2 _2 w2 v

  59. - d& d: |' ~7 R9 P
  60. //增加好友 ! j& p' h5 L$ j* G( G
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    & O5 J6 j8 y3 s& G7 ^3 ?) x0 t
  62. - A" j. F3 ^/ A7 X2 w$ A) }
  63. //发送验证 / [. {. h' b& f! o$ r. F; Z; Y! D) O
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    , X' Q4 t" K  i5 O
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    ! L  C, \" m; x" i
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    0 f- _( p/ o' W' Q
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    . ^) ?& @* a, {7 i; n2 ^8 X3 q
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    1 v, ~7 k4 d. F; J/ f5 M1 R
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    + K' o" L8 n/ l* }) G

  70. / B: ^% l# F, L# w
  71. //删除好友 0 J% n$ b0 d5 ?- E1 ?
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; . o# r6 f' O) P2 y

  73. & E4 L1 {& D- ?& }; Z
  74. //改变状态 1 C2 ~: D1 n  \2 s  `0 [' v/ L: v
  75. for($i=0;$i<=60;$i=$i+5) - k- @# _0 U" B9 H; `- C; R
  76. {
    ' {9 D9 r& a# O% s  Q  L
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; : ^, J- l9 D, i7 ]1 f
  78. } # _8 x/ c# D" F" r' t5 e4 E! l8 U

  79. 9 t+ b* r% {# Z: i+ X/ o
  80. //获得消息
    2 |' j! H; B# p0 Q+ D& w
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    , l$ F" w) B- g" Z( P' b

  82. 3 R/ k5 |1 A- n) [5 X
  83. //发送消息
    ' D8 `. A0 v$ U0 g8 E5 }5 ]; t. |
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    3 K0 Z9 z- d. Q
  85. ; [: E+ \- h$ h$ e/ m
  86. //登出 + |# b* F9 F6 f  j; c( Z' g
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
      D+ ^  _3 i3 N  I  m

  88. ! o+ M. I4 n; r1 n% L
  89. $file = fopen("p.txt","w");
    ( T$ p* D, l! F- ]. ~! k

  90. : F/ g9 @5 m2 r% o6 Y" [) m
  91. foreach($poststring as $k=>$v) + f! T" d# Z+ j( c2 k+ n
  92. {
    / n3 S0 _, k1 d$ ?' z2 Z
  93. ss_timing_start(); 2 k# z. ^0 z: Z. \2 g0 n/ A
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  
    5 G' l, X" a# O" P( S) @" n
  95. $ a6 B) L6 X9 J( k2 [
  96. if(!$fp){  
    4 ]& J6 D  i9 D$ y0 N3 S4 K, ?
  97. //error tell us  
    $ }3 ]; y4 _' r5 n. O
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  8 [% V- v8 Q6 a- f' ~
  99.    
    , N& K0 |; n: }0 m: D7 ^
  100. }else{  
    & k" s* S2 L% R8 |9 V4 F/ s

  101. / c' e: s6 H$ [! W
  102.   //send the server request  
    & X5 i% ?% }7 ?' x8 u' l
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    - H; W9 ^$ m. q2 N! `/ z
  104. //  fputs($fp, "Host: $host\r\n");  , q  A+ c" {3 x) f9 S$ P
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  ( L3 m# y) M( O2 R3 T/ K
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  - [& j2 ^' Q( W; S2 R
  107.   fputs($fp, "Connection: close\r\n\r\n");  9 e( U1 X$ K! E( i( J+ u
  108.   fputs($fp, $v . "\r\n\r\n");  
    ! O6 N7 _( U8 U0 o- H3 v2 n

  109. 2 B# q5 e% n) a  Z# ]3 g' A
  110.   //loop through the response from the server  . x; d3 ~; R- i# ]6 f/ a1 K
  111.   $res = ""; + W; G1 d3 I. x' i3 i
  112.   while(!feof($fp)) {  5 B: ~' x' l# K2 Z# [
  113.   $res .= fgets($fp, 4096);  
    ; ?, |8 d0 S. ~; R; P, t
  114.   }  
    3 L3 u- D2 l% T4 P/ k
  115.   //close fp - we are done with it  ; v2 O$ |3 R# F* `
  116.   fclose($fp);  
    3 Y8 K) P1 ]. S2 o# ]; q1 c

  117. & u. H4 [% \+ i" B
  118.   $content = $v.chr(13).chr(10).$res; ( d: }+ p: F' Z/ M% M
  119. }  ) F* T* r) {8 e; K/ H
  120. ss_timing_stop();  
    ( r2 F. ]+ s, }0 }0 u1 ^. E
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); . ]! X& m8 _; T  X7 v
  122. fputs($file,$content); ( w# M9 O2 ?) q3 y3 H" ^7 A% Y
  123. } 8 P7 m- _, ?2 z$ r+ q+ \% X
  124. fclose($file); 2 m2 z7 j) A/ q; q( Q5 Z. [5 m; R
  125. ?>
    7 Y3 j' r0 |6 I+ T0 e& d
  126. <? 0 M. o' T8 Z; A  @0 H
  127. function ss_timing_start ($name = "default") {  
    : p+ C( k- n/ @
  128. global $ss_timing_start_times;  
    " }3 a% y# G, E
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  ! a. B) v; d, }7 v
  130. }  
    ! o* x2 \/ T: D& g
  131. function ss_timing_stop ($name = "default") {  ; k$ `0 M/ i' B6 ~$ d0 h; F; a) b0 Z
  132. global $ss_timing_stop_times;  3 H2 {* b2 s' k( a3 p. G" [& z2 o
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
      M1 p! ]% m' h/ o+ s6 \) q
  134. }  
    6 }" R; k1 a6 O0 J$ d) g/ R4 W
  135. function ss_timing_current ($name = "default") {  ' w1 @2 A4 k0 B9 a; ^% y- N2 G- X' N8 a
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    % S% L% A/ _- b$ o3 ~! G
  137. if (!isset($ss_timing_start_times[$name])) {  
    9 J7 T2 s2 D! N7 ~# [
  138. return 0;  $ O+ X) b5 c3 S! v8 G& ^
  139. }  & W5 S9 {( I: N5 w
  140. if (!isset($ss_timing_stop_times[$name])) {  : R+ g5 Y! K5 ~4 v0 ~( x( @
  141. $stop_time = explode(' ', microtime());  
    ! a/ @' e# I7 V  ]/ C5 q8 X- O
  142. }  
    # T* q/ ]4 v5 e6 Z8 S# }! R+ ~
  143. else {  - {1 {* d4 C( F; T% y( h
  144. $stop_time = $ss_timing_stop_times[$name];  
    - B! ]6 @; w) k: Q: P2 X
  145. }  
    " j3 Z$ ?* v6 N* }. K/ g
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    + Y' o, [+ R; J( m1 j2 {
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  * O* O" |/ L& f; m
  148. return $current;  + ^" Z& r* y& y" `
  149. }  % ^) |+ D$ Q& q: {6 r
  150. ?>
复制代码

1 y% [5 ^+ v4 S* h; d4、研究成果:
& J; ]# u3 k/ ?" ?2 i7 A
6 w/ b$ b  X" S& [6 M* ~6 ~9 h(1).登陆
- K  B6 j; |9 R+ {  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 ( c3 L7 O. P% U1 K+ Y1 T
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^
# Q+ C; P7 z2 C' y/ A
* g7 v+ l6 z. K" ^. C9 R# r  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 1 ^: k  ^+ A6 {7 ~" E! Q: R
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密; # E" [% f, n# F' Y
     M5这个参数的作用还不清楚,但最好为1。
1 f8 x. Q4 A# `8 @. s+ H7 g3 \- ^* C     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。 2 d; Q$ U  u2 \

5 o! G5 Z! L9 M" n0 Y2 \  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) ( _4 A+ v: A: E% u
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) + U; v' i$ S9 x) I4 s
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
( V* A1 p7 ]; B/ M4 Q# _( k: l     NULL(UIN为字符、PS为空、LC错误)
. ?  [* o; i$ `- K
( C4 U' w( \/ u5 k1 f/ I5 X# b(2).得到好友列表
: z; r3 }) s; b  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0
6 a0 z* ^- B" Q# d8 A9 s  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
$ b- \# }# s& j) F8 z6 R9 F& X. s
. r2 i, E' B$ V/ X7 w  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)
* \( @8 m# w1 K5 G: [' k     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)
) b" w9 C* F: ~) g) T- d, N. Y     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 c4 X9 a+ u/ F7 Q1 ]* \
     NULL(UIN、TN、UN为字符) ( v; E4 n2 H& I4 b9 c9 c0 o
* U, i" n9 V# b1 v" }3 w) a4 f
(3).得到在线好友列表
! S: {( e- k) y8 z$ g1 S3 A# G  X, ^2 H! ?  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 , u* }% q: @' L! P1 ]7 x1 S$ _8 S! n: \
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
/ p6 ]+ A( C! [) M8 b/ A0 J, A
8 T+ A2 T: L/ t2 U  返回: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 {" z5 t1 E+ F$ B- u, F
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 6 g" o1 S5 T2 }& q+ X/ ~9 I( g' V7 I: z
     NULL(UIN、TN、UN为字符) / T4 m3 W3 B2 l
  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; ) Z3 x6 T! P- r" b& j
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; , Y% i0 z$ P+ M1 P; u

, J4 a! p2 F6 E% U3 x9 \  特别说明:当参数TN=0或不存在时,服务器返回:
4 ~" B6 T/ ?6 |! ^VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号 , f8 Y! A' V* A8 C( ^
HTTP/1.1 200 OK
0 c8 h9 W1 m: l" l/ NServer: tencent imserver/1.0.0
, S( ]% T" e# u% u! {1 j( XContent-Type: text/plain; charset=UTF-8 : r! Q- G+ `2 d' r
Content-Length: 56   j9 ]8 i- m1 `9 h" S+ T
2 u' Y) l& f- G. ?9 n
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 0 Q5 ]/ K8 R1 F
HTTP/1.1 200 OK
- I5 c6 ^# o# wServer: tencent imserver/1.0.0
+ h' V5 `8 x" M- k8 X7 k( PContent-Type: text/plain; charset=UTF-8
0 {6 F+ ?# c3 W$ S, v  hContent-Length: 77 5 I, z$ V0 k% D' O2 q9 z; X4 n

; L  q6 z7 z/ H5 f$ K, R; c+ ?% L# oVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= 4 r: L1 r0 n" T1 T/ e; D
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
% x$ T1 b: }5 r
& r' d8 @2 O3 c) `6 B% L(4).查看好友信息
! V* d* b% i9 s# _  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 % Y. }- a% W4 V. k, ?. [* b. H# Z
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 8 ?! a; F  z) I. ^* V
! M1 V  d  K. Z2 X+ I
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
! x! F6 L$ A" s  t) A+ b9 {8 t; ]     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=学生
- J* h% K; y/ F  ~; G&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  4 |# `# L8 k2 [+ B$ L3 V
好(普通查询) 3 M5 e# \. b* z( p5 @+ B
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
* |/ b3 k/ q3 k% r9 }&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  # N2 S3 k7 X" {% Y1 r) i! F
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) $ w  H  ?/ V1 e, j; a& l0 f  F$ y. n! s' o
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
/ }& G( [$ Y! R/ G     NULL(UIN、LV、UN为字符) $ d( y3 W0 B7 m2 T' O2 j9 S
- o" ?4 |! V) [0 l7 U
  说明:AD为联系地址
% U# Z5 T; ^2 s  x8 A; ^" _: v     AG为年龄 : d# T, l! Z8 W; {5 v6 f) g1 I3 n
     BT为血型
8 E  T0 e. w, e5 J, D! X; J     CO为星座 ) L4 k- Z5 E5 @; S8 Z5 q
     CT为城市 9 H) B6 f) i1 @' U; N
     CV为未知* - g, [, k4 Z0 y1 @9 v( V0 ]5 p; K
     CY为国家
+ @1 d7 @& W' ?9 ~+ H     EM为Email
$ a& C. Q' s" _* @( D# P7 I     FC为头像
" A( ?$ J3 ~, Z% w$ }+ D/ Q     HP为网站
0 a) b$ S" N$ ~& H8 O     ID为未知 4 w* F. q, H5 ]3 c- \
     JB为职业 * Y* T+ @; d/ m0 v9 G5 \/ E
     LV为查询代码(就是发送的LV)
% `+ X+ R: `% C4 r( x     MO为移动电话 ) n; k7 k$ q) k: r* A
     MT为未知
0 O8 o2 N& O( ?     MV为未知 . ^& h! m2 k: Q& @# ?3 f6 @% Y
     PC为邮编 4 c+ ^) t/ ~. j: o
     PH为联系电话
6 g; @$ C+ Y/ ^$ C     PR为简介 " G+ W% u2 d  c$ V; [5 C
     PV为省
! V5 [3 f$ x+ U& g' H     RN为真实姓名 7 M! v6 Q: o1 y
     SC为毕业院校 . S5 b. G, \3 V2 Z
     SH为生肖
6 X& d) q; e# m& _% Z* T# A     SX为性别
; L9 n7 u9 f) V' I  m     UN为QQ号
' O. ]* G  Y9 t0 M     NK为昵称
0 \: G& T/ f9 d9 S8 B7 @# i5 Y- d4 D6 n  A  T$ t) p$ t" V8 i/ X
     血型:0 => '', & r* _) @4 F# `. k+ T7 f" J  O) L
        1 => 'A型',
) A3 ?: T9 n# Q: H9 O6 N, p2 ^        2 => 'B型',
0 h, B! r+ {8 P/ z* [% f( F        3 => 'O型', / K3 E. s3 M/ i9 `
        4 => 'AB型',
: m1 C; o: ]- A        5 => '其他' 5 I; \3 w3 D/ `* {9 ~
( C, d6 ?( u7 H- e9 S) c$ H
8 w) |% T  _3 B8 \& ^. u
     星座:0 => '',
$ C) p$ n0 I9 J9 N/ k! d3 r7 Z        1 => '水瓶座', & j2 F, [: W( I8 N) A* t4 T
        2 => '双鱼座', 9 h2 E/ @2 W5 f* ^& z
        3 => '牡羊座',
: A$ y& W' d# p* o. p8 n! L        4 => '金牛座', 5 L/ H0 @/ O/ ^7 C
        5 => '双子座', 5 @/ v7 u; U( p; r3 |) ?8 z. Y+ b
        6 => '巨蟹座',
+ T& J- e1 e+ D        7 => '狮子座',
, z  `  r" m0 F% x0 w        8 => '座',
$ s2 G, a5 q+ T0 Y( _* h! A3 V4 \        9 => '天秤座',   \, A4 |6 ~+ D# {' u
        10 => '天蝎座', 1 [) V* W8 U* o6 z7 e6 M  G/ }
        11 => '射手座', " S2 F0 K3 V; Q+ s4 m
        12 => '摩羯座' 4 \, R  y9 Y3 @, c; H! _, Z3 ?0 k% R

6 @( K* ]. z1 b! p4 F* X$ h! l     生肖:0 => '',
, O+ P# V: {2 ]( I# K% Z; x6 ~        1 => '鼠',
1 K! G5 B! G* \- m2 ~; Q8 O        2 => '牛',
" I. {/ Z; x' K/ q4 z$ y' U! J- C        3 => '虎',
  Z5 r: l. u" |  I- k, N* Y        4 => '兔',
! U7 X7 q3 f* t8 g4 i, v        5 => '龙',
' W+ k! x4 w* C4 u' z. c$ U        6 => '蛇',
% o) t) ^7 r' A2 l        7 => '马', 1 j5 C) v5 C  H& `+ B1 Q. ^
        8 => '羊',
6 O/ c( R6 f& ?0 Q) g  g        9 => '猴',
2 b& r: R3 V' }6 W. D# t  Q1 c! }6 f        10 => '鸡',
9 S0 t" z* F! U0 J& K        11 => '狗', ; V$ ^3 ?. a# ^; n6 `9 L
        12 => '猪' & [5 p6 t3 }0 o$ R

. P. i7 N/ k8 b: X     性别:0 => '男',
. f0 O- {9 e% \, |4 e1 }. C7 C        1 => '女' 4 o5 o$ g$ `: W- A
' X: a6 N" ~- b2 A3 r
(5).增加好友
, H0 h4 H0 g& ]  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
& H. z6 g5 c1 r6 W; x! @/ e1 t; q' ~6 A3 X$ Z4 Z
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) / r- c% Y/ d" p; s9 x
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) # X) S' E  q. Y  w' {
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
  K: n6 Y* V* z     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ' L5 @9 F/ [$ u: J) a
     NULL(UIN、UN为字符)
6 t7 i; \- j* ]
7 m1 f( P8 z( p2 {(5).发送验证 4 n0 ?% a  I7 M
  说明:1、如果你加对方为好友,你需要发送验证 - I# I4 T! x% z
     2、对方加你为好友,发送了验证,你要通过或者拒绝
- x1 u$ \2 f1 l     这2种情况需要发送验证消息 . P( S0 Q$ r5 X( G+ S$ K

; m3 g- n. \3 e  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
2 M: o2 L( v6 y9 e  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 % w# I5 ]8 J, u

" L) w! n9 {! g  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)
) c: h- X" g0 O  x& Z2 z3 P     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
- a* l, s( G: ~' p4 Q9 r0 e- A     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
4 L8 ]3 H( L" F3 ]0 H) _1 I  V     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)
  j  |4 g- |3 B5 b) i+ J) N8 x  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
- T: l; r3 i  D* U/ Y  V
# h; H6 N) U' ?# D, c# v(6).删除好友 ( h7 I: b) c9 J* `
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号
- q2 ~9 ]" m* O' U* L! {. A; q. x- p2 k) G" n7 S
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) : g. k9 R' x. z5 B
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) ' N* J4 d% Y7 H; h& J& P# h
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
2 ]% M/ h; D5 K  S/ d     NULL(UIN、UN为字符) ; H/ x" h, t6 K5 o% L) N& q3 X: k
1 ~- s7 o( S0 T( [1 u. E5 H7 I5 a: A2 c
(7).改变状态 6 O: W8 D: Q2 |3 E9 W4 L1 S9 L0 c
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
% \4 B9 s) o/ L) Y0 L  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 , o3 @0 A; h; E) [% K+ J

( D! _5 w' v" Z& z2 D: }- R9 o) e! H  I  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
7 j# y8 {" {# R9 `9 `( o- |$ K     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的) 5 v! a( ?; p  B  D
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
* S# R- b; Z! D4 M8 }6 z     NULL(UIN为字符,ST非法)
* t9 U1 ?( _: l
% m0 W2 [1 p% n; z( G  P  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 9 @3 A7 L7 V* w: \2 F5 {. j
       同理,当你的好友改变状态,你也会收到一条系统信息。 ; j1 I5 w5 Q6 y6 B

; g0 X; }1 O0 w& v" X/ q  b% x* Z(9).获得消息
& Q1 g1 r, W+ X  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号 % }, O' `, s# X

2 f- s, Z0 z  w* B! U9 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的值用","分割,分别表示消息类型、发送人号码、消息内容)
3 l  W+ Q4 A0 C7 W! s4 m% ?* z. c     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
/ I6 A; g  q' s  M; R     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
6 k8 I0 \& T$ q% G7 T     NULL(UIN为字符) 7 _" [: a* |. x9 V! S
  说明:关于MT: 2 c4 g; ?' E% ?" u* Z+ K
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 " V. ~! R# ~& ?
     关于MG: ) m- T) a+ k7 O0 r
       当MT=9时,MG为用户发送的消息内容
) {; s/ b! t0 [. t& l& s( r       当MT=99时, 7 M$ h5 i: ^* w- }' _0 v
         MG=10(QQ_STATUS_ONLINE)表示对方上线 . W; e' `7 G& l) i3 f  l6 G
         MG=20(QQ_STATUS_OFFLINE)表示对方下线
+ f3 e) j! N, Z5 e) P         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 % s) T3 J  ?& v( k) J$ n: S( v, J' M5 h
       当MT=2时,MG为对方请求你验证的信息 * A" J% p7 S7 E* M6 W
       当MT=3时,表示对方通过你的验证 - d/ j6 r5 h( z' f; u) d5 ]6 Q6 b
       当MT=4时,MG为对方拒绝你理由 5 e6 u* q" {0 D+ Q* }0 z

/ a( h3 A/ l9 z(10).发送消息
; c& t. P9 }8 }  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 4 x# |- |+ A, s0 ^

- {: K& \$ c3 ]" B& k  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)   x4 j7 I# |8 H9 s7 p/ k' n
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 2 M0 m$ ]' m& Y5 I3 c- T
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 k% F8 _4 D0 Y; D0 _
     NULL(UIN、UN为字符,MG含非UTF-8字符) : ~8 c7 q. c- p) ~8 m3 g( C6 }
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: / G0 V) D% |6 ~3 M
       你俩互为陌生人,且对方没有和你说过话 5 D% d' [: M* ]
       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
. v5 s& K5 e: Z) ?! d! a4 D* g; U     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s & |9 r# h& V% V" ~7 ]8 |
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
% I$ g! b3 Y* Q: C. }% T; c1 V& ?* ^2 C
(11).登出 ! `$ R4 w- [% z0 s* n9 h7 A
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
: C+ m: p# Y9 j+ g' f+ U' [  B& m# t7 G+ y5 ]; [* _
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
; X  k* X  @) m9 s; h     NULL(UIN为字符)
/ K) v1 k. k6 H. `" H
2 s* @, }+ t6 q; E* G, D5、总结
7 i1 U" p; J$ g( ^: ?" t9 T1 v' B
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
  t* T6 n- H; n  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
0 Y' u! O) Q2 ^- e- a  本文撰写时间仓促,难免有误,希望各位不吝赐教
3 @- b5 Y2 Q8 y- d
0 [* q- x& x6 U) @$ R; e% ?
" w0 D; O& ^7 ?; c- r8 ~) fTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 04:27 , Processed in 0.035937 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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