.NET微信公众号开发之公众号消息处理

一.前言

微信公众平台的消息处理还是比较完善的,有最基本的文本消息,到图文消息,到图片消息,语音消息,视频消息,音乐消息其基本原理都是一样的,只不过所post的xml数据有所差别,在处理消息之前,我们要认真阅读,官方给我们的文档:http://mp.weixin.qq.com/wiki/14/89b871b5466b19b3efa4ada8e577d45e.html。首先我们从最基本的文本消息处理开始。

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

我们可以看到这是消息处理的一个最基本的模式,有发送者,接受者,创建时间,类型,内容等等。

首先我们来创建一个消息处理的类,这个类用来捕获,所有的消息请求,根据不同的消息请求类型来处理不同的消息回复。

public class WeiXinService
  {
    /// <summary>
    /// TOKEN
    /// </summary>
    private const string TOKEN = "finder";
    /// <summary>
    /// 签名
    /// </summary>
    private const string SIGNATURE = "signature";
    /// <summary>
    /// 时间戳
    /// </summary>
    private const string TIMESTAMP = "timestamp";
    /// <summary>
    /// 随机数
    /// </summary>
    private const string NONCE = "nonce";
    /// <summary>
    /// 随机字符串
    /// </summary>
    private const string ECHOSTR = "echostr";
    /// <summary>
    ///
    /// </summary>
    private HttpRequest Request { get; set; }
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="request"></param>
    public WeiXinService(HttpRequest request)
    {
      this.Request = request;
    }
    /// <summary>
    /// 处理请求,产生响应
    /// </summary>
    /// <returns></returns>
    public string Response()
    {
      string method = Request.HttpMethod.ToUpper();
      //验证签名
      if (method == "GET")
      {
        if (CheckSignature())
        {
          return Request.QueryString[ECHOSTR];
        }
        else
        {
          return "error";
        }
      }

      //处理消息
      if (method == "POST")
      {
        return ResponseMsg();
      }
      else
      {
        return "无法处理";
      }
    }

    /// <summary>
    /// 处理请求
    /// </summary>
    /// <returns></returns>
    private string ResponseMsg()
    {
      string requestXml = CommonWeiXin.ReadRequest(this.Request);
      IHandler handler = HandlerFactory.CreateHandler(requestXml);

      if (handler != null)
      {
        return handler.HandleRequest();
      }

      return string.Empty;
    }
    /// <summary>
    /// 检查签名
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private bool CheckSignature()
    {
      string signature = Request.QueryString[SIGNATURE];
      string timestamp = Request.QueryString[TIMESTAMP];
      string nonce = Request.QueryString[NONCE];

      List<string> list = new List<string>();
      list.Add(TOKEN);
      list.Add(timestamp);
      list.Add(nonce);
      //排序
      list.Sort();
      //拼串
      string input = string.Empty;
      foreach (var item in list)
      {
        input += item;
      }
      //加密
      string new_signature = SecurityUtility.SHA1Encrypt(input);
      //验证
      if (new_signature == signature)
      {
        return true;
      }
      else
      {
        return false;
      }
    }
  }

在来看看我们的首先是如何捕获消息的。首页Default.ashx的代码如下

    public void ProcessRequest(HttpContext context)
    {
      context.Response.ContentType = "text/html";

      string postString = string.Empty;
      if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
      {
        //由微信服务接收请求,具体处理请求
        WeiXinService wxService = new WeiXinService(context.Request);
        string responseMsg = wxService.Response();
        context.Response.Clear();
        context.Response.Charset = "UTF-8";
        context.Response.Write(responseMsg);
        context.Response.End();
      }
      else
      {
        string token = "wei2414201";
        if (string.IsNullOrEmpty(token))
        {
          return;
        }

        string echoString = HttpContext.Current.Request.QueryString["echoStr"];
        string signature = HttpContext.Current.Request.QueryString["signature"];
        string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
        string nonce = HttpContext.Current.Request.QueryString["nonce"];

        if (!string.IsNullOrEmpty(echoString))
        {
          HttpContext.Current.Response.Write(echoString);
          HttpContext.Current.Response.End();
        }
      }

    }

从上面的代码中我们可以看到WeiXinService.cs类中的消息相应至关重要。

    /// <summary>
    /// 处理请求
    /// </summary>
    /// <returns></returns>
    private string ResponseMsg()
    {
      string requestXml = CommonWeiXin.ReadRequest(this.Request);
      IHandler handler = HandlerFactory.CreateHandler(requestXml);

      if (handler != null)
      {
        return handler.HandleRequest();
      }

      return string.Empty;
    }

IHandler是一个消息处理接口,其下面有EventHandler,TextHandler处理类实现这个接口。代码如下

  /// <summary>
  /// 处理接口
  /// </summary>
  public interface IHandler
  {
    /// <summary>
    /// 处理请求
    /// </summary>
    /// <returns></returns>
    string HandleRequest();
  }

EventHandler

class EventHandler : IHandler
  {
    /// <summary>
    /// 请求的xml
    /// </summary>
    private string RequestXml { get; set; }
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="requestXml"></param>
    public EventHandler(string requestXml)
    {
      this.RequestXml = requestXml;
    }
    /// <summary>
    /// 处理请求
    /// </summary>
    /// <returns></returns>
    public string HandleRequest()
    {
      string response = string.Empty;
      EventMessage em = EventMessage.LoadFromXml(RequestXml);
      if (em.Event.Equals("subscribe", StringComparison.OrdinalIgnoreCase))//用来判断是不是首次关注
      {

        PicTextMessage tm = new PicTextMessage();//我自己创建的一个图文消息处理类
        tm.ToUserName = em.FromUserName;
        tm.FromUserName = em.ToUserName;
        tm.CreateTime = CommonWeiXin.GetNowTime();
        response = tm.GenerateContent();

      }

      return response;
    }
  }

TextHandler

  /// <summary>
  /// 文本信息处理类
  /// </summary>
  public class TextHandler : IHandler
  {
    string openid { get; set; }
    string access_token { get; set; }

    /// <summary>
    /// 请求的XML
    /// </summary>
    private string RequestXml { get; set; }
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="requestXml">请求的xml</param>
    public TextHandler(string requestXml)
    {
      this.RequestXml = requestXml;
    }
    /// <summary>
    /// 处理请求
    /// </summary>
    /// <returns></returns>
    public string HandleRequest()
    {
      string response = string.Empty;
      TextMessage tm = TextMessage.LoadFromXml(RequestXml);
      string content = tm.Content.Trim();
      if (string.IsNullOrEmpty(content))
      {
        response = "您什么都没输入,没法帮您啊。";
      }
      else
      {
          string username = System.Configuration.ConfigurationManager.AppSettings["weixinid"].ToString();
          AccessToken token = AccessToken.Get(username);
          access_token = token.access_token;
          openid = tm.FromUserName;
          response = HandleOther(content);

      }
      tm.Content = response;
      //进行发送者、接收者转换
      string temp = tm.ToUserName;
      tm.ToUserName = tm.FromUserName;
      tm.FromUserName = temp;
      response = tm.GenerateContent();
      return response;
    }
    /// <summary>
    /// 处理其他消息
    /// </summary>
    /// <param name="tm"></param>
    /// <returns></returns>
    private string HandleOther(string requestContent)
    {
      string response = string.Empty;
      if (requestContent.Contains("你好") || requestContent.Contains("您好"))
      {
        response = "您也好~";
      }else if (requestContent.Contains("openid") || requestContent.Contains("id") || requestContent.Contains("ID"))//用来匹配用户输入的关键字
      {
        response = "你的Openid: "+openid;
      }
      else if (requestContent.Contains("token") || requestContent.Contains("access_token"))
      {
        response = "你的access_token: " + access_token;
      }else
      {
        response = "试试其他关键字吧。";
      }
      return response;
    }
  }

HandlerFactory

  /// <summary>
  /// 处理器工厂类
  /// </summary>
  public class HandlerFactory
  {
    /// <summary>
    /// 创建处理器
    /// </summary>
    /// <param name="requestXml">请求的xml</param>
    /// <returns>IHandler对象</returns>
    public static IHandler CreateHandler(string requestXml)
    {
      IHandler handler = null;
      if (!string.IsNullOrEmpty(requestXml))
      {
        //解析数据
        XmlDocument doc = new System.Xml.XmlDocument();
        doc.LoadXml(requestXml);
        XmlNode node = doc.SelectSingleNode("/xml/MsgType");
        if (node != null)
        {
          XmlCDataSection section = node.FirstChild as XmlCDataSection;
          if (section != null)
          {
            string msgType = section.Value;

            switch (msgType)
            {
              case "text":
                handler = new TextHandler(requestXml);
                break;
              case "event":
                handler = new EventHandler(requestXml);
                break;
            }
          }
        }
      }

      return handler;
    }
  }

在这里基本的一些类已经完成了,现在我们来完成,关注我们的微信公众号,我们就发送一条图文消息,同时输入我们的一些关键字,返回一些消息,比如输入id返回用户的openid等等。

二.PicTextMessage

public class PicTextMessage : Message
  {
    /// <summary>
    /// 模板静态字段
    /// </summary>
    private static string m_Template;

    /// <summary>
    /// 默认构造函数
    /// </summary>
    public PicTextMessage()
    {
      this.MsgType = "news";
    }
    /// <summary>
    /// 从xml数据加载文本消息
    /// </summary>
    /// <param name="xml"></param>
    public static PicTextMessage LoadFromXml(string xml)
    {
      PicTextMessage tm = null;
      if (!string.IsNullOrEmpty(xml))
      {
        XElement element = XElement.Parse(xml);
        if (element != null)
        {
          tm = new PicTextMessage();
          tm.FromUserName = element.Element(CommonWeiXin.FROM_USERNAME).Value;
          tm.ToUserName = element.Element(CommonWeiXin.TO_USERNAME).Value;
          tm.CreateTime = element.Element(CommonWeiXin.CREATE_TIME).Value;
        }
      }

      return tm;
    }
    /// <summary>
    /// 模板
    /// </summary>
    public override string Template
    {
      get
      {
        if (string.IsNullOrEmpty(m_Template))
        {
          LoadTemplate();
        }

        return m_Template;
      }
    }
    /// <summary>
    /// 生成内容
    /// </summary>
    /// <returns></returns>
    public override string GenerateContent()
    {
      this.CreateTime = CommonWeiXin.GetNowTime();
      string str= string.Format(this.Template, this.ToUserName, this.FromUserName, this.CreateTime);
      return str;
    }

    /// <summary>
    /// 加载模板
    /// </summary>
    private static void LoadTemplate()
    {
      m_Template= @"<xml>
              <ToUserName><![CDATA[{0}]]></ToUserName>
              <FromUserName><![CDATA[{1}]]></FromUserName>
              <CreateTime>{2}</CreateTime>
              <MsgType><![CDATA[news]]></MsgType>
              <ArticleCount>1</ArticleCount>
              <Articles>
                <item>
                <Title><![CDATA[有位停车欢迎你!]]></Title>
                <Description><![CDATA[如有问题请致电400-6238-136或直接在微信留言,我们将第一时间为您服务!]]></Description>
                <PicUrl><![CDATA[http://www.baidu.com/youwei.jpg]]></PicUrl>
                <Url><![CDATA[http://www.baidu.com]]></Url>
                </item>
              </Articles>
            </xml> ";
    }
  }

最后我们的效果如下所示;

以上所述就是本文的全部内容了,希望大家能够喜欢

(0)

相关推荐

  • asp.net微信开发(永久素材管理)

    除了3天就会失效的临时素材外,开发者有时需要永久保存一些素材,届时就可以通过本接口新增永久素材. 最近更新,永久图片素材新增后,将带有URL返回给开发者,开发者可以在腾讯系域名内使用(腾讯系域名外使用,图片将被屏蔽). 请注意: 1.新增的永久素材也可以在公众平台官网素材管理模块中看到 2.永久素材的数量是有上限的,请谨慎新增.图文消息素材和图片素材的上限为5000,其他类型为1000 3.素材的格式大小等要求与公众平台官网一致.具体是,图片大小不超过2M,支持bmp/png/jpeg/jpg/

  • asp.net开发微信公众平台之获取用户消息并处理

    获取用户消息 用户发送的消息是在微信服务器发送的一个HTTP POST请求中包含的,获取用户发送的消息要从POST请求的数据流中获取 微信服务器推送消息到服务器的HTTP请求报文示例 POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915debcba66cb864d751f3e6&timestamp=1409659813&nonce=1372623149 HTTP/1.1 Host: qy.weixin.qq.com 从POST请求中

  • asp.net微信开发(高级群发图文)

    上一篇介绍了如何群发文本消息,本篇将介绍如何群发图文信息,上传图文信息所需的素材,界面如下: 我们先看从素材库中获取图文素材的代码,界面: 素材列表,我是使用的repeater控件, 前台代码如下: <!--弹出选择素材窗口--> <div id="shownewgroup"> <div class="closeLogin" style="height:40px; background-color:#ddd9ff; line-

  • asp.net微信开发(自定义会话管理)

    和微信用户的沟通少不了,总觉得看起来微信官网后台管理中的会话回复消息有点呆板,所以我这里就自定义了一个会话管理功能,最终效果图如下: 因为我试使用富文本文件CKEDITOR来进行编写,你看到稳中可能会有<P></p>字段,后台获取数据内容时,替换为空字符即可:如下 string txtcontent = this.txtMessage.Value.ToString().Replace("<p>", ""); StringBuild

  • 基于js实现微信发送好友如何分享到朋友圈、微博

    微信浏览器内置了javascript私有对象WeixinJSBridge,可以实现发送给朋友.分享到朋友圈.分享到微博等功能. <script> var imgUrl = "图片地址"; var lineLink = "当前网址"; var descContent = "描述"; var shareTitle = '标题'; var appid = ''; function shareFriend() { WeixinJSBridge

  • .Net语言Smobiler开发之如何仿微信朋友圈的消息样式

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的"Smobiler Components"拖动一个MicroBlog控件到窗体界面上 2.用代码添加手机界面上显示的内容 Load事件代码: VB: Private Sub TestMicroBlog_Load(sender As Object, e As EventArgs) Handles MyBa

  • Android仿微信发朋友圈浏览图片效果

    先看一下效果吧: 下面就来说一下具体怎么实现的: 实现思路 1.首先我们要获取数据源,数据源就是我们的每条说说(包括姓名.标题.图片数组) 2.自定义适配器(ListView嵌套着GridView) 3.图片点击浏览图片(Fragment+ViewPager) 具体实现 1.初始化数据源,设置适配器,看一下代码: public class MyActivity extends Activity { /*图片显示列表*/ private ListView listView; /*图片URL数组*/

  • .NET微信公众号开发之准备工作

    一.前言 微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字.图片.语音.视频的全方位沟通.互动 .形成了一种主流的线上线下微信互动营销方式. 二.开发准备 在开发以前,公司给你把一些资料准备好,这时候你只需要登录微信公众平台https://mp.weixin.qq.com.启动我们的开发者模式 这些工作都准备好了就可以开始我们的编码工作了. 三.开始编码 第一步:我们要做的就是创建菜单.菜单分为一级菜单,二级菜单,官

  • asp.net开发微信公众平台之验证消息的真实性

    验证消息的真实性 在MVC Controller所在项目中添加过滤器,在过滤器中重写 public override void OnActionExecuting(ActionExecutingContext filterContext)方法 新建数据模型 注:服务器接收消息时,不再是signature而是msg_signature 微信服务器推送消息到服务器的HTTP请求报文示例 POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915de

  • asp.net微信开发(高级群发文本)

    首先我们先来讲解一下群发文本信息的过程,我个人开发程序是首先要有UI才能下手去写代码,界面如下, 看图我们也可以看出首先我们要获取该微信号本月还能群发几条信息,关于怎么计算,就是群发成功一条信息,就在本地数据库存储一条信息,用来计算条数,(这个我相信都会),大于4条就不能发送(这里我已经限制死了,因为服务号每月只能发送4条,多发送也没用,用户只能收到4条,除非使用预览功能,挨个发送,但预览功能也只能发送100次,或许可能使用开发者模式下群发信息可以多发送N次哦,因为我群发了两次之后,再进入到微信

随机推荐