微信公共服务平台开发(.Net 的实现)11——-客服消息(定项消息推送 重要的OPENID)

这次我们来一起研究一下“客服消息”,首先明确一下“客服消息”的概念。这不同于之前的“被动响应消息”,也就是说并不是之前“你一言我一语的即时响应”,可能在某种情况下你需要给不同的人主动发送消息,例如你的餐馆推出了新的川菜,那么你需要给喜欢川菜的人发送消息,而并不是等着被人发送“有什么新菜”后,然后反馈给客户,我推出了什么什么的。

 

       说道这里可能有人会问,那不是群发吗?微信不是每天只能发一条吗?服务号每个月发一条吗?答案很明确微信说的是“客服消息”,也不是群发,它跟群发的区别就在于只要关注了我,那么我就可以群发给你消息,而为了不让用户感到讨厌,微信作了严格的群发条数限制。而“客服消息”则是只有关注你的人向你发送了消息,你才能主动推送。就像打电话只有人家问过你问题了,你才能回答,并且继续跟进回答。再举一个例子:你通过被人知道了我的手机号,存下来了,你突然给我打电话,我肯定是抵触的。但是如果我给你打过电话,你通过来电显示知道了我的号码,以后再给我打电话,说明我们是认识的,我最少不会抵触。这就使群发/被动响应/客服消息的本质区别。

 

       就像我们可以通过收集电话号码,手机自己的客户信息一样,一旦他们的信息被我们收录。那么我们就可以突破群发条数的限制了,按照微信的限制群发一个月只能一条(服务号),但是“客服消息”则可以一天50000条,足够用了。

 

       下面的问题就是如何手机客户的“手机号”了,微信里面有一个OPENID,这就使手机号了,这个是关注你的用户的唯一标识,这个标识是不会变的,但是同一个用户关注不同的微信号,那么他在不同微信号中的ID是不一样的。如何取得OPENID呢?

 

       网上找了些资料,有的说的的确是错误的,有的还说要通过OAuth 2.0授权才可以,这个的确可以,但是太复杂了吧,通过我的测试得出了这样的结论“只要用户和你的公共微信好发生交互”就可以取得他的OPENID了。就如同打电话一样,只要用户给你打了电话,你一定知道他的电话了。在微信里是这样的:用户只要发信息给你,或者点了某个菜单,发过来的信息都会有一个“FromUserName”,这个就使OPENID了。我们可以建立一个数据库来收集这些宝贵的用户身份信息,也就是记录他的“电话号码”,有了电话号码,我们就可以以后经常与客户主动打电话了。我做这样的一个实验:

 

       首先记录用户的OPENID在OnLoad函数第二行里面加上一个 WriteLog(wx.FromUserName);把它记录在一个文本文件中

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. protected void Page_Load(object sender, EventArgs e)  
  2.      {  
  3.          wxmessage wx = GetWxMessage();  
  4.          WriteLog(wx.FromUserName);  
  5.          string res = “”;  
  6.   
  7.   
  8.          if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == “subscribe”)  
  9.          {  
  10.              string content = “”;  
  11.              if (!wx.EventKey.Contains(“qrscene_”))  
  12.              {  
  13.                  content = “/:rose欢迎北京永杰友信科技有限公司/:rose\n直接回复“你好””;  
  14.                  res = sendTextMessage(wx, content);  
  15.              }  
  16.              else  
  17.              {  
  18.                  content = “二维码参数:\n” + wx.EventKey.Replace(“qrscene_”, “”);  
  19.                  res = sendTextMessage(wx, content);  
  20.              }  
  21.          }  
  22.   
  23.          else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.ToLower() == “scan”)  
  24.          {  
  25.              string str = “二维码参数:\n” + wx.EventKey;  
  26.              res = sendTextMessage(wx, str);  
  27.          }  
  28.          else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == “CLICK”)  
  29.          {  
  30.              if(wx.EventKey==“HELLO”)  
  31.                  res = sendTextMessage(wx, “你好,欢迎使用北京永杰友信科技有限公司公共微信平台!”);  
  32.          }  
  33.          else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == “LOCATION”)  
  34.          {  
  35.              res = sendTextMessage(wx, “您的位置是经度:” + wx.Latitude + “,维度是:” + wx.Longitude+“,地理经度为:”+wx.Precision);  
  36.          }  
  37.          else  
  38.          {  
  39.              if (wx.MsgType == “text” && wx.Content == “你好”)  
  40.              {  
  41.                   
  42.                  res = sendTextMessage(wx, “你好,欢迎使用北京永杰友信科技有限公司公共微信平台!”);  
  43.              }  
  44.              else if (wx.MsgType == “voice”)  
  45.              {  
  46.                  res = sendTextMessage(wx, wx.Recognition);  
  47.              }  
  48.              else if (wx.MsgType == “location”)  
  49.              {  
  50.                  res = sendTextMessage(wx, “您发送的位置是:” + wx.Label + “;纬度是:” + wx.Location_X + “;经度是:” + wx.Location_Y + “;缩放比例为:” + wx.Scale);  
  51.              }  
  52.              else  
  53.              {  
  54.                  res = sendTextMessage(wx, “你好,未能识别消息!”);  
  55.              }  
  56.          }  
  57.   
  58.          
  59.   
  60.          Response.Write(res);  
  61.      }  

WriteLog的方法是这样的:

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. /// <summary>  
  2.     /// 写日志(用于跟踪)  
  3.     /// </summary>  
  4.     private void WriteLog(string strMemo)  
  5.     {  
  6.         string filename = Server.MapPath(“/logs/log.txt”);  
  7.         if (!Directory.Exists(Server.MapPath(“//logs//”)))  
  8.             Directory.CreateDirectory(“//logs//”);  
  9.         StreamWriter sr = null;  
  10.         try  
  11.         {  
  12.             if (!File.Exists(filename))  
  13.             {  
  14.                 sr = File.CreateText(filename);  
  15.             }  
  16.             else  
  17.             {  
  18.                 sr = File.AppendText(filename);  
  19.             }  
  20.             sr.WriteLine(strMemo);  
  21.         }  
  22.         catch  
  23.         {  
  24.   
  25.         }  
  26.         finally  
  27.         {  
  28.             if (sr != null)  
  29.                 sr.Close();  
  30.         }  
  31.     }  

        这样当客户发送任何一种信息给微信公共号,我们的log.txt文件中就会记录这个OPENID,我先打开Log.txt这个文件看看OPENID号,我的事这样的“oV93gjl5slD3p29yS1dOijy-pqZ8”,有了这个OPENID很多事情就都好办了,以后我们还会介绍如何获取客户的信息。这里先说“客户消息”吧。

        下面我们建立一个新的ASPX页面,在这个页面里面我就可以给这些用户发信息了。这个页面(SendMessage.aspx.cs)很简单就使两个文本框和一个按钮:

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. string MyOpenID;  
  2. string MyContent;  
  3. protected void Page_Load(object sender, EventArgs e)  
  4. {  
  5.     MyOpenID = “oV93gjl5slD3p29yS1dOijy-pqZ8”;  
  6.     MyContent = “这是一个客服消息”;  
  7.     UserName.Text = MyOpenID;  
  8.     Content.Text = MyContent;  
  9. }  
  10. protected void Button1_Click(object sender, EventArgs e)  
  11. {  
  12.     string res = “”;  
  13.     string Access_Token = IsExistAccess_Token();  
  14.      
  15.     string posturl = “https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=” + Access_Token;  
  16.     string postData = “{\”touser\”:\”” + UserName.Text + “\”,\”msgtype\”:\”text\”,\”text\”:{\”content\”:\”” + Content.Text + “\”}}”;  
  17.     res = GetPage(posturl, postData);  
  18.       
  19.     Response.Write(res);  
  20. }  

       中间还用到了之前提到的3个函数:

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

 
  1. public string GetPage(string posturl, string postData)  
  2.    {  
  3.        Stream outstream = null;  
  4.        Stream instream = null;  
  5.        StreamReader sr = null;  
  6.        HttpWebResponse response = null;  
  7.        HttpWebRequest request = null;  
  8.        Encoding encoding = Encoding.UTF8;  
  9.        byte[] data = encoding.GetBytes(postData);  
  10.        // 准备请求…  
  11.        try  
  12.        {  
  13.            // 设置参数  
  14.            request = WebRequest.Create(posturl) as HttpWebRequest;  
  15.            CookieContainer cookieContainer = new CookieContainer();  
  16.            request.CookieContainer = cookieContainer;  
  17.            request.AllowAutoRedirect = true;  
  18.            request.Method = “POST”;  
  19.            request.ContentType = “application/x-www-form-urlencoded”;  
  20.            request.ContentLength = data.Length;  
  21.            outstream = request.GetRequestStream();  
  22.            outstream.Write(data, 0, data.Length);  
  23.            outstream.Close();  
  24.            //发送请求并获取相应回应数据  
  25.            response = request.GetResponse() as HttpWebResponse;  
  26.            //直到request.GetResponse()程序才开始向目标网页发送Post请求  
  27.            instream = response.GetResponseStream();  
  28.            sr = new StreamReader(instream, encoding);  
  29.            //返回结果网页(html)代码  
  30.            string content = sr.ReadToEnd();  
  31.            string err = string.Empty;  
  32.            return content;  
  33.        }  
  34.        catch (Exception ex)  
  35.        {  
  36.            string err = ex.Message;  
  37.            Response.Write(err);  
  38.            return string.Empty;  
  39.        }  
  40.    }  
  41.   
  42.    /// <summary>  
  43.    /// 根据当前日期 判断Access_Token 是否超期  如果超期返回新的Access_Token   否则返回之前的Access_Token  
  44.    /// </summary>  
  45.    /// <param name=”datetime”></param>  
  46.    /// <returns></returns>  
  47.    public static string IsExistAccess_Token()  
  48.    {  
  49.   
  50.        string Token = string.Empty;  
  51.        DateTime YouXRQ;  
  52.        // 读取XML文件中的数据,并显示出来 ,注意文件路径  
  53.        string filepath = HttpContext.Current.Server.MapPath(“XMLFile.xml”);  
  54.   
  55.        StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8);  
  56.        XmlDocument xml = new XmlDocument();  
  57.        xml.Load(str);  
  58.        str.Close();  
  59.        str.Dispose();  
  60.        Token = xml.SelectSingleNode(“xml”).SelectSingleNode(“Access_Token”).InnerText;  
  61.        YouXRQ = Convert.ToDateTime(xml.SelectSingleNode(“xml”).SelectSingleNode(“Access_YouXRQ”).InnerText);  
  62.   
  63.        if (DateTime.Now > YouXRQ)  
  64.        {  
  65.            DateTime _youxrq = DateTime.Now;  
  66.            Access_token mode = GetAccess_token();  
  67.            xml.SelectSingleNode(“xml”).SelectSingleNode(“Access_Token”).InnerText = mode.access_token;  
  68.            _youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in));  
  69.            xml.SelectSingleNode(“xml”).SelectSingleNode(“Access_YouXRQ”).InnerText = _youxrq.ToString();  
  70.            xml.Save(filepath);  
  71.            Token = mode.access_token;  
  72.        }  
  73.        return Token;  
  74.    }  
  75.   
  76.   
  77.   
  78.    public static Access_token GetAccess_token()  
  79.    {  
  80.        string appid = “wx043225275885dafd”;  
  81.        string secret = “cb4425b24ab79ef875029cf0bf326ae9”;  
  82.        string strUrl = “https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=” + appid + “&secret=” + secret;  
  83.        Access_token mode = new Access_token();  
  84.   
  85.        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(strUrl);  
  86.   
  87.        req.Method = “GET”;  
  88.        using (WebResponse wr = req.GetResponse())  
  89.        {  
  90.            HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();  
  91.   
  92.            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);  
  93.   
  94.            string content = reader.ReadToEnd();  
  95.            //Response.Write(content);  
  96.            //在这里对Access_token 赋值  
  97.            Access_token token = new Access_token();  
  98.            token = JsonHelper.ParseFromJson<Access_token>(content);  
  99.            mode.access_token = token.access_token;  
  100.            mode.expires_in = token.expires_in;  
  101.        }  
  102.        return mode;  
  103.    }  

        这个页面就是这些了,打开这个页面然后发送消息试试?很不错吧,这样在配合上我们的数据库啦,什么循环了,就可以突破了微信群发的限制,做到定项的群发消息推送了!这里面能发很多种消息:文本,语音,视频,图文,图片等等。只是Json而已,聪明的你一定可以举一反三的。

版权声明:本文为Alex80原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Alex80/p/4259123.html