天天看點

微信公共服務平台開發(.Net 的實作)11-------客服消息(定項消息推送 重要的OPENID)

       這次我們來一起研究一下“客服消息”,首先明确一下“客服消息”的概念。這不同于之前的“被動響應消息”,也就是說并不是之前“你一言我一語的即時響應”,可能在某種情況下你需要給不同的人主動發送消息,例如你的餐館推出了新的川菜,那麼你需要給喜歡川菜的人發送消息,而并不是等着被人發送“有什麼新菜”後,然後回報給客戶,我推出了什麼什麼的。

       說道這裡可能有人會問,那不是群發嗎?微信不是每天隻能發一條嗎?服務号每個月發一條嗎?答案很明确微信說的是“客服消息”,也不是群發,它跟群發的差別就在于隻要關注了我,那麼我就可以群發給你消息,而為了不讓使用者感到讨厭,微信作了嚴格的群發條數限制。而“客服消息”則是隻有關注你的人向你發送了消息,你才能主動推送。就像打電話隻有人家問過你問題了,你才能回答,并且繼續跟進回答。再舉一個例子:你通過被人知道了我的手機号,存下來了,你突然給我打電話,我肯定是抵觸的。但是如果我給你打過電話,你通過來電顯示知道了我的号碼,以後再給我打電話,說明我們是認識的,我最少不會抵觸。這就使群發/被動響應/客服消息的本質差別。

       就像我們可以通過收集電話号碼,手機自己的客戶資訊一樣,一旦他們的資訊被我們收錄。那麼我們就可以突破群發條數的限制了,按照微信的限制群發一個月隻能一條(服務号),但是“客服消息”則可以一天50000條,足夠用了。

       下面的問題就是如何手機客戶的“手機号”了,微信裡面有一個OPENID,這就使手機号了,這個是關注你的使用者的唯一辨別,這個辨別是不會變的,但是同一個使用者關注不同的微信号,那麼他在不同微信号中的ID是不一樣的。如何取得OPENID呢?

       網上找了些資料,有的說的的确是錯誤的,有的還說要通過OAuth 2.0授權才可以,這個的确可以,但是太複雜了吧,通過我的測試得出了這樣的結論“隻要使用者和你的公共微信好發生互動”就可以取得他的OPENID了。就如同打電話一樣,隻要使用者給你打了電話,你一定知道他的電話了。在微信裡是這樣的:使用者隻要發資訊給你,或者點了某個菜單,發過來的資訊都會有一個“FromUserName”,這個就使OPENID了。我們可以建立一個資料庫來收集這些寶貴的使用者身份資訊,也就是記錄他的“電話号碼”,有了電話号碼,我們就可以以後經常與客戶主動打電話了。我做這樣的一個實驗:

       首先記錄使用者的OPENID在OnLoad函數第二行裡面加上一個 WriteLog(wx.FromUserName);把它記錄在一個文本檔案中

protected void Page_Load(object sender, EventArgs e)
     {
         wxmessage wx = GetWxMessage();
         WriteLog(wx.FromUserName);
         string res = "";


         if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe")
         {
             string content = "";
             if (!wx.EventKey.Contains("qrscene_"))
             {
                 content = "/:rose歡迎北京永傑友信科技有限公司/:rose\n直接回複“你好”";
                 res = sendTextMessage(wx, content);
             }
             else
             {
                 content = "二維碼參數:\n" + wx.EventKey.Replace("qrscene_", "");
                 res = sendTextMessage(wx, content);
             }
         }

         else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.ToLower() == "scan")
         {
             string str = "二維碼參數:\n" + wx.EventKey;
             res = sendTextMessage(wx, str);
         }
         else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "CLICK")
         {
             if(wx.EventKey=="HELLO")
                 res = sendTextMessage(wx, "你好,歡迎使用北京永傑友信科技有限公司公共微信平台!");
         }
         else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "LOCATION")
         {
             res = sendTextMessage(wx, "您的位置是經度:" + wx.Latitude + ",次元是:" + wx.Longitude+",地理經度為:"+wx.Precision);
         }
         else
         {
             if (wx.MsgType == "text" && wx.Content == "你好")
             {
                
                 res = sendTextMessage(wx, "你好,歡迎使用北京永傑友信科技有限公司公共微信平台!");
             }
             else if (wx.MsgType == "voice")
             {
                 res = sendTextMessage(wx, wx.Recognition);
             }
             else if (wx.MsgType == "location")
             {
                 res = sendTextMessage(wx, "您發送的位置是:" + wx.Label + ";緯度是:" + wx.Location_X + ";經度是:" + wx.Location_Y + ";縮放比例為:" + wx.Scale);
             }
             else
             {
                 res = sendTextMessage(wx, "你好,未能識别消息!");
             }
         }

       

         Response.Write(res);
     }
           

WriteLog的方法是這樣的:

/// <summary>
     /// 寫日志(用于跟蹤)
     /// </summary>
     private void WriteLog(string strMemo)
     {
         string filename = Server.MapPath("/logs/log.txt");
         if (!Directory.Exists(Server.MapPath("//logs//")))
             Directory.CreateDirectory("//logs//");
         StreamWriter sr = null;
         try
         {
             if (!File.Exists(filename))
             {
                 sr = File.CreateText(filename);
             }
             else
             {
                 sr = File.AppendText(filename);
             }
             sr.WriteLine(strMemo);
         }
         catch
         {

         }
         finally
         {
             if (sr != null)
                 sr.Close();
         }
     }
           

        這樣當客戶發送任何一種資訊給微信公共号,我們的log.txt檔案中就會記錄這個OPENID,我先打開Log.txt這個檔案看看OPENID号,我的事這樣的“oV93gjl5slD3p29yS1dOijy-pqZ8”,有了這個OPENID很多事情就都好辦了,以後我們還會介紹如何擷取客戶的資訊。這裡先說“客戶消息”吧。

        下面我們建立一個新的ASPX頁面,在這個頁面裡面我就可以給這些使用者發資訊了。這個頁面(SendMessage.aspx.cs)很簡單就使兩個文本框和一個按鈕:

string MyOpenID;
    string MyContent;
    protected void Page_Load(object sender, EventArgs e)
    {
        MyOpenID = "oV93gjl5slD3p29yS1dOijy-pqZ8";
        MyContent = "這是一個客服消息";
        UserName.Text = MyOpenID;
        Content.Text = MyContent;
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        string res = "";
        string Access_Token = IsExistAccess_Token();
       
        string posturl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + Access_Token;
        string postData = "{\"touser\":\"" + UserName.Text + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + Content.Text + "\"}}";
        res = GetPage(posturl, postData);
        
        Response.Write(res);
    }
           

       中間還用到了之前提到的3個函數:

public string GetPage(string posturl, string postData)
    {
        Stream outstream = null;
        Stream instream = null;
        StreamReader sr = null;
        HttpWebResponse response = null;
        HttpWebRequest request = null;
        Encoding encoding = Encoding.UTF8;
        byte[] data = encoding.GetBytes(postData);
        // 準備請求...
        try
        {
            // 設定參數
            request = WebRequest.Create(posturl) as HttpWebRequest;
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;
            outstream = request.GetRequestStream();
            outstream.Write(data, 0, data.Length);
            outstream.Close();
            //發送請求并擷取相應回應資料
            response = request.GetResponse() as HttpWebResponse;
            //直到request.GetResponse()程式才開始向目标網頁發送Post請求
            instream = response.GetResponseStream();
            sr = new StreamReader(instream, encoding);
            //傳回結果網頁(html)代碼
            string content = sr.ReadToEnd();
            string err = string.Empty;
            return content;
        }
        catch (Exception ex)
        {
            string err = ex.Message;
            Response.Write(err);
            return string.Empty;
        }
    }

    /// <summary>
    /// 根據目前日期 判斷Access_Token 是否超期  如果超期傳回新的Access_Token   否則傳回之前的Access_Token
    /// </summary>
    /// <param name="datetime"></param>
    /// <returns></returns>
    public static string IsExistAccess_Token()
    {

        string Token = string.Empty;
        DateTime YouXRQ;
        // 讀取XML檔案中的資料,并顯示出來 ,注意檔案路徑
        string filepath = HttpContext.Current.Server.MapPath("XMLFile.xml");

        StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8);
        XmlDocument xml = new XmlDocument();
        xml.Load(str);
        str.Close();
        str.Dispose();
        Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText;
        YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText);

        if (DateTime.Now > YouXRQ)
        {
            DateTime _youxrq = DateTime.Now;
            Access_token mode = GetAccess_token();
            xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token;
            _youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in));
            xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString();
            xml.Save(filepath);
            Token = mode.access_token;
        }
        return Token;
    }



    public static Access_token GetAccess_token()
    {
        string appid = "wx043225275885dafd";
        string secret = "cb4425b24ab79ef875029cf0bf326ae9";
        string strUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        Access_token mode = new Access_token();

        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(strUrl);

        req.Method = "GET";
        using (WebResponse wr = req.GetResponse())
        {
            HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();

            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);

            string content = reader.ReadToEnd();
            //Response.Write(content);
            //在這裡對Access_token 指派
            Access_token token = new Access_token();
            token = JsonHelper.ParseFromJson<Access_token>(content);
            mode.access_token = token.access_token;
            mode.expires_in = token.expires_in;
        }
        return mode;
    }
           

        這個頁面就是這些了,打開這個頁面然後發送消息試試?很不錯吧,這樣在配合上我們的資料庫啦,什麼循環了,就可以突破了微信群發的限制,做到定項的群發消息推送了!這裡面能發很多種消息:文本,語音,視訊,圖文,圖檔等等。隻是Json而已,聰明的你一定可以舉一反三的。

繼續閱讀