天天看點

關于QQ一些功能的實作(一)類中定義的變量:構造一個QQ類執行個體的構造函數:實作QQ登陸的功能:擷取QQ好友清單:更新目前線上online_四個字元串數組中好友資訊的值:輸入一個QQ号,查詢這個QQ号使用者的資訊:添加好友功能:回應添加好友的請求:删除好友:改變QQ目前狀态(線上,離線,忙碌):給QQ好友發送消息:接收QQ消息:退出QQ:結尾

原文位址為: 關于QQ一些功能的實作(一)

        Update:代碼已經全部重構 2013-1-11

        在網上搜了很久關于騰訊的接口, 但資料很有限, 絕大部分都是重複的, 由于想實作一些比較好玩的應用, 我隻好根據手頭能搜到的資料進行實作了. 現在可以實作QQ登陸, 發消息, 接受消息, 加好友, 查詢好友資料, 更改QQ狀态, 查詢已添加的好友(隻能按QQ号排序, 擷取到前120名名單, 原因不明), 檢視某QQ使用者個人資料等功能, 可以給有興趣的同學們參考一下. 也請有這方面經驗的前輩們補充補充你們知道的其它功能:)

        原理是向騰訊http://tqq.tencent.com:8000 進行POST一個UTF8編碼的Byte[], 這個數組是根據各個功能的協定進行編碼的, 成功後傳回一個UTF8編碼的Byte[]數組, 是以我把這個方法抽取出來:

private void UploadData()
{
    try
    {
        pageData = _client.UploadData("http://tqq.tencent.com:8000", "POST", byteArray);
    }
    catch { }
}
           

類中定義的變量:

public string num;  //構造函數的QQ号碼
private string pwd; //構造函數的QQ密碼

public string[] online_Face = { "" };   //線上的頭像号碼
public string[] online_Station = { "" };    //線上的狀态
public string[] online_Number = { "" }; //線上的号碼
public string[] online_NameK = { "" };  //線上的昵稱

private WebClient _client = new WebClient();    //用來給伺服器發送消息的

private string postValues;  //發送給伺服器的字元串
private byte[] byteArray;   //把要發送的字元串變成字元數組
private byte[] pageData;    //接受伺服器傳回的字元數組
private string s;   //把傳回的字元數組變成字元串

public string[] MT;    //儲存資訊類型
public string[] UN;    //儲存資訊來源号碼
public string[] MG;    //儲存資訊内容

public bool is_RightLogin;  //判斷目前使用者是否正确登入
           

構造一個QQ類執行個體的構造函數:

/// <summary>
/// QQ類的構造函數
/// </summary>
/// <param name="QQ_Num">QQ号碼</param>
/// <param name="QQ_Pwd">QQ密碼</param>
public QQ (string QQ_Num, string QQ_Pwd)
{
    this.num = QQ_Num;
    this.pwd = QQ_Pwd;
}
           

實作QQ登陸的功能:

        協定:

VER=1.1&CMD=Login&SEQ=&UIN=&PS=&M5=1&LC=9326B87B234E7235

        解釋:

VER是用來說明QQ協定的版本,CMD是說明協定的指令,Login就是指QQ的登入了, SEQ是他的為了防止重複發送而設定的一個标記,可以取時間得毫秒值, 一個随機數也可以, UIN是說明你目前要登入的使用者QQ号, PS是MD5加密過後的密碼的值.
/// <summary>
/// 登陸QQ
/// </summary>
/// <returns>登陸成功就傳回True</returns>
public bool QQ_Login()
{
    postValues = "VER=1.1&CMD=Login&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7)
            + "&UIN=" + num + "&PS=" + MD5(pwd) + " &M5=1&LC=9326B87B234E7235";
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    if (Encoding.UTF8.GetString(pageData).Contains("RES=0&RS=0"))
    {
        is_RightLogin = true;
        return true;
    }
    else
        return false;
}
           

        QQ的MD5加密方法:

public static string MD5(string toCryString)
{
    MD5CryptoServiceProvider hashmd5;   //using System.Security.Cryptography安全.密碼系統
    hashmd5 = new MD5CryptoServiceProvider();
    return BitConverter.ToString(hashmd5.ComputeHash(Encoding.UTF8.GetBytes(toCryString))).Replace("-", "").ToLower();
}
           

        QQ登陸的傳回協定:

VER=1.1&CMD=Login&SEQ=&UIN=&RES=0&RS=0&HI=60&LI=300(這是登陸成功的一個例子)

        解釋:

RES為0表示成功傳回,RS為0表示登入成功, VER=1.1&CMD=Login&SEQ=&UIN=&RES=0&RS=1&RA=登入失敗

RS為1表示登入失敗,那麼就會出現提示資訊RA說明原因.

擷取QQ好友清單:

        協定:

VER=1.1&CMD=List&SEQ=&UIN=&TN=160&UN=0
/// <summary>
/// 擷取QQ好友清單
/// </summary>
/// <returns>傳回一個字元串數組,數組最後一個元素是空格</returns>
public string[] QQ_List()
{
    postValues = "VER=1.1&CMD=List&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=160&UN=0";
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (!s.Contains("&RES=0"))
        is_RightLogin = false;
    string s2 = s.Remove(0, s.IndexOf("&UN=") + 4);
    string[] QQ_Friend_List = s.Split(',');
    return QQ_Friend_List;
}
           

        傳回協定:

VER=1.1&CMD=LIST&SEQ=&UIN=&RES=0&FN=1&SN=&UN=

        解釋:

UN後面則是您好友的QQ号碼,每個号碼都由,進行分開, 我用string.Split(',')把值放入字元串數組中傳回了.

更新目前線上online_四個字元串數組中好友資訊的值:

        協定:

VER=1.1&CMD=Query_Stat&SEQ=&UIN=&TN=50&UN=0

        解釋:

獲得QQ好友線上名單跟獲得好友名單差不多,不同的是用的指令不同用的是Query_Stat
/// <summary>
/// 更新QQ類中目前線上online_四個字元串數組的值
/// </summary>
public void QQ_Query_Stat()
{
    postValues = "VER=1.1&CMD=Query_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=50&UN=0";
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (!s.Contains("&RES=0"))
        is_RightLogin = false;
    StringBuilder sb = new StringBuilder(s);
    sb.Remove(s.IndexOf("&FN="), s.Length - s.IndexOf("&FN="));
    sb.Remove(0, s.IndexOf("&FC=") + 4);
    online_Face = sb.ToString().Split(',');

    sb = new StringBuilder(s);
    sb.Remove(s.IndexOf("&UN="), s.Length - s.IndexOf("&UN="));
    sb.Remove(0, s.IndexOf("&ST=") + 4);
    online_Station = sb.ToString().Split(',');

    sb = new StringBuilder(s);
    sb.Remove(s.IndexOf("&NK="), s.Length - s.IndexOf("&NK="));
    sb.Remove(0, s.IndexOf("&UN=") + 4);
    online_Number = sb.ToString().Split(',');

    string ss = s.Remove(0, s.IndexOf("&NK=") + 4);
    online_NameK = ss.Split(',');
}
           

        傳回協定:

VER=1.1&CMD=QUERY_STAT&SEQ=9118265&UIN=634882287&RES=0&FC=12,&FN=1&SN=1&ST=10,&UN=6234238153,&NK=,

        解釋:

FC為QQ頭像的的ID,如的頭像ID為270,那麼其頭使用的圖檔為91.bmp,其算法為ID/3+1, ST為QQ使用者的狀态,10為上線,20為離線,30為忙碌, UN為線上使用者的QQ号,NK為線上使用者的QQ昵稱.ST,UN,NK,每個逗号隔開的資料互相對應.

輸入一個QQ号,查詢這個QQ号使用者的資訊:

        協定:

VER=1.1&CMD=GetInfo&SEQ=&UIN=&LV=2&UN=

        解釋:

UN為要檢視使用者資訊的QQ号.
/// <summary>
/// 輸入一個QQ号,查詢這個QQ号使用者的資訊
/// </summary>
/// <param name="search_num">輸入一個QQ号,查詢該QQ資訊</param>
/// <returns>字元串數組(聯系位址,使用者年齡,使用者郵箱,頭像,個人網站,職業,郵箱,聯系電話,簡介,省份,真實姓名,畢業院校,性别,QQ号,昵稱)</returns>
public string[] QQ_GetInfo(string search_num)
{
    postValues = "VER=1.1&CMD=GetInfo&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&LV=2&UN=" + search_num;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (!s.Contains("&RES=0"))
        is_RightLogin = false;
    MatchCollection matches = Regex.Matches(s, "&([^=][^=])=([^&]*)");
    List<string> Info = new List<string>();
    for (int i = 0; i < matches.Count; i++)
        Info.Add(matches[i].Groups[2].ToString());
    Info.RemoveAt(6);   //去除LV=多少, 這表示查詢方式,默然就是普通查詢
    if (Info[12].ToString() == "0")
        Info[12] = "男";
    else
        Info[12] = "女";
    string[] Inf = Info.ToArray();
    return Inf;
}
           

        傳回協定:

VER=1.1&CMD=GETINFO&SEQ=41707&UIN=&RES=0&AD=&AG=&EM=&FC=&HP=&JB=&LV=&PC=&PH=&PR=PV=&RN=&SC=&SX=&UN=&NK=

        解釋:

AD使用者的聯系位址, AG為使用者年齡, EM為使用者MAIL, FC為使用者頭像, HP為使用者網站, JB為使用者職業, PC為使用者郵編, PH為使用者聯系電話, PR為使用者簡介, PV為使用者是以的省, RN為使用者真實名稱, SC為使用者畢業院校, SX為使用者性别, UN為使用者QQ号, NK為使用者QQ昵稱

添加好友功能:

        協定:

VER=1.1&CMD=AddToList&SEQ=&UIN=&UN=

        解釋:

UN為我們要增加使用者的QQ号
/// <summary>
/// 添加好友功能
/// </summary>
/// <param name="fir_num">輸入一個QQ号,請求加為好友</param>
/// <returns>0表示已經加為好友,1表示需要驗證請求,2表示拒絕</returns>
public string AddToList(string fir_num)
{
    postValues = "VER=1.1&CMD=AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fir_num;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (!s.Contains("&RES=0"))
        is_RightLogin = false;
    MatchCollection matchs = Regex.Matches(s, "&CD=(.)");
    return matchs[0].Groups[1].ToString();
}
           

        傳回協定:

VER=1.1&CMD=AddToList&SEQ=&UIN=&RES=0&CD=0&UN=

        解釋:

CD為被加QQ的身份驗證狀态,CD為0表示"允許任何人把我列為好友"

CD為1表示"需要身份證認才能把我列為好友",CD為2表示"不允許任何人把我列為好友"

如果CD為0那麼資訊回饋後,使用者就直接加為好友了,如果CD為1,那麼還要發送一次回應加為好友的響應

回應添加好友的請求:

        協定:

VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&UN=&CD=&RS=

        解釋:

CD為響應狀态, CD為0表示"通過驗證", CD為1表示"拒決加為對方為好友"
/// <summary>
/// 回應加為好友的響應
/// </summary>
/// <param name="fri_Num">請求的QQ号碼</param>
/// <param name="agree_Type">0表示通過驗證,1表示拒絕對方,2表示請求加對方為好友</param>
public void Ack_AddToList(string fri_Num, string agree_Type)
{
    //WebClient _client = new WebClient();
    postValues = "VER=1.1&CMD=Ack_AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fri_Num + "&CD=" + agree_Type + "&RS=";
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (!s.Contains("&RES=0"))
        is_RightLogin = false;
}
           

        成功操作後傳回協定:

VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&RES=0&

删除好友:

        協定:

VER=1.1&CMD=DelFromList&SEQ=&UIN=&UN=

        解釋:

UN為你要删除的QQ号
/// <summary>
/// 删除好友,成功傳回True
/// </summary>
/// <param name="del_num">輸入一個QQ号,删除這個QQ好友</param>
/// <returns></returns>
public bool DelFromList(string del_num)
{
    postValues = "VER=1.1&CMD=DelFromList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + del_num;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (s.Contains("&RES=0"))
        return true;
    else
        return false;
}
           

        操作成功傳回協定:

VER=1.1&CMD=DelFromList&SEQ=&UIN=&RES=0&

改變QQ目前狀态(線上,離線,忙碌):

        協定:

VER=1.1&CMD=Change_Stat&SEQ=&UIN=&ST=

        解釋:

ST為要改變的狀态,10為上線,20為離線,30為忙碌.
public bool Change_Stat(string stat)
{
    postValues = "VER=1.1&CMD=Change_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&ST=" + stat;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (s.Contains("&RES=0"))
        return true;
    else
        return false;
}
           

        成功操作後傳回協定:

VER=1.1&CMD=Change_Stat&SEQ=&UIN=&RES=0&

給QQ好友發送消息:

        協定:

VER=1.1&CMD=CLTMSG&SEQ=&UIN=&UN=&MG=

        解釋:

UN是你的QQ好友, MG就是消息内容
/// <summary>
/// 向一個QQ号碼發送消息
/// </summary>
/// <param name="msgTo">輸入一個QQ号,向他發送消息</param>
/// <param name="msg">輸入消息内容</param>
/// <returns>成功傳回True</returns>
public bool QQ_SendMsg(string msgTo, string msg)
{
    postValues = "VER=1.2&CMD=CLTMSG&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + msgTo + "&MG=" + msg;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (s.Contains("&RES=20"))
    {
        is_RightLogin = false;
        return false;
    }
    if (s.Contains("&RES=0"))
        return true;
    else
        return false;
}
           

        傳回協定:

VER=1.1&CMD=CLTMSG&SEQ=标記&UIN=QQ号&RES=0&(成功發送,對方不一定能收到哦)

VER=1.1&CMD=CLTMSG&SEQ=标記&UIN=QQ号&RES=3(發送過快)

VER=1.1&CMD=CLTMSG&SEQ=标記&UIN=QQ号&RES=20(沒有正确登陸)

        解釋:

1. 當你發消息時,以下情形對方可能看不到(其實是收到了,QQ不提示)你發送的消息:

          a.你倆互為陌生人,且對方沒有和你說過話

          b.你在他的陌生人清單裡,并且他沒有和你說過話(沒有驗證)

2. 當你過快發送消息時,系統會給你一個懲罰,RES=3,相應時間20s

接收QQ消息:

        協定:

VER=1.1&CMD=GetMsgEx&SEQ=&UIN=

        解釋:

這個不需要解釋了, 看懂前面的協定, 這個肯定能看懂的, 呵呵
public void GetMsgEx()
{
    postValues = "VER=1.1&CMD=GetMsgEx&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (s.Contains("\r"))
        s =  s.Replace("\r", "\n");
    if (s.Contains("&RES=0"))
    {
        is_RightLogin = true;
        MatchCollection matches = Regex.Matches(s, "&MN=([^&]*)");
        if (matches[0].Groups[1].ToString() != "0") //判斷傳回的資訊數量是否為0條
        {
            matches = Regex.Matches(s, "&MT=([^&]*)&UN=([^&]*)&MG=([^&]*)");
            MT = matches[0].Groups[1].ToString().Split(',');   //資訊類型
            UN = matches[0].Groups[2].ToString().Split(',');   //資訊來源号碼
            s = s.Remove(0, s.IndexOf("&MG=") + 4);
            MG = s.Split(',');   //資訊内容
            //将消息内容進行轉碼
            for(int i = 0; i<MG.Length-1;i++)
            {
                MG[i] = MG[i].Replace("%25", "%");
                MG[i] = MG[i].Replace("%26", "&");
                MG[i] = MG[i].Replace("%2c", ",");
            }
        }
        else
        {
            MT = null;
            UN = null;
            MG = null;
            is_RightLogin = false;
        }
    }
}
           

        傳回協定:

VER=1.1&CMD=GETMSGEX&SEQ=&UIN=&RES=0&MN=&MT=,&UN=,&MG=,(正确傳回的)

VER=1.1&CMD=GETMSGEX&SEQ=标記&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示沒有資訊)

VER=1.1&CMD=GETMSGEX&SEQ=标記&UIN=QQ号&RES=20(沒有正确登陸)

        解釋:

關于MT:  9為使用者消息,99為系統消息,2為請求資訊,3為通過驗證,4為拒絕被加好友

        當MT=2時,MG為對方請求你驗證的資訊

        當MT=3時,表示對方通過你的驗證

        當MT=4時,MG為對方拒絕你理由

關于MG:

        當MT=9時,MG為使用者發送的消息内容

        當MT=99時,

                MG=10(QQ_STATUS_ONLINE)表示對方上線

                MG=20(QQ_STATUS_OFFLINE)表示對方下線

                MG=30(QQ_STATUS_BUSY)表示對方進入忙碌狀态

退出QQ:

       協定:

VER=1.1&CMD=Logout&SEQ=&UIN=

        解釋:

這個也不解釋, 非常簡單
/// <summary>
/// QQ退出登陸,并改變is_RightLogin為False
/// </summary>
public void QQ_Logout()
{
    postValues = "VER=1.1&CMD=Logout&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num;
    byteArray = System.Text.Encoding.UTF8.GetBytes(postValues);
    //向伺服器POST資料
    UploadData();
    s = Encoding.UTF8.GetString(pageData);
    if (s.Contains("&RES=0"))
        is_RightLogin = false;
}
           

        成功傳回協定:

VER=1.1&CMD=LOGOUT&SEQ=&UIN=&RES=0

結尾

        這些功能研究了兩三天, 代碼寫的不好的地方請各位大牛們指點指點. 本篇最主要的目的還是抛磚引玉, 希望關于QQ其它一些有意思的功能, 自己可以實作的, 歡迎各位高手前輩補充補充:)

        點選下載下傳 : 點選

        下載下傳位址: http://cid-07452800dc0167da.office.live.com/browse.aspx/.Public/Contact?uc=1

        轉載請注明: http://www.cnblogs.com/technology/ Create Chen

轉載請注明本文位址: 關于QQ一些功能的實作(一)