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

QQ的HTTP接口探究

[复制链接]
发表于 2005-9-28 12:07:47 | 显示全部楼层 |阅读模式
作者:Hackfan
/ g  g+ p: {. L! c5 R+ o日期:2005.8.21凌晨
1 m/ M7 ~7 x6 c* h0 t& @" r联系:QQ:106814 Email:hackfan@vip.sina.com 1 G% Q/ h! C4 O1 f9 v$ p& s+ d
, T/ w# n; b  s3 ]. o4 u) V$ J, V
1、研究说明
9 I1 l3 M/ M7 _/ E, z
# ?* w; E  b& ^7 ]  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、收发用户消息、系统信息。 6 S$ y. ~  x! p: Y0 d. C" ]8 r% S
' t% n% x9 {8 c- \1 e9 W
  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。
9 K3 B! K3 T, P- U0 L+ S
# y( |1 ?9 ?1 }; _7 Y7 Z( b/ C) w2、接口说明:
! |$ C$ D9 I/ o7 A/ K& r7 m  W1 i  k
% k6 ]. y4 S2 C/ `4 R, E4 {# E  接口位置:tqq.tencent.com:8000
- W& G0 ~8 ^* P2 l0 s/ u6 q  通信协议:HTTP ) }: U3 g+ _3 G
  数据传输方法:POST ' ]) u8 Q6 b% O# I4 U+ o9 |
  HTTP请求格式:
! w% K& v+ Z0 S& F* D
+ q- H7 d9 y' R/ GPOST HTTP/1.1 + L# z1 m* S2 y: Z- g0 E
Host: tqq.tencent.com:8000 9 I: e2 ~2 {) M6 [
Content-Type: text/plain; charset=UTF-8
0 [" Z5 [; m# U) O1 s( kContent-length: 长度 ) \* O- _5 y% o
Connection: close 4 z" Y0 M- v( b

2 }4 u$ w  P% a数据
9 c9 ~: j, P+ A9 x! L% p# }5 p& N- v' r1 w5 ]( `5 Z  G6 a# M
  其中长度为 数据 的长度,数据的格式:
9 [5 K: D; E, F' Z) Y. C  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&....   ^9 R5 Z8 Z. U

. R3 e: Q% D4 m+ i; @# j$ L( G/ t  以上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还需要不同的参数,下面我就公布我的研究成果。 3 n1 A! a7 k. b5 w9 y

+ T5 k# Y2 d# O5 R& O! \" C: u3、研究方法:
0 w  B( N( m' N, O7 c: O' n2 f4 j1 C6 n8 r3 a
  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。 6 b% P# n) p+ n: P' V0 Z6 P8 ^
  下面我公布我探测的代码(PHP):
  1. <? + @  O5 D1 J' ~4 H" n4 P
  2. $uin = "QQ号";
    + H9 o1 l% ?6 [  ?3 A
  3. $pwd = md5("QQ密码"); 1 ^5 Y, e! X5 ~: B- }: A% Y4 Q

  4. 9 ?+ Z2 V/ ~& q- M: A" ~& Y
  5. //登陆测试 $ Z  c% o# P# H0 {1 ^4 X* D, F
  6. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; 7 P6 S8 z+ R. s/ a1 ]! P
  7. //注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信 ; V/ i2 K2 @( d4 j
  8. /******* 9 ^* k; I' ?+ r9 C
  9. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235"; - O5 i4 ^) N' C. R, x0 s7 d
  10. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235"; $ V6 s) c; U, h: \! x3 R
  11. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235"; 0 O1 [: X$ |9 G' c- n9 Y
  12. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";
    ) f' d- T1 S3 {) y  b
  13. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";
    5 L9 g0 I9 {8 _. G" _1 G1 a* J
  14. $poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679"; ' i* V$ ^* W6 L, S5 x! e
  15. *******/
    " }# {2 Y: a, U. s& s/ p  [

  16. % i# N# D# m/ k& Y- ?0 |/ K, {
  17. & Y4 m% ?: S0 }
  18. //得到好友列表
    8 c+ f& H* ^2 z$ g
  19. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin; : _- s9 g7 A0 Y
  20. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0"; 7 ~% A# n7 W  \1 D" T1 U9 y
  21. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    5 l9 c9 i. k; D0 k( `
  22. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; 3 U1 }  Y4 o7 w& M6 h
  23. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);
    , M% [7 D( {2 _2 c: z3 x
  24. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    9 A( R7 r& s: F( Q
  25. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ! E" C2 }2 u5 k5 v2 w0 d+ J. L4 m
  26. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0"; 0 f; s0 a. J) s% R) X
  27. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    $ ?( w# L& w4 n* h+ Y1 J0 y
  28. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    8 d6 ~7 v9 v6 s; ~4 z7 b7 H. W( M
  29. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0"; , _1 o; w2 u% |- u2 S$ d4 K
  30. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    - E* I" p9 G4 V* V" R( S
  31. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); 1 r2 I4 z# g8 Y
  32. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10); & S; {7 v" v) `
  33. $poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    ) ~7 N6 t" W; P5 H

  34. 6 N& Q: o$ y; d3 Q4 l8 O" v: q, u5 M1 s
  35. //得到在线列表 ; i6 b0 D$ X# M% y# u" \
  36. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin; , \0 ^1 v5 w2 r! s
  37. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";
    1 A2 z  ~5 ^4 g# X9 z+ Y7 S- n
  38. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";
    + m# T4 Z8 @% J6 Z
  39. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0"; - l2 ^$ h# }  T. @3 t& D
  40. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10); 1 ^/ x+ ^  l1 U; y+ s3 r4 v0 J: I
  41. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";
    9 D& w- R4 ~/ n) F! @
  42. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    ( m7 v" \4 x' P+ |9 F
  43. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";
    1 \" @: }: H: K5 T3 d
  44. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    % x/ B; y' l& ?7 j% P, L: U6 ?
  45. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    * C% a2 x# O% t! }% o) L
  46. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";
    & C7 ^, ^1 F: T! d2 L. L
  47. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    7 t4 g* U" }. B: W9 I
  48. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ; |, j0 w5 a$ B0 b
  49. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);
    ( [: t0 i  [+ H! b1 k( Z
  50. $poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";
    $ i! d" f% V" \% H/ U# N- u% L* @

  51. 4 @, N  H2 ?5 C' ]
  52. //查看好友信息 2 y$ n! x& x) L. m8 W+ ~9 p
  53. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";
    9 V  Z: i/ y- H3 b: i% E( ^
  54. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814"; 0 s1 V" s7 g9 F0 N' s( Z: R
  55. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814"; ' ^' ?  `& K+ I2 h  ]- P
  56. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";
    ' `. p# E8 t0 P9 l+ ^8 X2 f
  57. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814"; ! e7 u# U! {* x9 z( `
  58. $poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";   O4 C: m! }0 Y

  59. 9 t1 c$ h- u. ^) t$ p* k, V
  60. //增加好友
    & I, s* |' |# m5 q! x
  61. $poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";
    ) B- m0 w6 I+ [1 G3 t# O+ x

  62. 9 h6 l. G+ J3 H9 z" v- I
  63. //发送验证 2 {7 E- E; D) p0 d# l' G
  64. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";
      J+ b" Y) n1 m3 O
  65. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST"; 3 A0 {( x# H" o1 N7 y
  66. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST"; # v& Y: w. d3 q+ B! m; Y
  67. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";
    5 C: C: `4 H5 Z5 Z: X' N! f. A
  68. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";
    / ^2 A" [" V( i/ m
  69. $poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST"; & \& q+ g9 V: `! C' t6 A' g
  70. 2 T- B5 W2 Y. f1 T5 L7 B! `3 y$ b' s
  71. //删除好友 . k% b3 M  F" Q+ D0 P& O9 L
  72. $poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814"; 8 l; e3 W. [1 v4 H
  73. 0 V- {' [: ^% X5 \. `" X- N
  74. //改变状态
    5 G* o) t7 y5 w3 S
  75. for($i=0;$i<=60;$i=$i+5)
    0 d7 u( s6 s  Z
  76. { / H) `3 v4 @  Y6 L- s9 F
  77. $poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;
    ) x" G3 z7 @- [
  78. } + X* X! ?/ Q, V+ k# \

  79. 1 g5 B4 Y) ^% J5 I2 _. K- r0 G% A
  80. //获得消息 * S" V1 z. i9 V& e' Q
  81. $poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    , ]$ ~+ g/ ^. Q8 C8 p
  82. ! L0 E2 d, k! n! T* f6 r7 g+ c
  83. //发送消息 $ @' P. g; q- ^8 n* s; j
  84. $poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";
    ' `# T! X" p5 S
  85. 1 n, m6 G7 A& B
  86. //登出 $ W( g0 p' F9 o  @
  87. $poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";
    " Y1 a/ O1 {# @) r0 F# y' \
  88. ' z+ D2 A# ~& `1 w, p9 O& h
  89. $file = fopen("p.txt","w"); 3 C. [$ @3 M, V3 j' m2 K6 J' n

  90. 3 X' {- I" R* o( S# g; N
  91. foreach($poststring as $k=>$v) ; _& w+ a2 U% N/ B/ u8 Q
  92. { * i" L: D$ h5 K' W" d1 [  z" C. U
  93. ss_timing_start();
    9 P/ j2 ~. U7 D# j2 z
  94. $fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10);  ( f9 h2 c2 N8 N: q. H% k+ A$ r

  95. 7 h% w  J* b7 b6 B
  96. if(!$fp){  
    8 p: Q0 G3 }' m3 p. K, L; B1 Y
  97. //error tell us  
    + O( P) H7 C3 m+ P1 U
  98. $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)";  9 z7 W) C5 l8 \
  99.    : O/ _' V- v) M- h' E6 q5 R
  100. }else{  
    9 j" f, i- ~7 _
  101. - W! Y: j, i% `: m9 b4 _7 ?- V3 Z
  102.   //send the server request  + f* r, P& C" a6 Q: [  t: H5 @
  103.   fputs($fp, "POST HTTP/1.1\r\n");  $ ?: m5 g/ l6 G  V# ~/ e8 x
  104. //  fputs($fp, "Host: $host\r\n");  , Q  |3 [6 Q1 o4 W+ |* |; w
  105. //  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");    H1 E/ v2 D  x5 u
  106.   fputs($fp, "Content-length: ".strlen($v)."\r\n");  
    0 a) P- k5 t3 }0 k5 G8 T
  107.   fputs($fp, "Connection: close\r\n\r\n");  
    8 }5 O  p4 o, Z% N* q
  108.   fputs($fp, $v . "\r\n\r\n");  7 m  \/ G) v+ U7 _& t" M' D
  109. 0 H; q. u1 }6 r7 Q4 W
  110.   //loop through the response from the server  
    7 s6 N3 Z' G% K  f* j
  111.   $res = "";
    3 x2 F$ K4 U& H' D
  112.   while(!feof($fp)) {  
    4 G8 W- ]+ B9 [# g. V
  113.   $res .= fgets($fp, 4096);  
    2 P3 n+ ~! r6 ]9 @  b' c8 k8 P
  114.   }  
    6 v/ Z0 B2 u( l! F1 N) p
  115.   //close fp - we are done with it  
    8 A, H3 D( G, _  ~: S/ o# i% v
  116.   fclose($fp);  
    % _; j; G9 S, m' W; z; q5 I

  117. , d) n: i+ m7 M4 T* N% f
  118.   $content = $v.chr(13).chr(10).$res;
    2 ?, r0 _& F9 ~
  119. }  
    " I) I0 v1 G% T8 ^1 ~
  120. ss_timing_stop();  
    ( q: V4 V: F% E0 b9 V0 {
  121. $content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10); * z! R$ B: Q8 c
  122. fputs($file,$content); , k2 S3 S, u! o6 D. w6 {$ e; s! l7 m
  123. }
    / \: ], K8 h- j! G; ~6 P' }
  124. fclose($file); / S/ [, j# ?% C- ]! |
  125. ?> 7 C* `1 E. V7 u$ t
  126. <?
    * Q4 z, m1 E6 {( {# F% U3 W( b) e
  127. function ss_timing_start ($name = "default") {  
    + ]8 a1 A: v  t" X; q1 ]' n
  128. global $ss_timing_start_times;  " t; D' p* [: x* c" `, P1 {% }
  129. $ss_timing_start_times[$name] = explode(' ', microtime());  
    2 O9 N1 f5 }" f4 ]
  130. }  8 x0 v. w4 }2 t4 w3 i
  131. function ss_timing_stop ($name = "default") {  
    & D4 ~7 b6 c; N3 H% I5 _
  132. global $ss_timing_stop_times;  $ N& C  w$ Z+ M& E! U9 ?: x3 @
  133. $ss_timing_stop_times[$name] = explode(' ', microtime());  
      }/ {& ?/ {6 x2 U2 d
  134. }  
    / F6 _1 v: S5 k! E9 h2 t
  135. function ss_timing_current ($name = "default") {  
    ; Q6 t4 i& `4 ?& o* V! b2 f
  136. global $ss_timing_start_times, $ss_timing_stop_times;  0 Q! [# {* u) Y' s5 f8 q/ f
  137. if (!isset($ss_timing_start_times[$name])) {  
    / @# x' ?' M1 f3 u0 u8 e5 Z
  138. return 0;  0 s8 N( _; a1 d0 ?
  139. }  
    $ T- y# b* M3 J5 _1 W: S1 e, o
  140. if (!isset($ss_timing_stop_times[$name])) {  8 j& s" d1 w2 u* R! d6 U
  141. $stop_time = explode(' ', microtime());  
    # [$ c5 \. l# u9 x
  142. }  ; U/ y6 _8 ^; h
  143. else {  
    - c+ i& v+ Z% d  E$ Z
  144. $stop_time = $ss_timing_stop_times[$name];  
    . D, I2 z/ u; x7 P
  145. }  
    $ P5 j2 G% {. P. q1 N. K1 s; z
  146. $current  =  $stop_time[1]-$ss_timing_start_times[$name][1];  8 I2 }, [0 c4 I  o6 p. E" c1 D. y
  147. $current += $stop_time[0]-$ss_timing_start_times[$name][0];  $ N9 f' \! {1 Z+ k
  148. return $current;  $ N7 |5 m) `% [0 P7 N2 Y
  149. }  
    * w5 o6 H4 I# v9 i. C3 o$ s
  150. ?>
复制代码
; [1 D9 F% `. g; \: K* o& ^
4、研究成果: ( q1 Q& Z; W1 ]" k9 |% g" Y

& Z6 Z+ x! R* q' G: u3 Q& X& _% [(1).登陆
$ k. ]5 `& ]) t  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES= 20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影响,就是因为有参数UIN。 3 h" M# j, E+ S+ d4 K) |
  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^ % N) ~% {: X3 e; A
8 _7 x$ @4 z8 J; P
  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235 8 s$ v, j# f' \3 }6 J  ~
  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;   d$ t% d/ u1 f& V
     M5这个参数的作用还不清楚,但最好为1。 6 q5 `  V* p$ Q! H' p* ~% r7 {8 n8 B
     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。
. Z& w$ q) r. _, e% x, E" R2 p6 E' J
  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)
, L! m5 a, U1 {: E" m9 g& |$ B$ k     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)
1 U# |$ }; ?% Z: C8 a7 C- h8 p/ ?     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100) 8 P* D0 f7 c( t7 _! i& Z) q
     NULL(UIN为字符、PS为空、LC错误) # t5 m+ |  l" [% @: L. I$ z$ y

8 K7 g9 I! z, f- M3 L; W8 v9 T: C(2).得到好友列表
  S+ @, s. E6 o  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0 7 P$ z- e  a  j* h  ^4 H
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 9 X5 q+ }( S$ V

" a: p+ q. a# R1 Q  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数) / ?- i- T' f9 L* i; Q
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN= 1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割) $ X2 Y" v4 a( y8 k, `
     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 5 R& E( u+ Y' T; C# C
     NULL(UIN、TN、UN为字符) 1 [/ X+ f$ I# J- C- K1 J. D2 a

, M" j# p4 w8 ~(3).得到在线好友列表 " z1 |0 ?) w4 n# Z7 C; S) `
  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0 : d8 F$ R' a/ ~  Q; E4 s2 s, t; N
  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响 6 i# K) {% r* D

) X  Y0 P2 i% R6 A$ n+ E  返回: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 r, s4 s/ }% x! B     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) + |' k/ t% @. z, z% C. b% d
     NULL(UIN、TN、UN为字符) 7 C/ K/ x3 i6 K/ S$ n
  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1; & Z% Q3 v) x2 `( p" W; R0 g
     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌; $ c4 m# S1 h; [' _5 T
5 p' b6 A6 C, o$ b+ I$ I+ |: L; A
  特别说明:当参数TN=0或不存在时,服务器返回:
8 N( g+ i4 E* mVER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号
9 C- x/ N. l; h# s" r* GHTTP/1.1 200 OK $ q7 O9 q( n1 y
Server: tencent imserver/1.0.0 0 h! W& w2 g! L" Y/ ^+ `  I
Content-Type: text/plain; charset=UTF-8 ' h4 `$ w) f9 m9 E8 Q, ]3 H4 s
Content-Length: 56
/ x( g1 [. X* F; t
6 x# |& N2 b: _& bVER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1
) F' U8 ]4 m: i- w& u, HHTTP/1.1 200 OK ' X2 O4 v2 ^& n( w4 [9 T
Server: tencent imserver/1.0.0 4 x" C( l* c( j1 Y& q! \* g. p
Content-Type: text/plain; charset=UTF-8
' y8 t+ G0 I( E% U" A* r. o: n2 xContent-Length: 77
( ?/ Q9 T! k: @* ]( {" {3 s3 t4 g: u# x0 `5 |. b) B3 U- r
VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=
& A- z* G# Y" b& v  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。   e. S  `& P* V; ~5 m, M; H+ t
3 v8 Y  i$ h2 T
(4).查看好友信息 . L7 `) O3 x0 q. @+ H' @7 O+ w
  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码
, L* W  j- m2 [3 D2 W  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询
4 r* |5 I) w0 _# E2 {
6 U& ?* s' d' _0 S& f2 d  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)
8 W% y4 |; j; l1 ?" l& @' c+ _     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=学生
' P" I/ o* g. E4 I&LV=2&PC=邮编&PH=电话&PR= The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC= 毕业院校&SX=0&UN=106814&NK=Hackfan  4 L; T, b& v% m: U9 w  p; D, t
好(普通查询)
8 s% L4 O0 t3 v7 G0 c- d     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD =地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国
! ]% u6 Y  l2 k) [2 D&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  
/ u8 i0 h8 f9 L5 N8 Y, @0 gupdating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)
& `' z' C" E6 H& d, |2 L3 j  ~* n     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
; U5 c) u5 C( _# K& {2 T) x     NULL(UIN、LV、UN为字符)
0 J* S  M) N7 `4 E
  C% e/ _9 _2 P8 E! n  说明:AD为联系地址 # [; u9 C: D  {
     AG为年龄
2 [% m  r/ D8 \     BT为血型
, |- c* |4 V% {# D: @     CO为星座
7 ?3 Y) o% P$ z     CT为城市
8 `! S1 f2 a) c) M     CV为未知*
3 J2 H: ^+ D9 }, R" t     CY为国家 & U5 l- h$ ^: _3 |
     EM为Email # D- g0 s' F- A! J
     FC为头像 % ]/ ]# g" v0 ~  Y/ c6 h+ C
     HP为网站
! d1 S4 ^# m8 c" i     ID为未知
& h) M+ L: L. f4 n     JB为职业
5 y7 p  H9 s) \3 O     LV为查询代码(就是发送的LV)   X( [% N9 P6 `" n, J# F! e1 A
     MO为移动电话 & p- `1 B+ z6 N
     MT为未知 / K/ H2 v6 I9 Y" o: d' o
     MV为未知
- p7 q; D" O! l7 v& p" j) F4 j  L     PC为邮编 + E/ P7 K! X  j9 C% \9 F
     PH为联系电话 ( N' [0 q8 n) t" n: u
     PR为简介
+ Y- n: j4 w  ~5 E8 a     PV为省 ; K8 H3 e! C% j+ I7 d0 J+ H0 w
     RN为真实姓名 ' Z: m+ \% b8 Q0 c' r% ^8 y1 ]
     SC为毕业院校 ) p$ U% d( v; o* }8 E9 M+ I
     SH为生肖
' h/ F  g( _% i* _3 J8 r! V     SX为性别 . q  ~& q6 q' a8 @# K1 n
     UN为QQ号 # H+ z4 U2 O+ b1 Z0 l( ]
     NK为昵称
6 R1 m# |* o: B$ u9 Z4 s1 n3 h$ w4 O  Q! C
     血型:0 => '',
5 Z2 N4 @( q) V4 `" t        1 => 'A型', & V2 J0 b6 D! `9 e9 N' L" b% H
        2 => 'B型', 9 |* Q6 l2 b) `$ n: g
        3 => 'O型',
- s/ d. n+ P4 u. a4 l/ N! Y& P        4 => 'AB型',
. _7 t/ Q! q5 ?8 p& y' ?1 p        5 => '其他'
% S% [# r$ R" l% s
; N0 g9 g: z( b9 {7 s: k+ k9 @8 n3 i5 N; E
     星座:0 => '', 3 g8 @- O/ V, z  j$ k/ k$ h2 d$ `
        1 => '水瓶座', / y3 A9 ?$ b' k; Y
        2 => '双鱼座',
/ u/ i% L( E4 w' I2 u$ N, A0 E$ W' U        3 => '牡羊座',
  W# g8 Q- L  K7 _( ~* c        4 => '金牛座',
( s% B+ }: C. ]- P6 b( L  u1 s8 j        5 => '双子座',
5 }) A  j# S3 q4 n" }        6 => '巨蟹座',
  j# i0 Z* J" E        7 => '狮子座', + t6 Z) m( \' c
        8 => '座',
2 K( r6 G( b0 ]# k& h! \4 d# Q        9 => '天秤座',
8 K( t$ d2 v* t: Y# }6 ?( H) [8 s+ g        10 => '天蝎座',
5 Y5 Y5 E6 d$ O" K6 L        11 => '射手座',   v& a( F- \1 ^' b! ~
        12 => '摩羯座' 6 l& F& N1 c# }; C# M* t
5 \9 U- j  B9 n& ]+ q: H/ V$ u
     生肖:0 => '',
# i  Q- K$ M! o# i& {  `) y        1 => '鼠',
/ o0 u: E7 j* h1 F5 {, l/ N) P4 V' \        2 => '牛',
" C- `8 W% @# X& l+ M  f' q8 t        3 => '虎', ! D7 y. G, J! ^; x+ i+ h& Z4 v
        4 => '兔',
! x; q+ c2 V+ C+ z! s1 n        5 => '龙', 9 r" k6 ^, A: g& t8 ]" l  ]5 [2 ]) c
        6 => '蛇',
0 F' }3 h8 \- |. u# `, g        7 => '马',
" @* V/ N" t. v3 p2 @0 ~- l  f1 d' C& w        8 => '羊',
! q9 e9 S! L; _        9 => '猴',
. E  X* Z! X6 Y        10 => '鸡', ; y5 n7 o) \  i4 k! o
        11 => '狗',
4 U- c+ Q0 u( E2 S, \        12 => '猪' 1 A( b* B! O! y. U) S% ^  I

5 b8 {3 t$ H! Y, }     性别:0 => '男',
# p: X& @  B+ L  R# A        1 => '女'
8 |$ d" I" k2 a' r( d7 ~1 n
2 R; w! k2 o4 L* M(5).增加好友
- g3 u2 _: D: H: A  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号 4 |4 R& I( J1 ~

5 a; f- H) q5 W# G  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友) $ V% ?2 I- O2 |  b- D
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证) + z5 F. G, q! N/ Q: }, r' S6 g6 X
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友) - I0 z6 p. m# S, \/ ?$ ]
     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) # l. l! ^5 t5 ?0 V% u. e& H) y
     NULL(UIN、UN为字符) 7 I  v. {+ f- @7 t8 Y
+ R9 F8 i( D% Y- j- c2 I
(5).发送验证
9 _/ |! b5 b; Q- ^' K  说明:1、如果你加对方为好友,你需要发送验证
" B9 v7 A% p) ]$ h4 Y& Z8 j     2、对方加你为好友,发送了验证,你要通过或者拒绝 2 h! o- W& j+ z  Y3 ^5 {
     这2种情况需要发送验证消息 2 X( L$ p2 _: A" u

3 \$ W* D7 Y# R+ P, F& R' K% L  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由
8 d/ T8 a6 P( v: n( x  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。
/ I" q- E; R5 M# t+ j2 Z& W9 W
, c3 i; _7 [2 V! @  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功) : w3 z% U' l% F4 j! {: J% [  m
     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)
+ ]! N( }6 S, H1 B- n: z6 @4 F     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
# z) i5 a9 i3 ?: G+ D  b! {% j     NULL(UIN、UN、CD为字符,RS为非UTF-8字符) 9 q  a+ h3 N* R( v4 a% r# Z
  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。
/ N( {% s7 Y% i" W" ~- H* _
% M* C: R, o  ^6 U4 ^3 S# U9 s% m(6).删除好友 ' x0 C% g# m& n
  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号 8 x0 U/ t& V& C: i

+ N% V# m% v5 O- R( @; [  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功) ; x& l  }8 s3 X
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果) 8 R& ^" w8 M1 i7 p
     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
0 [# }- @( e% y$ N1 ?. M4 ]4 l8 b9 d5 @     NULL(UIN、UN为字符)
" Y* b  m2 Y" z0 e8 Z" M) m5 T9 r
5 W- P! F% f+ a  g(7).改变状态 # \- L2 b+ b$ ^  H0 _
  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码
, V  p2 }: B) K2 L( m  ^+ z2 \' g' X7 J  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法
8 @4 K! N4 E7 `% q% n! A
) f, [* Y9 P( A  g* z  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功) ( S0 s5 P, \8 U0 U
     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)
" `: ]( d* C# k6 F* ~  r( n     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆) 3 h. e' p0 V- u3 n% w
     NULL(UIN为字符,ST非法) % o  Q: e( i6 O0 o6 N$ {' i

* X% F6 M" Y- v8 W1 D* C  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。 * g4 B5 W, o% m( d3 P% {4 d
       同理,当你的好友改变状态,你也会收到一条系统信息。 ) C: t% i; M. C, \) k

. L$ t/ k+ W8 ^0 I(9).获得消息 ' h: k9 W0 e6 j% X2 B+ f
  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号
& _0 v9 K( `. @/ n
# g' \: u+ |  ^6 ?' U) G8 ~  返回: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的值用","分割,分别表示消息类型、发送人号码、消息内容)
# g3 n8 a  Q" i' a% z+ ^     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)
5 Y; d, S. m9 V1 |; X     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)   D9 r% _+ B  T& r8 r# {+ O
     NULL(UIN为字符) 5 y4 p7 B+ ~! A3 V' a
  说明:关于MT: + u$ o* D' g- i* @0 }% O
       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友
; M  p4 u$ E' A  i     关于MG: 6 d9 e# v5 q9 b
       当MT=9时,MG为用户发送的消息内容 2 ]' r4 V& N' j: Y5 h& n6 a1 `/ m
       当MT=99时,
3 F7 I) J8 t/ w! {         MG=10(QQ_STATUS_ONLINE)表示对方上线 2 O* v' Z+ ^, K
         MG=20(QQ_STATUS_OFFLINE)表示对方下线
% q: S" p0 Y' j) K+ R: E         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态 " t% i! n# P  p' u* J9 \* s( b
       当MT=2时,MG为对方请求你验证的信息 - J; m$ j& b+ n6 p
       当MT=3时,表示对方通过你的验证 % d' o! ]/ F: S% j
       当MT=4时,MG为对方拒绝你理由
3 Y% k. w- R0 m4 W& K, Z9 X" k
7 y! @: L0 @5 {3 M, O3 ^4 z(10).发送消息 % l* j8 b  M7 l% i
  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容 8 U. \1 q/ h' R0 h% Z

1 X3 Y7 v7 E0 |( h: s0 n  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)   L7 }4 ]' ]7 f/ Q7 w9 @' w
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快) * m* |/ P3 T8 c/ u$ Z
     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
% ^( I9 c+ D8 }3 }+ h     NULL(UIN、UN为字符,MG含非UTF-8字符)
" o  |3 i5 S  n% i9 e  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息: / S/ B1 w: [$ e3 |! k0 L& }
       你俩互为陌生人,且对方没有和你说过话 ' n; c( ]) h: p3 }; @8 e( [& q9 Q
       你在他的陌生人列表里,并且他没有和你说过话(没有验证) 1 M* U1 t5 H0 L9 u- y/ b
     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s
) w/ p4 Q/ e+ ~3 [     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL
( X0 b; g% ?3 T: ?, r
/ T9 e' i# y: |- y% ?(11).登出
7 p3 c6 W: @+ _1 Y! |% A. F; k  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号
; W- ]" w9 v, ?& C0 V; |  V
# V, J8 `0 f5 {3 b! J  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)
0 Y7 [; J  _; G     NULL(UIN为字符) ' U1 w9 R! Y% g

: t8 s* L' s6 n; N/ X- j3 }5、总结
$ e( `0 B6 K$ u; u  {/ B3 v  F2 C+ T" |* ]6 ^3 A7 r+ j
  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到 0 C8 h' q" o1 {( o! w1 m; E
  http://blog.hackfan.net/index.ph ... d=a_20050819_223558
+ Y8 M5 G1 ^+ m' o6 J  本文撰写时间仓促,难免有误,希望各位不吝赐教
4 A+ `+ V* p& m& _! K! e  l; o0 \' L8 v/ S7 {
2 P4 a2 A, M* D# L* k% C) M) O3 D, N
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=520301
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 08:41 , Processed in 0.019777 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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