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

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

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

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

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

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

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

[csharp] view plaincopy

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

WriteLog的方法是这样的:

[csharp] view plaincopy

  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. finally
  26. {
  27. if (sr != null)
  28. sr.Close();
  29. }
  30. }

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

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

[csharp] view plaincopy

  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. string posturl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + Access_Token;
  15. string postData = "{\"touser\":\"" + UserName.Text + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + Content.Text + "\"}}";
  16. res = GetPage(posturl, postData);
  17. Response.Write(res);
  18. }

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

[csharp] view plaincopy

  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. /// <summary>
  42. /// 根据当前日期 判断Access_Token 是否超期  如果超期返回新的Access_Token   否则返回之前的Access_Token
  43. /// </summary>
  44. /// <param name="datetime"></param>
  45. /// <returns></returns>
  46. public static string IsExistAccess_Token()
  47. {
  48. string Token = string.Empty;
  49. DateTime YouXRQ;
  50. // 读取XML文件中的数据,并显示出来 ,注意文件路径
  51. string filepath = HttpContext.Current.Server.MapPath("XMLFile.xml");
  52. StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8);
  53. XmlDocument xml = new XmlDocument();
  54. xml.Load(str);
  55. str.Close();
  56. str.Dispose();
  57. Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText;
  58. YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText);
  59. if (DateTime.Now > YouXRQ)
  60. {
  61. DateTime _youxrq = DateTime.Now;
  62. Access_token mode = GetAccess_token();
  63. xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token;
  64. _youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in));
  65. xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString();
  66. xml.Save(filepath);
  67. Token = mode.access_token;
  68. }
  69. return Token;
  70. }
  71. public static Access_token GetAccess_token()
  72. {
  73. string appid = "wx043225275885dafd";
  74. string secret = "cb4425b24ab79ef875029cf0bf326ae9";
  75. string strUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
  76. Access_token mode = new Access_token();
  77. HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(strUrl);
  78. req.Method = "GET";
  79. using (WebResponse wr = req.GetResponse())
  80. {
  81. HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();
  82. StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
  83. string content = reader.ReadToEnd();
  84. //Response.Write(content);
  85. //在这里对Access_token 赋值
  86. Access_token token = new Access_token();
  87. token = JsonHelper.ParseFromJson<Access_token>(content);
  88. mode.access_token = token.access_token;
  89. mode.expires_in = token.expires_in;
  90. }
  91. return mode;
  92. }

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

时间: 2024-08-05 11:26:52

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

微信公共服务平台开发(.Net的实现)1 认证“成为开发者”

http://www.cnblogs.com/freeliver54/p/3725979.html http://www.it165.net/pro/html/201402/9459.html 这些代码也就开始认证的时候用一次,以后就不用了: view sourceprint? 01.const string Token = "XXXXX";//你的token 02.protected void Page_Load(object sender, EventArgs e) 03.{ 04

微信公共服务平台开发(.Net 的实现)13-------网页授权(下 :C#代码的实现 )

接着上次的理论,我们这次来研究用代码实现“网页授权获取用户基本信息”,首先我们需要一个链接指向微信的授权页面,在微信开发平台中已经说了,这个链接必须在微信客户端中打开,那么我们就干脆使用文本消息来完成吧,也就是说当我们发送“授权”两个字的时候,微信给我们一个链接,我们点击这个链接然后进入“授权页面”.首先改造一下我们OnLoad函数: [csharp] view plaincopy if (wx.MsgType == "text" && wx.Content == &q

微信公共服务平台开发(.Net 的实现)9-------处理二维码

今天我们来共同学习一下微信公共服务平台中一个重要内容---二维码扫描.众所周知二维码目前应用范围很广,在这里不再叙述背景了,但是值得一提的是目前大家手机上面应用的二维码扫描工具是支持的都是QR码和PDF417码标准,这就是为什么你用各种扫码工具扫出来的都一样的原因,因为大家都使用了同样的标准. 在微信中的“扫一扫”功能也支持了这种标准,但是我们如果在微信公共服务平台中开发,使用的就不是这种标准了,而是微信自己的标准.也就是说如果你用通用软件生成的二维码“微信”,“我查查”等都可以扫描出来,但是你

微信公共服务平台开发(.Net 的实现)6-------自定义菜单

用户自定义菜单制作时,需要用到access_token,我们直接使用前面讲解的IsExistAccess_Token()函数.我理解的微信公共平台里面菜单分为button和sub_button,即菜单和子菜单,这些菜单都有一个name的属性,类别分为click和view,click类有key属性:而view类有url属性,含有子菜单的菜单没有key属性也没有url属性.这些情况可以从下面的例子看出来. [csharp] view plaincopy public void MyMenu() {

微信公共服务平台开发(.Net 的实现)10-------地理位置

微信公共平台中涉及到地理位置的有两种情况:       第一.我发送一个自选的地理位置给微信,然后微信可以自动反馈响应的信息.       第二.让微信获取我们GPS定位地址位置,反馈响应的信息. 首先我们先来看第一种,在微信中除了可以发文本,图片,语音等还有一个信息就是地理位置,按照微信接受地理信息的XML信息,我们需要改造一下之前的wxmessage类加上几个属性: [csharp] view plaincopy class wxmessage { public string FromUse

微信公共服务平台开发(.Net 的实现)12-------网页授权(上 :更加深入理解OAuth2.0 )

我们首先来认识一下OAuth协议吧,这个东西很早就听说过,总觉得离我很远(我的项目用不到这些),但是最近不得不学习一下了.我在网上找了一些解释,认为解释的最好的是这样说的(出处:http://hi.baidu.com/powerthinks/item/f1cb9b3c7a88251c9dc65efa) 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店后,只需

微信公共服务平台开发(.Net 的实现)2-------获得ACCESSTOKEN

成为了开发者之后微信平台会给您appid和secret,在订阅号中是没有的,所以因该申请一下服务号 有了ACCESSTOKEN才能做添加菜单,上传/下载图片等功能 [csharp] view plaincopy private string GetToken() { // 也可以这样写: //return  GetPage("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的appid

微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题

因为access_token,在以后的高级功能里面会经常用到,所以这里不得不这里对前面所讲解的access_token改造一下.另外需要说明的是access_token是变化的,有自己的周期,官方解释为:"有效期为7200秒",这就要 求我们把获得的access_token存入一个物理文件或者Application中,请求到过期后修改这些内容,需要用的时候读出来.有些人可能想到了,如果过期我就在获得一个就好了,不用物理文件和Application也可以达到同样的效果,但是需要注意了微信

微信公众服务号开发

1 公司提供接口,微信平台可以通过访问我们的接口,进行数据交互,通过xml. 2 http://mp.weixin.qq.com/ 微信服务号平台,输入用户名密码进入高级功能-开发者模式, 3 申请服务号之后,微信会提供appid和AppSecret两个参数,根据这两个参数可以获取token,token作为你服务号和微信交互的证明. 4 接下里就是完成自己的接口部分的开发,然后接口的服务器配置地址输入微信服务号的服务器配置url,本地的项目地址是不行的,得是能访问的地址 5 接口的开发,接受xm