1. 程式人生 > >C#微信公眾號開發 -- (三)使用者關注之後自動回覆

C#微信公眾號開發 -- (三)使用者關注之後自動回覆

通過了上一篇文章之後的微信開發者驗證之後,我們就可以做微信公眾號的程式碼開發了。

當我們點選關注某個公眾號的時候,有時候會發現他會自動給我們回覆一條訊息,比如歡迎關注XXX公眾號。這個功能其實是在點選關注的時候,使用者觸發了微信定義的事件,同時微信會返回給我們一個XML資料包,微信官方的解釋如下:

推送XML資料包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>

引數說明:

引數 描述
ToUserName 開發者微訊號
FromUserName 傳送方帳號(一個OpenID)
CreateTime 訊息建立時間 (整型)
MsgType 訊息型別,event
Event 事件型別,subscribe(訂閱)、unsubscribe(取消訂閱)

 從示例中可以看出,如果我們想要處理使用者點選的關注事件,那麼必須要知道訊息型別MsgType,事件型別Event。所以我們可以仿照著微信給我們的XML示例用C#建立一下事件接受的類,具體程式碼如下:

複製程式碼
public class wxmessage
    {
        /// <summary>
        /// 本公眾帳號
        /// </summary>
        public string ToUserName { get; set; }
        /// <summary>
        /// 使用者帳號
        /// </summary>
        public string FromUserName { get; set; }
        /// <summary>
        /// 傳送時間戳
        /// </summary>
        public string CreateTime { get; set; }
        /// <summary>
        /// 傳送的文字內容 
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 訊息的型別
        /// </summary>
        public string MsgType { get; set; }
        /// <summary>
        /// 事件名稱
        /// </summary>
        public string EventName { get; set; }
        
        //這兩個屬性會在後面的講解中提到
        public string Recognition { get; set; }
        public string EventKey { get; set; } 
    }
複製程式碼

事件類建立完成之後,我們就可以在wxapi.aspx頁面中做事件處理的邏輯操作了,請看下面的程式碼:

複製程式碼
public partial class wxapi : System.Web.UI.Page
    {
        const string _token = "在微信公眾測試號後臺寫的那個Token";
        private const string _myOpenid = "你自己微信公眾測試號的appID";
        string postStr = "";
        protected void Page_Load(object sender, EventArgs e)
        {

            //************** 驗證成為開發者的時候將此程式碼註釋 ***********//
            //對微信的資訊進行處理和應用
            WXOpera();

            //***********  驗證成為開發者之後將此程式碼註釋 *************//
            //string httpMethod = Request.HttpMethod.ToLower();
            //if (httpMethod == "post")
            //{
            //    //第一次驗證的時候開啟
            //    FirstValid();
            //}
            //else
            //{
            //    Valid();  //如果不是post請求就去做開發者驗證
            //}
        }

        /// <summary>
        /// 驗證成為開發者
        /// </summary>
        private void Valid()
        {
            string echoStr = Request.QueryString["echoStr"].ToString();
            if (CheckSignature())
            {
                if (!string.IsNullOrEmpty(echoStr))
                {
                    Response.Write(echoStr);
                    Response.End();
                }
            }
        }

        /// <summary>
        /// 驗證微信簽名
        /// </summary>
        /// * 將token、timestamp、nonce三個引數進行字典序排序
        /// * 將三個引數字串拼接成一個字串進行sha1加密
        /// * 開發者獲得加密後的字串可與signature對比,標識該請求來源於微信。
        /// <returns></returns>
        private bool CheckSignature()
        {
            string signature = Request.QueryString["signature"].ToString();
            string timestamp = Request.QueryString["timestamp"].ToString();
            string nonce = Request.QueryString["nonce"].ToString();
            string[] ArrTmp = { _token, timestamp, nonce };
            Array.Sort(ArrTmp);     //字典排序
            string tmpStr = string.Join("", ArrTmp);
            tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
            tmpStr = tmpStr.ToLower();
            if (tmpStr == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 第一次驗證配置
        /// </summary>
        private void FirstValid()
        {
            Stream s = System.Web.HttpContext.Current.Request.InputStream;
            byte[] b = new byte[s.Length];
            s.Read(b, 0, (int)s.Length);
            postStr = Encoding.UTF8.GetString(b);
            if (!string.IsNullOrEmpty(postStr))
            {
                ResponseMsg(postStr);
            }
        }

        /// <summary>
        /// 返回資訊結果(微信資訊返回)
        /// </summary>
        /// <param name="weixinXML"></param>
        private void ResponseMsg(string weixinXML)
        {
            //回覆訊息的部分:你的程式碼寫在這裡
        }

        /// <summary>
        /// 微信操作
        /// </summary>
        private void WXOpera()
        {
            wxmessage wx = GetWxMessage();
            string res = "";
            if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe")
            {
                //剛關注時的時間,用於歡迎詞
                string content = "";
                content = "您好,歡迎關注XXX公眾號";                
res = sendTextMessage(wx, content); HttpContext.Current.Response.Write(res); HttpContext.Current.Response.End(); } } /// <summary> /// 獲取和設定微信類中的資訊 /// </summary> /// <returns></returns> private wxmessage GetWxMessage() { wxmessage wx = new wxmessage(); StreamReader str = new StreamReader(Request.InputStream, Encoding.UTF8); XmlDocument xml = new XmlDocument(); xml.Load(str); str.Close(); str.Dispose(); wx.ToUserName = xml.SelectSingleNode("xml").SelectSingleNode("ToUserName").InnerText; wx.FromUserName = xml.SelectSingleNode("xml").SelectSingleNode("FromUserName").InnerText; wx.MsgType = xml.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText; if (wx.MsgType.Trim() == "text") { wx.Content = xml.SelectSingleNode("xml").SelectSingleNode("Content").InnerText; } if (wx.MsgType.Trim() == "event") { wx.EventName = xml.SelectSingleNode("xml").SelectSingleNode("Event").InnerText; wx.EventKey = xml.SelectSingleNode("xml").SelectSingleNode("EventKey").InnerText; } return wx; } /// <summary> /// 傳送文字訊息 /// </summary> /// <param name="wx" />獲取的收發者資訊 /// <param name="content" />內容 /// <returns></returns> private string sendTextMessage(wxmessage wx, string content) { string res = string.Format(Message_Text, wx.FromUserName, wx.ToUserName, DateTime.Now.Ticks, content); return res; } /// <summary> /// 普通文字訊息 /// </summary> private static string Message_Text { get { return @"<xml> <ToUserName><![CDATA[{0}]]></ToUserName> <FromUserName><![CDATA[{1}]]></FromUserName> <CreateTime>{2}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{3}]]></Content> </xml>"; } } }
複製程式碼

其中:Message_Text屬性,是微信定義的傳送文字訊息格式,下面是微信官方給出的解釋:

文字訊息格式:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

文字訊息格式說明:
引數 是否必須 描述
ToUserName 接收方帳號(收到的OpenID)
FromUserName 開發者微訊號
CreateTime 訊息建立時間 (整型)
MsgType text
Content 回覆的訊息內容(換行:在content中能夠換行,微信客戶端就支援換行顯示)

注:有的朋友可能會將這裡的ToUserName和FromUserName,與接收事件的ToUserName和FromUserName混淆,可能你看出來了sendTextMessage()方法中引數順序與Message_Text屬性中的順序不一致。

然後重新將wxapi.aspx頁面釋出到伺服器上面,隨後用自己的微訊號關注測試公眾號(掃描測試公眾號的二維碼),關注完成之後,如果你能看到:您好,歡迎關注XXX公眾號 ,則說明自動回覆設定成功!