服务器之家

服务器之家 > 正文

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

时间:2019-12-18 16:13     来源/作者:hebedich

一.前言

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

?
1
2
3
4
5
6
7
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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的代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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类中的消息相应至关重要。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <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处理类实现这个接口。代码如下

?
1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 处理接口
/// </summary>
public interface IHandler
{
  /// <summary>
  /// 处理请求
  /// </summary>
  /// <returns></returns>
  string HandleRequest();
}

EventHandler

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/// <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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/// <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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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> ";
    }
  }

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

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

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

标签:

相关文章

热门资讯

玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分 2019-06-21
男生常说24816是什么意思?女生说13579是什么意思?
男生常说24816是什么意思?女生说13579是什么意思? 2019-09-17
配置IIS网站web服务器的安全策略配置解决方案
配置IIS网站web服务器的安全策略配置解决方案 2019-05-23
Nginx服务器究竟是怎么执行PHP项目
Nginx服务器究竟是怎么执行PHP项目 2019-05-24
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情 2019-06-22
返回顶部