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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan # N2 z1 O8 Z/ p* M* {" ?
日期:2005.8.21凌晨
- e* c3 _: e& {# d" U联系:QQ:106814 Email:hackfan@vip.sina.com 3 C5 y+ I5 _  J+ }( @

+ a4 x& t; v5 H# o1 t1、研究说明 " `8 z" W9 U0 `. e% l+ m8 N) T

! A( S3 I2 T3 V. O3 Z) P) }  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 / I# l( N0 C; Y6 N1 _, h7 y" q
/ u+ s" i. X9 v- h: `4 Z: b
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 . C0 A$ ^! Z# Z& N1 J) P
! Y' m# @7 ]) P4 V: a0 i
2、接口说明: & z# g4 X* r/ d" b/ `
, ^% }( d! G7 }- Z
  接口位置:tqq.tencent.com:8000
& Z) s0 |" L) [' y1 X9 d  通信协议:HTTP
5 |1 a, H0 s" Z; R  数据传输方法:POST * p/ J; ~' N1 l, ^& g2 p
  HTTP请求格式: - k# y. e: N5 E2 r; q4 ~" ]
& L5 C/ R0 j4 U8 G/ ^" n3 |& w( m
POST HTTP/1.1
) _' R7 n3 y* N+ WHost: tqq.tencent.com:8000
- z0 d! _+ ^% W5 t1 pContent-Type: text/plain; charset=UTF-8 $ P- \* `2 b" g
Content-length: 长度
$ o. Q: W5 P* g: p' }( J. nConnection: close
$ u% U' V: f0 X- [; Y( t& Q% x
: c$ z) v5 U. h" l9 ~1 r2 d数据
  ^) b5 i+ ]# P% v
5 u0 [$ U  t0 p$ _  其中长度为 数据 的长度,数据的格式:
8 ?6 I: c+ t# H8 s* y7 @; r  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... / k2 I0 Q' f0 Z+ ~- k& O
) G. a' d6 a4 U3 {! N
  以上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还需要不同的参数,下面我就公布我的研究成果。
: _- g" @0 F5 r3 K
) X5 \/ T9 y+ P3、研究方法:   @6 {) }- ?/ ]7 V8 _1 d2 O" R

* t7 O0 ]* r5 ]. ^% i' {9 y  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。   b! S! T9 |$ J1 P( S0 V
  下面我公布我探测的代码(PHP):
  1. <? 8 T& g( X8 c' ]; T! S3 c
  2. $uin = "QQ号"; 8 J9 v6 _8 P' X' H+ p
  3. $pwd = md5("QQ密码");
    1 I" y2 g) N+ [' v
  4. ; N, R% t) h0 H& w# e* _
  5. //登陆测试
    ; V( g9 p8 u" ^) H3 c1 N
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; + t0 h8 h! l  @: [' D. }3 O/ A
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 7 a# k7 D, y# `, S0 W
  8. /******* # q5 \, P) w2 q7 d& ^' W7 @
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; 2 o" c/ w! G- }, h! P
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";
    $ a1 v0 N# e& s; k) H
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";
    ) p- N6 u9 I7 b1 _/ V2 O
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    % f" K  P# a! U, |( ~8 o
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    ' j7 @1 Z. H. Z1 C- p- n9 z
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";   t7 c2 n+ E7 [
  15. *******/ 2 m; w5 V/ |6 X# |) [4 y
  16. 2 U! e5 ~/ }& k9 b
  17. 8 P# }" f% s' \, x% _0 `" S7 U
  18. //得到好友列表
    # s; E- }; p3 u6 h
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; 5 ^3 j# v4 ]! o
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; % a. \/ Q  Z7 j) l: a* `7 A' g
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
      Z( S9 m0 X* }2 e0 Q
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    ; K! x9 A$ f3 ^
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); * t9 ?* W9 i' n, q; e- c( U
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; " ^' u, c, ?8 d2 |% \6 R3 M
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ' ]& y4 P- N9 Y" o6 k# y* n
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; + }9 s* {. }/ a; ^, o4 |
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 9 @" [# y+ y1 R3 K8 e
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    0 Q2 _. r* B# H, T6 R  e, O
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    6 o! f0 K2 e* B: L; }" l
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    0 S( W- B* J( o1 G
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ) p" j9 {1 M  F5 o) U" [6 V
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    7 x$ R3 `2 m9 ^1 o6 ?. M
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; ' I6 {  N, L) d

  34. ! `, D' x0 f6 A" t. _! B: r
  35. //得到在线列表
    $ Z4 K8 f6 E' N, h: j9 P/ v
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; ! X% l5 a# o5 u& ^
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    : f# W/ P8 {6 v7 @& l4 N
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 2 G& ~1 ]) w* m. W
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; , \8 e" v8 p/ w9 I
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    " l' |' S; d8 D; I
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    ( A8 C/ A' Y1 V& v3 q6 {2 X1 @
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; ( a6 Q) T" y2 a3 B( q
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ' P# }6 L$ z0 Q3 L4 G% T2 W
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    ; @4 l/ Y3 n( A* r2 `
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 5 H% [! I' W: t5 \; w9 \2 |3 a: N
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; " N( ~- y- W6 k0 W! h% V; s( |
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    . `1 o; B/ O: Q( |
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    4 v4 J- c5 L( o2 S2 @9 e! y
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    2 I/ Y+ L' l  C' O- S
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    " t5 u: `: }' r3 A

  51. 7 b  X' b% `7 A; c1 X
  52. //查看好友信息   I/ j3 }/ U& J' n2 T, P  A; R5 x5 P
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; ; y( {6 P  W2 p4 t+ Q: {7 Y8 b, ^
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; 6 b9 ?) q/ O+ n* ^
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; 6 l  m8 L- H. i/ B: m+ Q
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    9 ^+ L  ^5 q$ U0 n
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; 0 L" d+ E/ U. L8 g
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    . {: l) |. |0 s% R- ]0 O2 x
  59. * O: ^- T! d4 y! v) Y* c0 S
  60. //增加好友
    # r! C* M' }; M% @2 G. ?7 S
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    4 w7 u  Z8 l" b' |: h% q+ L

  62. : J# o" D$ P! T4 T) A/ k
  63. //发送验证
    , l& H0 z' F: g( ?
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
    0 }4 _& G9 O" f$ t
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
      `) M: F1 h9 u6 e, o5 ?* I
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";
    / v1 u: T0 c: |6 ^: b2 r' ]
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST"; 0 @2 {7 d% F8 Y9 g1 A! k
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
      _9 d+ _5 E. `7 z4 O( r
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    # B5 V) [/ i6 T9 ~# H

  70. 0 c5 l# Y  d/ K5 ~6 s6 f) M+ E
  71. //删除好友 / m1 ?8 X' k. e/ h: X  t7 X+ l
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; 7 d/ a3 J9 k0 A7 R' X; F
  73. * u5 [+ o, X8 x0 |
  74. //改变状态 / z, L6 F( K2 w# ]! E* K" v- r2 m
  75. for($i=0;$i<=60;$i=$i+5) + O6 d& w% z; p1 P# w# P& P9 p& d
  76. { " W4 a& U% M1 m" p3 M: w
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; % P; A3 F9 D# x
  78. } + M4 [" m1 Q( `1 ~
  79. ( S+ j3 s5 o7 P1 T% D9 I
  80. //获得消息 . H1 \- d+ H- l( Z; g8 c  m2 o6 D  L
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    9 Y. C0 q6 F. k+ m5 `8 N

  82. ; v, E) s6 ], m, _3 A& ^: Q
  83. //发送消息
    9 G/ J: l# ~5 i3 Y7 }% T5 s
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST"; . W; `/ }* c9 k2 J; @; q
  85. . c  w5 r! @& @  }$ G
  86. //登出
    0 J. p6 M2 T. {6 H$ M, q
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin.""; 7 o* i5 {) P, o+ `9 q

  88. $ P) L% q% y* C1 q; ^
  89. $file = fopen("p.txt","w");
    * q2 p% \9 d3 T* t! u

  90. ; z. A& v/ \# C3 G1 B9 R: c% w9 ]
  91. foreach($poststring as $k=>$v)
    1 z6 A+ S) H$ g7 E0 V; U
  92. {
    ( F. {# c# x6 {4 P- l
  93. ss_timing_start(); % `3 R7 M- f( \, A: |8 Y+ K0 d
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  + P: U& d% t+ E' p  L

  95. ) G* y; G1 Q0 m$ u+ e  ^
  96. if(!$fp){  " X6 A1 j/ q2 T0 H& {* P% z
  97. //error tell us  * y0 a. z7 t# t5 x3 ~( d- W
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    - v# b" A8 Y2 ~# w* D
  99.    : V$ r& _, v2 J! J8 O8 t! C
  100. }else{  
    0 Q* G& W) l6 C5 A$ v

  101. ( Q5 l) _- t5 n. v# p
  102.   //send the server request  
    3 M0 ?3 M! s" X1 _3 ~
  103.   fputs($fp, "POST HTTP/1.1\r\n");  
    ; X/ u4 Q; z. R7 }
  104. //  fputs($fp, "Host: $host\r\n");  
    , Q2 }  J; U; @. f
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    7 f! d3 E' b* d' s6 Q
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  , u. c) E' c, [2 N" o# u) g
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    * `' ^. k6 Q1 j/ l2 b( r
  108.   fputs($fp, $v . "\r\n\r\n");  " J- S" ~1 W9 @4 k
  109. 8 w) ^" h* b. t2 J4 Y# e
  110.   //loop through the response from the server  / @; c) y  e# b8 F: {# @
  111.   $res = "";
    & o8 f4 _$ @1 v5 \( W
  112.   while(!feof($fp)) {  # ?" k3 t$ f- x
  113.   $res .= fgets($fp, 4096);  
    1 u8 h/ F: y3 l2 [8 X6 H
  114.   }  # b) X! z. d% a. H9 \; V* q# S
  115.   //close fp - we are done with it    I  M$ @: m% l* E9 n
  116.   fclose($fp);  
    5 T% }& G8 i+ m: P2 v+ @6 x

  117. : }/ s* {2 w1 F7 ^( j, o+ ]% |
  118.   $content = $v.chr(13).chr(10).$res; * ]: @' q* X' w4 n0 u* u) r, D' T# U  R
  119. }  
    & \8 k2 G6 a1 _# A
  120. ss_timing_stop();  
      k3 _5 f/ i4 X+ b3 G- ~+ q
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    ( B$ f6 ~7 O% `& o  j7 v
  122. fputs($file,$content);
    ' I0 g7 x8 U1 C
  123. }
    7 ~1 F6 @/ S+ P& b8 b
  124. fclose($file); . y* S0 d/ F  o5 }. K0 }
  125. ?> % h4 g; o8 c7 l6 N
  126. <?
    : @/ T2 {) I2 v  y
  127. function ss_timing_start ($name = "default") {  
    * Y; \5 c& }6 m$ N  |
  128. global $ss_timing_start_times;  
    + r8 y) Y/ C1 M3 [) o
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    ; n. T/ z, U9 ~; j3 u- A
  130. }  
    2 q! ~- V- K8 m8 F3 ]8 [
  131. function ss_timing_stop ($name = "default") {  
      l+ ~. B" T9 F: l7 Y- |. M
  132. global $ss_timing_stop_times;  
    $ b. A+ [  a9 n* C8 t% |/ P
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  ' A* D- A9 m: d' X. ?
  134. }  % L+ P& X4 V2 v' J' \
  135. function ss_timing_current ($name = "default") {    @5 W- P! e# ?# H& o: N
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    7 d4 c2 x& K; i, V
  137. if (!isset($ss_timing_start_times[$name])) {  $ Z# |* N2 l. ~. w" B. r
  138. return 0;  4 k1 U. b2 c' Z( D' `
  139. }  
    . T% w* ~7 Q6 ~+ K) H
  140. if (!isset($ss_timing_stop_times[$name])) {  2 S( P4 K& P$ L' X8 Z+ m) K/ s
  141. $stop_time = explode(' ', microtime());  
    ) ]) B8 J& H! j% P1 Y" g; N
  142. }  
    $ Y; k) l$ V& y+ u
  143. else {  : y8 p% Q, n6 h+ H5 v
  144. $stop_time = $ss_timing_stop_times[$name];  - h+ n$ U; n% Y6 Y3 v/ \
  145. }  - Q! e7 e; e, Q( a8 d/ q( `3 k
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    : X2 N4 l+ {. L( L7 ^
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  
    4 t! N0 V# [3 I& H& n9 g& d
  148. return $current;  , I  W( y! [& W. D/ b( e
  149. }  
    * E  d. u( L3 u5 Q
  150. ?>
复制代码
( f% P6 P0 f4 M- P
4、研究成果: * S$ G& i( b2 t- X; I
' E' ?) t7 l0 z, g
(1).登陆
! h3 }9 K* o- g9 ]( V& e  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。
$ J0 v9 k8 r1 m0 j  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ , \8 C" G, m0 Y9 X  Q0 p
0 j( u4 s  z) [4 J( N& X
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 # Q% d6 H2 t9 \0 @
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
2 G. ~! {1 V7 E7 c$ d! S     M5这个参数的作用还不清楚,但最好为1。
: Y) [8 ]7 C1 j, s  ^! P2 f- I; O     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
% P/ K9 [( y- h. B+ e7 G9 V  L: v+ ]0 W" ^% N+ B6 H
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功) : X* d* x/ n' o0 |
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误) 7 f9 g, V' l" K
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) , I( c0 Q+ q/ @- T/ K4 R
     NULL(UIN为字符、PS为空、LC错误)
  Q/ v6 S+ }5 d3 ]- w' h! ]4 y, O: u8 ]8 |" Z# B
(2).得到好友列表 % Q/ _- |, z0 \; J) t0 u" |( p
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 * K, j3 D3 y8 }- R( _! B
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 / ~0 a4 d4 u/ o+ u8 ?& C" K% c& U
* h$ R6 j  o# o0 ]/ z! r
  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) * c. ?% `* ]$ ~- z
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) ! r3 r+ m  s( u
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
) e% e5 |3 D4 E     NULL(UIN、TN、UN为字符)
5 y. I! h9 S0 s9 N% H' h  U: n) g3 o; d. p
(3).得到在线好友列表 % G" K' E8 C" \* s
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
- B: c  }; j- {$ I+ K. F  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 1 Q8 [$ ~8 f; V+ a( }

, A4 p! L' ]7 U2 T; f; X  返回: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的值用','分割,分别表示头像、状态、号码、昵称) & }/ G. A3 N2 t+ \& N
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
% X; t: m! V2 A* A     NULL(UIN、TN、UN为字符)
/ d0 h5 L4 I1 O! y+ X) O  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; + W- K$ a0 s3 i8 i( {+ t! d3 l
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;
2 y) H; J7 S% {2 I  k2 e
/ H2 y! b  c2 Q  特别说明:当参数TN=0或不存在时,服务器返回:
) e& r+ h9 z+ B, a0 Z/ qVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
: K+ c# \: m/ sHTTP/1.1 200 OK   M" m8 [/ y  I4 }  ~& P. l  ]
Server: tencent imserver/1.0.0 5 O5 [' N4 ?1 M4 N. |3 ?. G
Content-Type: text/plain; charset=UTF-8 & d6 F8 N  E# \0 ?0 h
Content-Length: 56 * s7 i' j0 v( \" T7 K7 ^
4 o% `) Q% J, w' ]0 \: M7 y4 o
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
; _# \& u2 n: s) i# ^" iHTTP/1.1 200 OK
' K2 V7 a4 l* ?& tServer: tencent imserver/1.0.0
" _6 C( ^$ O) oContent-Type: text/plain; charset=UTF-8 2 N* W- D8 S3 F/ D: w
Content-Length: 77 & g! z3 R; D+ U8 J+ p' ]+ H/ o

5 V" e; z. d# T) [9 c) xVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
0 F- e8 [+ |& d1 A4 F+ v8 g  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。 # w* B! M1 Z8 n5 ?# ~5 Y) \1 `
; H% D% ]- P% A
(4).查看好友信息 + D1 [, c3 b$ H: ^* X. J* o
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 8 }$ V9 N3 k+ n% j) o
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
9 y0 z. Z  j3 r% Q$ C( t% E- q1 U5 R4 y0 @, G  B
  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
1 X6 M2 v3 F% H  d7 H8 f' M8 M     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=学生
3 B' \$ y& K. e&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
; U7 I" M7 R+ M6 b( E% q好(普通查询)
; m7 t2 a, D5 e* E     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 . z( Q  s  o: }" w9 V. E
&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  9 J, i: H9 @# b9 U0 G
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
1 Y7 }; i" W: V9 a% I7 T     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
. g5 s* m+ J% k' c     NULL(UIN、LV、UN为字符) ) D( K; l" G) i0 I- R; n' Q3 s
' V$ y8 ~; E0 d0 Z% `6 P9 {& W* ]
  说明:AD为联系地址 2 L8 h+ A) n0 O0 D& D% z, o( w
     AG为年龄 - q  W  Q# \, J  R# k) R, m* \; Y
     BT为血型
$ K8 P5 [4 ]9 ~4 `( g# a. S     CO为星座
7 d. `; x9 m$ P- g& X     CT为城市
& }' f  a" W7 [2 |  X9 T     CV为未知* 4 s, Q( c, X# J: G) O
     CY为国家   c- `# l' @- ^0 s/ K, [' }6 ?
     EM为Email
. N# [7 m, B# F     FC为头像
! l, v! ?  @7 [5 e: M0 {     HP为网站 ; }, b4 y7 ]3 h1 ]8 G& S# b( C+ ?
     ID为未知
6 j4 s; l; H0 x, b% F3 I     JB为职业
) M4 Y+ q" r2 r' I7 Y3 C     LV为查询代码(就是发送的LV) ! @% F1 W" t  q7 \: v$ C
     MO为移动电话
! R; }$ j( X( v! N6 k8 i9 u     MT为未知
. \. \2 P; K% D4 a7 O% \     MV为未知
- y& ~$ d5 Y* t$ b: {  T- ~     PC为邮编   `: O4 G" u* y% M( @
     PH为联系电话
' R- H' s  H4 H1 O     PR为简介 " U' _9 }. Q' b; e0 ?+ m8 H( r
     PV为省
3 w6 E0 q, L8 V5 i! l     RN为真实姓名 $ f; P$ D$ c' f$ o- j
     SC为毕业院校
4 S. m, e3 c3 ~1 h     SH为生肖
# {" E8 S9 w9 y     SX为性别 ! x  L3 w+ y, G9 F- a" r( _4 V
     UN为QQ号 " k1 `: h/ i) f' Q% M  U: ~- Q1 u
     NK为昵称 2 P* O: n7 Y0 _1 s

9 d* C' ?/ H# f/ a2 ^( M     血型:0 => '',
  t3 ]; [6 A: U* N& \% h% O        1 => 'A型',
' D6 J4 U* ~( Y/ L        2 => 'B型', + P, \8 M+ j9 ~% B
        3 => 'O型',
: ~9 s" b4 W4 s$ _/ a: P        4 => 'AB型', 3 u& B, H* u$ R8 G; C6 d: [2 K
        5 => '其他'
7 t: N, u' H; I0 u8 n) M+ z  ]% z$ X6 n: E6 b
0 Z" s- n& A) @" }0 g) J/ j
     星座:0 => '', " v, d+ W3 E: ?$ B! i
        1 => '水瓶座', - \7 P2 O3 J, N7 o: Y6 l  O
        2 => '双鱼座', 4 z5 \: R3 @" G* p# n
        3 => '牡羊座', 3 W, ^( V# S7 e. z; a7 S( k( S
        4 => '金牛座', 4 R9 P4 [; c$ K
        5 => '双子座',
( h* m/ d% r% p% ~* ?" I: |        6 => '巨蟹座',
' y( c  w% n9 J7 q1 r9 R        7 => '狮子座',
  d# g% K8 }5 S8 P/ l. U. ]        8 => '座',
7 J' a( K7 o7 A4 p; f3 x        9 => '天秤座',
0 P7 y: g1 J8 p' W, B) d$ U% O        10 => '天蝎座', 6 I5 G; D9 u, w# c' n: O
        11 => '射手座', / f: a1 q0 M0 b" D. c8 p  y
        12 => '摩羯座' ) e. H0 J) J5 o, a
( \9 M1 i. V" b+ t/ I# O
     生肖:0 => '',
% k, h  P4 s# U! [8 F5 a) Q        1 => '鼠', 2 P9 L, j+ A/ h$ ^; \7 x2 l
        2 => '牛', 8 _# `& A& i  Y; @! G( a
        3 => '虎',
9 |, Z2 V- y6 C" I% }  j) _        4 => '兔',
6 t: q. \- i: M        5 => '龙',
. f! H, o4 H  c3 S3 }        6 => '蛇',
' p) `* r2 }! M/ {: f( h: K; ?1 |  T        7 => '马',   S. S3 f) e' q; J. ^5 E/ S
        8 => '羊',
8 R9 Z5 J6 m% w1 ^* Z  S1 @  r        9 => '猴',
# F3 ?8 h/ K. W5 K% n9 G/ \        10 => '鸡',
% O; g. y$ l4 B2 j8 Q        11 => '狗',
2 T0 I  ]9 p0 A' |* ]% L0 O        12 => '猪'
* a8 F& N: t8 R: G
0 Y( Q+ L8 A2 J# @1 v" v     性别:0 => '男',
' y! e" ]! d7 Z! J        1 => '女'
; l6 y' O* x( A' `9 h, ?& V6 s% Y: }
(5).增加好友
$ \% U0 J/ E" X2 u  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
- T/ @$ E; a) l. P1 m1 b6 t8 `- n1 s$ Z: b# W9 V* }- ^  q7 ^2 }
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)
" N6 O) f( D7 ~( M" R4 Z" y     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)
! G' ~, X! _& Y, |  q5 U9 ]     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)
0 o) H* I1 d: q' k! s2 _0 O, e     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 0 W# T+ J# }. \
     NULL(UIN、UN为字符) : v% q7 [& `8 O
/ s# b; P6 q6 u# n' ~; X4 \
(5).发送验证 ; l& [9 D* n! M  X' h/ S, k- n! g
  说明:1、如果你加对方为好友,你需要发送验证 % F- b& m! |; K* D
     2、对方加你为好友,发送了验证,你要通过或者拒绝 : t  z: e7 L+ ?. a5 ~) D
     这2种情况需要发送验证消息
) p9 h/ J  f) y" _! m/ r1 T) N  Q) Z% N% U
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由 * T, T  Z9 j  D9 B+ y0 o) s
  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
  L3 Y4 m' I# ^4 U& |) [
* r, a+ e. N" W7 Y$ i5 j  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 4 g% H+ [* h7 r) }. n$ z
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
. a( u1 @! \; g" t" F+ D" L. H; K     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
+ j6 i5 r# a( F4 _" m8 j     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) 8 w$ I& A0 t% ^1 u8 p
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
8 D& K/ W$ v0 m% ?0 d  W  x/ \7 H& B: i& }& w8 ~% {
(6).删除好友 8 i7 v5 X( K2 s# i
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 $ \& ]4 [* o1 y' h6 [& N
3 |: {$ g4 F) @& E6 A* x
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
, o; y. d' F) n6 _+ Y' f" `     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
. t1 G  {% l4 W; Q& j1 \! A     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
7 N! g7 H4 }+ w$ L     NULL(UIN、UN为字符)
" S& F3 e* l: Q( e! w
' x# g$ z$ B  q7 G( d/ ^' s(7).改变状态
! ?, H9 A) N: D0 Q3 Z  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
) B# k6 P" f1 x$ f  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
# ?4 r/ p* ?/ h1 j- L8 A
  k, X' `' A. {% d9 U  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)
& b8 K$ v4 r; Q. A     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
1 Z3 ~# O' q2 x* `; F# Q     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 7 f5 `0 A' E& t# z: q
     NULL(UIN为字符,ST非法)
* N( k* ~6 u& E  X% S( Y0 `( N4 d$ w% m3 n' [0 F; ]  s# Y6 E
  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。   y: ~( G* ^6 i1 g4 q/ o
       同理,当你的好友改变状态,你也会收到一条系统信息。
. G' E6 `7 U# a4 }
' k3 S( ^* {' ~/ Z+ i! A, T(9).获得消息 ' q6 t2 G3 L0 q" I5 M+ m
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号 9 H- a1 m  `4 G3 {. f9 {7 k, W

1 H3 v7 g1 h  i$ J0 K0 G& 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的值用","分割,分别表示消息类型、发送人号码、消息内容)
' c$ r* D& k- Y" F$ i     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
; L% V% L4 t8 g& u7 ]     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 9 @( }+ p2 i/ M
     NULL(UIN为字符)
( C. i  B. k1 M' Y( `) o  说明:关于MT:
' A1 o* A5 `# D3 p       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友
6 D& y" ^- h, `+ \" k     关于MG: 8 N9 K+ Z: Z2 Y3 b  Y6 d0 b: }. G
       当MT=9时,MG为用户发送的消息内容 + Z" O" W' q9 B6 e
       当MT=99时,
& Q) e, {, O' H) a         MG=10(QQ_STATUS_ONLINE)表示对方上线
' H! |( [8 Y& e: @! C( x  z  z+ i         MG=20(QQ_STATUS_OFFLINE)表示对方下线 1 w" H) z0 ], v6 |7 w  f( T) n% V( d
         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 , |5 ?$ M& b/ p8 R0 O' u# b
       当MT=2时,MG为对方请求你验证的信息 . Y8 Z7 A8 u# S- s4 B
       当MT=3时,表示对方通过你的验证 + \" i6 p6 y, F. `- H0 Y' J3 }
       当MT=4时,MG为对方拒绝你理由
8 R7 }% F/ H: t" z! l/ I2 [
3 F0 P& @- q" Y- I6 c: y(10).发送消息 " s4 v0 n* m3 y2 i9 I/ m
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 # ?9 I. i0 r. p+ `: x' A+ j! H
  }; M: P# }4 f/ G8 N
  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) 3 n7 H8 ^( R- `7 p/ E0 [
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 0 @8 ^9 q1 e7 U- S6 S& @0 [3 [
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
6 Z! h* J/ A: U& @# p     NULL(UIN、UN为字符,MG含非UTF-8字符) ) |7 `, E- u% S" ~
  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
. e, B. k# T8 C% ?, X& l( P  T3 {6 t       你俩互为陌生人,且对方没有和你说过话
; B3 q0 C" T  A6 M       你在他的陌生人列表里,并且他没有和你说过话(没有验证) 8 a7 ^  i7 K* \; Y5 e
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s 8 w' {8 P; S5 L8 c- K' w
     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL 2 N6 r0 L/ V' E! Q6 q7 Z/ d: h
! j& z' R' e# |  E7 H" ~6 U- [
(11).登出
  k/ i! D- ]0 E- n; `  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
. c% X& v. T# N+ u# e: f/ D  h7 y- C! R% @/ \
  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
& Y0 p) l) q7 p& W9 e% M     NULL(UIN为字符) 8 l. }: q' }1 G0 g; z
5 i  {& ~+ K3 f1 Q; P
5、总结 2 U: Q% G: S, f2 U# u0 V

# B& b% u7 h. `- @+ n  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 . C/ W; s/ |& x2 [2 Y/ `
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
8 ?) H' F3 `7 k  本文撰写时间仓促,难免有误,希望各位不吝赐教
. ^' w. ?/ h, u, W9 l0 k2 i3 a8 |9 K4 P2 U' k$ U
3 s. l, [0 y1 A
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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