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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan 5 Y. [, [  E; }# c- e( h& c8 a" \
日期:2005.8.21凌晨 . ^2 F( a$ J3 G1 ~$ c4 N+ C) K7 y0 b
联系:QQ:106814 Email:hackfan@vip.sina.com 2 E- a" c7 X, N0 j
7 x6 _) S. p! G2 E# y' K. c" W) o
1、研究说明
' N. k0 N  X% j0 k" j
/ f- P/ ^5 j6 K! u8 g, f" v  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。
9 ?! a8 F: O) D7 w7 ]: f4 G! q' {; {! R8 O+ d3 k
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。 3 A0 i/ _, ]  H7 i0 b; @8 @
8 I) F% }6 n  q" E6 j2 d
2、接口说明:
/ n+ ?! L3 Q( i$ S  G# Q+ K+ [) W1 ?
  接口位置:tqq.tencent.com:8000
$ J1 h4 r8 M( l# _' F- N  通信协议:HTTP 8 x. n1 S( t2 `- o' o" E/ b
  数据传输方法:POST
; R! z3 p# S3 a# w% [9 o" N3 x  HTTP请求格式: % P% }& G! A2 ~/ d  d2 E8 n
2 Y5 P4 F6 M. u; b- `5 {1 D/ O
POST HTTP/1.1
) Q7 W! w* {2 ]Host: tqq.tencent.com:8000
2 `# r; B" ^0 L7 }: sContent-Type: text/plain; charset=UTF-8
4 ~) L! j5 w& IContent-length: 长度 " B% M- k- M! _' ?& X2 F$ v' q9 k( ]4 y
Connection: close
  f/ k6 |. C; g/ L
6 \* o9 n% s- X6 R! [; b4 J) z1 C数据 5 H2 @* m) ]9 D2 w  W

# {4 h& _, f  Z/ r# A  其中长度为 数据 的长度,数据的格式:
. a' w- R2 l" [8 N% d8 `! C  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&.... 0 @3 R& z. R  P9 N: ~5 Q
) n- t3 \6 ]+ i9 j2 C9 m
  以上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 u) J/ R8 _5 ]+ u  k
7 j# z$ S7 O/ I4 D2 p' U/ i( E3、研究方法: 4 F, n% Q5 q6 y; i5 F
  o: o" m, @; e! Q: l- w3 ~
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。
# O6 Q2 K! Z3 P- R  下面我公布我探测的代码(PHP):
  1. <?
    % Y+ U  q" P1 j$ w% U2 k& z
  2. $uin = "QQ号"; " J3 {2 r8 T: Z/ M6 A2 e% w
  3. $pwd = md5("QQ密码");
    8 f& R6 h% D' [3 m
  4. / h8 W7 k: M! m; H8 D" z
  5. //登陆测试
    ! u! G9 p+ }# A6 r
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; ) U* b& o. @2 e7 ^1 r
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信
    # f& I( f. u5 _3 Q. r1 r* Y
  8. /*******
    4 X9 O6 c6 m# Q- S; v) {7 s3 c/ w
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; , z$ f1 Q/ S3 V* x( Z
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; - u# y# ?) E0 ~8 h
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; " D' b2 i% O4 s9 _
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235"; 1 r2 z4 K# ]; Q' n6 |  {) f
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235"; % L0 L5 W5 I9 ^  v# b
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; ( R5 l+ l# \2 U8 m4 r
  15. *******/
    , N& n4 i; z* S! m8 m

  16. ( N$ b8 C8 e* _1 t( @$ w

  17. - M1 m) v2 p+ e" ^! z
  18. //得到好友列表
    : @- l6 Y6 \" b9 E8 ~+ W' x. e
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; / p( b8 I, m) ]& n: Z, D+ e4 D
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 2 n7 [8 G: R& M' `
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; ) @. a: P, {0 S' f4 y
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; ) r3 ]: i. m6 p* [3 x
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    0 a7 e0 f9 C8 o4 W( f* t# @; D
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0"; 0 f+ t  n# D( i8 M+ R6 |! S: V
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ; z# m$ M. z5 ~9 ]
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    # t5 o) s8 @3 P6 t; E
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 1 E* ~; J6 e8 }1 S' C4 o
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    1 {& R+ q( M: e3 i! m# [
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
      ^5 c2 j$ c3 c) v- W
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); % j9 Q5 J( s# h/ R+ N2 }
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 4 l$ K9 A4 @% q  w$ I) y
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); - ~; a5 g2 G+ Y
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814"; ) ]: R1 s$ Y) h/ q. V
  34. ; D5 D! n  x+ L% w
  35. //得到在线列表
    ) X' m0 X  e. Y  d. V  @7 a6 Z( ^
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;
    3 K5 |% ^1 o: N* ^" o$ Z! ?
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 0 Q, T1 [/ L. Z! T, k  C. ~" k
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160"; 4 O7 w/ c4 ?: S9 j, i
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";
    " y% X9 [3 C" X4 \& |2 \# [# H
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    5 L. i, y: L) K; @! i4 A9 S* i
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    ( J. r9 k6 s3 i# J. s: _9 e! s
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    6 Z& H  G! Q  L' q
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ( Y7 B" q6 L: w% f6 L
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    6 B; V4 Q4 u! D* V% a) w1 m( E" y
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    - [# l1 k- `0 e& C# w, b# b4 f( v
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; 3 H2 Z: N! }0 L! @' \9 o
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ' h8 k+ e, ]% c9 N
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); ! F! {5 {; C% z5 t( `6 S: f5 A
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); # V* {' T0 r. Z7 M+ n3 y8 T) r' D! e1 j
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    / |. X6 f' l1 M! d

  51. $ F3 q5 @8 }9 Q. y
  52. //查看好友信息 . U* n; k0 k0 J+ j6 k
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814"; 2 I( Q8 ?' l+ t( C, L2 _
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";
      K. P4 X1 c& e6 v9 p" ?/ Y( _
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";
    ; K1 s) _* D5 K; e) t( O
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814"; 6 [5 \. E! E- |* t) v  ?, s
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";
    5 u  [% p) F! s. L
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";
    % n+ z' U2 q. C

  59. " o  z- u5 ~3 r6 j2 {8 F+ d
  60. //增加好友
    ! H; {& b2 J$ Q
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; 9 C  P; h3 s3 g' b) m$ ~# M1 ^
  62. * w+ Q0 i7 Z$ `% j( G. ~0 O: m2 K
  63. //发送验证 5 v; a* \) b# l4 G9 A, D( o0 P% @6 |
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST"; % G) M: j9 i# I- k
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";
    % r; |- S% e3 e7 E. q
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; 9 i/ t5 H4 s! v, s: v8 k' _! k) ]
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    / y& k: @2 H% j  c
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    ! h7 h( H5 m% z5 G3 o# a) o, l  K
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";
    2 D' {" J0 [* [) F8 u) \2 Y

  70. & j. d" W" q- y
  71. //删除好友
    & ~% w% K2 f/ [3 J
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    & p. k" v8 R' l4 o/ }  w8 A' u* `
  73. ; Q, w3 R6 ~* U  J
  74. //改变状态 6 o8 N% V& }: i- j9 [) d
  75. for($i=0;$i<=60;$i=$i+5)
    + F2 Q4 U8 a; A# j5 U' R% u1 R  e4 ]
  76. {
    * `. N" E* i3 U* E* n
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i; : V  |0 a" t) t# L
  78. } : x' j1 f  A. l( S  d$ L
  79. . b3 v" Q8 N6 j
  80. //获得消息 ; p  j+ V- Q3 }* k. y- N) G* _+ f
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin.""; . r( ?) x0 p: \0 J' c: x8 [
  82. ! o, Q0 ]  p, z* [* U. @! K
  83. //发送消息 0 ]! m* t. C- U: Z6 D- C
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    ; F/ o8 K0 p4 H  k/ H0 o: n
  85. / G$ Q/ a- \% }( o$ m, b6 b
  86. //登出
    ) n# Z+ p" }' e. s( }, O" a1 f
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    7 B5 t# O5 H) `( w8 R" u5 l# k

  88. " u/ r5 u2 D. z! b& H
  89. $file = fopen("p.txt","w");
    9 O3 \7 a: K: c- v
  90. 7 V- v' [# x/ _: a7 L5 o. X
  91. foreach($poststring as $k=>$v) # H0 I0 W: Y0 F1 N# _
  92. {
    + V) L5 K; d% G
  93. ss_timing_start(); ; D  @, T- l% u$ o& }
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  ! ?% `, z8 N9 J; |& w
  95. - D+ p8 c( m" y* T
  96. if(!$fp){  
    ( L3 Y$ P6 i& I# m# b0 {$ ]+ w. ~' |
  97. //error tell us  
    + X; j" P4 U6 F* |6 g6 A1 `
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  
    - v0 b* [$ B0 a6 o
  99.    . }8 i2 ?5 h% |3 j5 V
  100. }else{  - `" O$ U* @0 n% ?1 [! G# {" @
  101. ) E. U0 G/ x' x
  102.   //send the server request  : D2 ^  W. C( F& R, M' }
  103.   fputs($fp, "POST HTTP/1.1\r\n");  , N, W& ^& H1 J& I3 e2 w( Q
  104. //  fputs($fp, "Host: $host\r\n");  5 k( F9 c7 [0 J/ l* Z4 S4 V' ^* E
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");  
    9 B: B) b  f  m! I- C
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    2 r3 `, E/ A0 L& o# f; I, H& K
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    - U9 `$ ^7 R- F. o* ^% ?1 p
  108.   fputs($fp, $v . "\r\n\r\n");  
    3 _$ x" L4 ?8 L, Z* K
  109. & y6 g2 X0 ?$ ?: ^9 t
  110.   //loop through the response from the server  
    % X; k, F. V3 w" i- L( h% [# r% ~
  111.   $res = "";
    8 j  _: o: j& v! o
  112.   while(!feof($fp)) {  
    ( m9 k0 K( E8 z9 W( ?. N+ g
  113.   $res .= fgets($fp, 4096);  6 f1 Y" b( e8 W8 [0 ~" ?* B  ?
  114.   }  
    . s% p% O4 X5 Z1 z/ ^9 y; n5 p/ U! b) t
  115.   //close fp - we are done with it  
    / Z" |& p; `9 h& A# K% }
  116.   fclose($fp);  " n( H! k: l4 P) D( ?

  117. # d2 t. d( j/ N% S* q
  118.   $content = $v.chr(13).chr(10).$res; / p1 `( L" u* g  @7 g
  119. }  
    9 e1 O2 z% p* A* I
  120. ss_timing_stop();  
    2 I( ]! j  k% J. u  @
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);
    : x% S& a/ O& T. a! ?  P1 B
  122. fputs($file,$content); 3 F$ ^+ z# G! I3 d. P& S' }
  123. } 8 w1 ]8 w/ ]% d" V9 h: A
  124. fclose($file);
    % k4 O, M6 \6 F+ Y6 ^* b
  125. ?> $ e& q0 J, n6 D  {
  126. <?
    6 L4 O# r/ V8 }
  127. function ss_timing_start ($name = "default") {  
    # ?/ b8 G1 Q6 ?  X& ~' L5 _
  128. global $ss_timing_start_times;  " O& F3 z1 f2 F
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  / H( e  U' V/ b. Y  T, i" K: v9 V# e
  130. }  
    / t% J2 b  a, O/ x$ r3 |
  131. function ss_timing_stop ($name = "default") {  
    2 a3 [& o  y1 ]% C0 l1 U2 D9 ~/ W
  132. global $ss_timing_stop_times;  
    ! }7 z1 j  ?1 |0 W7 C; M8 g7 d
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
    5 C# U2 H% {3 C& w7 J; t
  134. }  + I, \' b% P  [* I1 k. k9 B, ?
  135. function ss_timing_current ($name = "default") {  8 Q  M- Z* w/ ]9 ~2 D# e' M
  136. global $ss_timing_start_times, $ss_timing_stop_times;  
    ! D( i. B0 w# p" s
  137. if (!isset($ss_timing_start_times[$name])) {  
    9 p3 i/ O+ H6 ^+ n
  138. return 0;  & y+ A5 d' x5 u
  139. }  
      P8 L9 K8 `1 p9 m) q) t
  140. if (!isset($ss_timing_stop_times[$name])) {  0 Z7 \, n: R" j5 J& q& q# G
  141. $stop_time = explode(' ', microtime());  ) L% i% P0 U: s9 y" x) t
  142. }  " k6 v4 s$ x1 d& U
  143. else {  + V4 r% a+ _( X) y
  144. $stop_time = $ss_timing_stop_times[$name];  ) C1 f" l0 ~" V# F8 e" L! J( n+ M. c
  145. }  
    % K2 Z( P8 R7 D7 X; s6 v) z, {: X
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  
    1 [8 ]3 P. m4 \/ M0 g! ^) W( h; p
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  9 J3 `& h9 d1 [. |
  148. return $current;  
    $ p# c5 `9 v; F' P
  149. }  
    8 w! W( G; t  b4 h# o
  150. ?>
复制代码
* ~' Z1 i8 ^/ b
4、研究成果:   S% A( ]" p& _3 j) |% K

) W7 E- @# \, x  j6 z* G  K(1).登陆
' |3 v  n7 y* W' O  J6 \; n' |  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 - l6 T/ J# P; }% x3 L* {
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ , e, A! B( s! a; @) G
3 l' }: N+ T- P) k6 S
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235
8 F9 a4 U) I8 ~% h' ^  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;
: k; i9 W$ M: n" s     M5这个参数的作用还不清楚,但最好为1。
& n! i  M" Y' A+ e     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
2 d+ M* u1 _3 B- P+ m' ~! R% W5 k: E8 w2 n; r
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
1 j  |& F9 b# s% k     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)   |! k$ Z: c5 r, R4 ~7 _
     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)
, {* |. R; n2 A     NULL(UIN为字符、PS为空、LC错误) ' o! F' a. L' D- }  K

8 y) I# N$ e7 F2 d7 E1 C(2).得到好友列表 0 E! R$ Z6 _9 A  ]7 O: L0 v6 ~
  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 9 C, M2 _$ `$ f1 `- X% o' J
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 , b5 m( a2 s; T- }3 i, Z
: E8 v6 j" C1 I$ A
  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) 7 N$ @# u2 R! t+ d: d' H
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) # a, D9 N: Y4 N; ~& ~1 T
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) % Z7 y/ @( m* M& d( ?9 e" Q. @
     NULL(UIN、TN、UN为字符)
9 P* E( \: B1 Y* D7 _
" t- o$ C& g3 |(3).得到在线好友列表
7 f; [+ z  e$ G  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0
8 N; N# S: T# w* }  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响
+ w- [# I( {8 [4 S0 {8 ^. ~3 V7 X2 w6 m7 m$ U# v
  返回: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的值用','分割,分别表示头像、状态、号码、昵称) / n5 a' c3 F" m: {: _- {" u
     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
9 x  y) c5 W. D$ W: _0 B     NULL(UIN、TN、UN为字符) & X# j$ S' X* p0 }. S
  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; - G1 G  N, R! r* `5 l' w% ?8 L
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; % k( O. l* g# G0 n2 ?  d
* C0 ?& p0 }3 O/ r1 K' H' B" d( `
  特别说明:当参数TN=0或不存在时,服务器返回: % q  \0 [* d6 t+ M. S
VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
& H7 b8 a7 ~* W0 h) J' tHTTP/1.1 200 OK # ~$ J2 j. O; U0 I4 b: z; J
Server: tencent imserver/1.0.0 / N) G2 H$ o8 z% _2 u& _  X* S% H
Content-Type: text/plain; charset=UTF-8 ; y, ~- ], }3 b7 D/ d/ x' q
Content-Length: 56
9 p% y1 M  U" b7 K/ ?
" C. ]# C3 Z6 I+ mVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1 , ?2 N# M: i( f  U4 o; ~( Y) s
HTTP/1.1 200 OK
2 \- F7 o$ _% R8 nServer: tencent imserver/1.0.0
: P" L6 Z# h% B0 n1 E0 W0 \" JContent-Type: text/plain; charset=UTF-8
' @; W6 Q/ o6 p! e+ O3 y4 S# E& KContent-Length: 77
- F- H( O! G1 r( I4 E7 `! R' _1 r8 a; ?7 R
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK= 9 q3 i# K( [# G$ Z
  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。
. D9 ^1 F3 F% [7 y! n! U2 j2 X6 u' m* X" b: `; b- o& X
(4).查看好友信息 % _- K4 m! j0 v$ \. ]: G5 S
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码 # V, o$ e* t& U  k5 _
  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询 ( w; f, Y- a, F8 n

7 t% Y" ]# J- F+ K; V2 Q' U  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
2 p2 V7 v1 ^5 \" e8 E0 k4 r     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=学生
; y- y# J+ [! z% P: F9 I7 C&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  
2 Z# Z0 ], ~$ Z1 O8 j( X好(普通查询) 2 q1 _( B$ l, I+ p% M) i
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国 ( I6 j5 S* F: ?  T  A- k6 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  , C" i: w( p0 f
updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询) " C  g. O8 f9 G; l
     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) " C; J, V7 x" z+ M" D
     NULL(UIN、LV、UN为字符) + E' J7 W, o, L! j- N$ U# o

1 G/ h- D/ e: X0 s! }  说明:AD为联系地址 0 g+ p' U' ^5 @$ n( s7 c
     AG为年龄
; J3 L. A% d' W3 D& W5 z: x     BT为血型 : I2 k  T' C* {5 {( \5 G. m8 W, P
     CO为星座 3 i! u3 }" x, _+ J2 p
     CT为城市
" g9 p% H9 F$ T3 i7 w# J# D7 M     CV为未知*
+ f$ X8 }( A1 _$ M     CY为国家 ' @* v! _1 B& Z  H& R) O
     EM为Email
' I; J2 T4 q6 P     FC为头像 0 o! E' K. L1 U% b, h) I% M4 \
     HP为网站
9 b+ D+ Y5 P3 S9 u0 h: [$ E0 R     ID为未知
8 p& X. U, V0 _4 }; y5 ?+ T, z     JB为职业 0 U, O* j) M. j
     LV为查询代码(就是发送的LV)
  B9 e5 R7 y3 o" [& y8 a     MO为移动电话 0 |1 N' b. _4 R7 ~# H9 x
     MT为未知
+ l- |! A4 q2 Q$ q     MV为未知
: X  J7 \$ P' M% [( w5 ?7 X     PC为邮编 9 {4 D# k" Q  E8 U" ]' j
     PH为联系电话
8 L' g* F% z  L: f7 I4 O     PR为简介
, A+ r7 }4 c+ P. k) e     PV为省
& o5 S$ S7 H  Y- A     RN为真实姓名 / D5 n" o' k* x, h$ N& z
     SC为毕业院校 ( e$ E7 g$ C+ V* u: b- J! |9 d3 C* j
     SH为生肖
* j2 m, @+ A' Q- O( }* [     SX为性别 + t) j' j. v; X2 g2 g
     UN为QQ号 ! H3 D3 o4 c) G
     NK为昵称 + x: |1 L/ R2 m3 o

% b3 i+ ]: g9 q. Z. d0 R" N     血型:0 => '',
, @: `  p3 U8 O: e        1 => 'A型',
( G6 L- C) l" q        2 => 'B型',
9 X& W7 [4 a  C3 M        3 => 'O型',
, L3 o& B( b. }8 y4 e        4 => 'AB型', # E  X( \, ^2 L% Z# A0 o
        5 => '其他'
) `5 f! c/ w" Y7 x0 d- B
! \7 x6 _0 Q! _- B$ s
3 l8 ~4 s7 Y6 s' D     星座:0 => '',
' a2 d$ B0 l) I6 Q1 H' [, Q9 r        1 => '水瓶座',
4 Q6 T" b2 w! D. J, S        2 => '双鱼座', 0 q$ i& H6 T! a* z$ ]& @* k
        3 => '牡羊座',
! T! R  d* ]' _2 n        4 => '金牛座',
- {8 ~1 F  C$ k8 F% z( u/ O5 k        5 => '双子座',   ~6 p- t  M/ o5 z- r7 y* X
        6 => '巨蟹座', 0 B9 s+ |  h9 G7 M
        7 => '狮子座', ) t) C" r* ~( E8 f, H5 g
        8 => '座',
0 _( m5 o. D& ?6 a) g        9 => '天秤座', 8 t& x- e) i4 H0 P, {* J& N
        10 => '天蝎座',
* A! c/ n* |1 x        11 => '射手座',
/ C7 W6 E/ M0 W! _) i  {% X  O9 j3 V        12 => '摩羯座'
7 E) s* t) l5 O! o- Y0 |8 }3 ?. L/ s2 k" }! t
     生肖:0 => '',
* c8 ]2 f* s- c/ w2 K; i+ q# |1 h        1 => '鼠',
5 U9 r2 o* \/ a* ~6 l        2 => '牛',
& m# A. ?6 Z4 c7 C0 _; |        3 => '虎', / t" }& \  [$ x9 V
        4 => '兔', " i# l, f: e3 o0 k. g" \! |
        5 => '龙',
; L0 ^8 ~+ @4 y( V        6 => '蛇', 1 i$ x. Z, }3 ?; s) W  x) o
        7 => '马', - q( c0 M1 P8 y% ?
        8 => '羊', * g. p) z0 x+ @% x7 q% k& S
        9 => '猴',   o9 e' P4 a0 A/ ?
        10 => '鸡', - G5 R+ k, X4 M7 H7 C+ i: a4 Q0 I
        11 => '狗',
5 M3 Q: V+ ^  q2 Y- U1 J/ y        12 => '猪' 5 h" B+ v7 a4 ?5 q3 @$ M
! q/ ~# e8 s# f* l9 s% q
     性别:0 => '男', 7 e0 d8 K: w' n) l' o6 i3 [
        1 => '女' : P" ?  e+ @: J! I. w+ P/ x
) p% J: t2 V; e( M, b" t& _5 p) |& Y) S
(5).增加好友
" R* S2 ]6 a  N; i! S  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号
3 l2 F  `& w6 ?/ `; K' ~+ L5 O- W, ^. G' ~+ t4 y
  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) + S  H2 j8 U: X: V& k& o
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) ! J% ]# f8 t) F2 ]
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) 2 V5 Y- A2 |6 b9 V8 Q7 |
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) ) H% a0 [5 e/ T6 V5 J; @3 m4 `
     NULL(UIN、UN为字符) 4 H9 e! f; z3 o! s; J" X) Z, v' h* [
( ]+ n! Q7 x9 l, Y$ L5 ^
(5).发送验证 ; d% a6 i) p% x& ~3 E
  说明:1、如果你加对方为好友,你需要发送验证 - x2 M" K/ W# n7 A6 j! E
     2、对方加你为好友,发送了验证,你要通过或者拒绝
9 I" H* l1 T- e  t" U     这2种情况需要发送验证消息 " T1 Z, D, F0 e9 K( X
! g% C* ^  j$ \! f& U
  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
& q. Z' J& L1 n9 _: F  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。 * H7 J/ [) I3 @  N6 e% o- n, a

* e; {7 v# z9 ^( q: \+ n/ ^( k  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) 3 i5 F# _% H8 q8 Z/ I8 l8 D
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
& o2 d4 x! d8 u3 [/ y/ A     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
- g" F2 V7 ?& I5 B# g& ^6 I  v* @     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) ' r+ {: {( c8 _- G' u  i2 d. i
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
& S) t+ u8 q9 }% L( O! f* ?) m" n* {2 P3 |8 E. Q+ @+ F: l
(6).删除好友
7 ]& c) f$ F  I/ C- I  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 7 w6 U$ A" g8 e5 d
) a" \3 \/ {, B' l8 s
  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)
8 V* j+ u6 J- l, i3 g  a7 L$ r     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)
' ~! o+ W+ q' A/ R( u     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 1 Z" X  [: m$ i) s7 T
     NULL(UIN、UN为字符)
. v0 @& ^; ?7 Z+ k% c, A& L% L; _$ i# S; H! I
(7).改变状态
0 E- f9 C3 V% P7 o  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码 0 o7 Q! ^( X% D# e0 o* i
  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法 * d( h6 D2 X0 u$ q

/ H4 P/ P( R+ J4 Y  h( Z  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) - X2 R: Y/ l* Z8 O
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
* Z9 ^5 F' f% R1 _1 y; ]     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
& k2 `$ B- G5 J: m$ q7 l& Y  W     NULL(UIN为字符,ST非法) ' q; f. l7 `& K) Q! w% t4 {: d9 P* H

" }* O6 Z8 R9 r& C# V  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 % ]7 G. r! B! ?* n3 k6 v2 s; J: t
       同理,当你的好友改变状态,你也会收到一条系统信息。
1 U5 F) ^' M6 J( _  n$ }6 b  y0 \2 d; G8 g5 {( L5 W+ Q& z
(9).获得消息
5 x% S( M7 h3 m; J$ ?  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
) C+ G! {& Z% G$ M
2 H/ y, P4 o; d) }/ i5 Y. I  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容)
& U  u: G( }- W" A6 v. j; F$ l     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
) L# F6 _* G+ X' O, L     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
% b* }0 A1 J' v( }! O( n     NULL(UIN为字符)
" d+ Q$ l0 S) f9 y9 X  说明:关于MT: # h) A! K2 X  I0 a9 H' s* l
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友 ; d6 |( L  p; c7 x9 X3 z, c0 F
     关于MG:
- w' }( d" Z8 p, w       当MT=9时,MG为用户发送的消息内容
; N4 Y9 C2 H6 ~$ h       当MT=99时, 4 a, c+ z7 h5 ]& R/ P- A1 n# N  D
         MG=10(QQ_STATUS_ONLINE)表示对方上线   R/ w: H7 J$ K! }8 Y; _/ _
         MG=20(QQ_STATUS_OFFLINE)表示对方下线
4 Q6 G- U1 i) H6 ?         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态
1 n: z; Z! B7 T/ `8 ]       当MT=2时,MG为对方请求你验证的信息
2 F2 i1 h% G$ t1 t       当MT=3时,表示对方通过你的验证
% @7 o2 N7 l8 t2 o* E" f       当MT=4时,MG为对方拒绝你理由 6 {6 W- C9 w* ?$ `
' o5 t/ w: j5 q* u5 K! i3 `, a* e
(10).发送消息
+ z& [8 k, R6 {' R  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容
# e8 L6 z+ a! ^# G, S
9 M3 _. ^' M6 j* Y+ K/ G7 Q' e  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦) & }8 [  `/ e: O- ^8 s& S" _
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) 0 R6 i  a, D. a! z( Q
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
3 h+ Z6 V9 h# I, ^7 Y     NULL(UIN、UN为字符,MG含非UTF-8字符)
- P! h/ T8 E" ]$ f0 y1 ~  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: 9 g4 k$ v" y! i% j! ]) A  H
       你俩互为陌生人,且对方没有和你说过话
- G: Z& `4 U$ r6 d8 p9 o- |# h- p: P$ U7 ~       你在他的陌生人列表里,并且他没有和你说过话(没有验证)
; f3 K3 Z4 c% n     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
; u5 C, X! E1 l! e( k' U) ~     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
. p$ h! `, Y/ s: f9 u+ ^
0 }. m- f/ B1 @: f7 n(11).登出 $ _9 @. H( C( w& [4 J
  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号 0 m: J6 n; z& F9 b3 E  @3 }

# H( H' X, J% U9 E' e  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆) 7 y2 ?' n4 E4 Z0 I) E$ Y- {. Q
     NULL(UIN为字符)
: P8 y( r" q: q8 }' d# p
( a& E" [- A- Q: `- Y9 F" V5、总结 & F, @0 y0 u$ [! @8 i
, X- H* W4 p; Z; `! {/ V
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到
' P- U  B6 s: [  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
. y0 G5 `0 g  E4 _: ~+ A. q  本文撰写时间仓促,难免有误,希望各位不吝赐教
3 n3 ^9 ~7 Y- D3 T$ q0 |! G  q# ?7 V! K: X

/ i) l: d% x# u* @! \) U: VTrackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 18:03 , Processed in 0.040551 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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