这一章主要讲应用菜单点击事件的接收
要接收企业微信消息,首先要配置API,这里不进行详细介绍了,具体请参考企业微信官方文档
另外还需要用代码设置菜单,菜单点击事件无法手动设置,至少要用代码设置一次之后才能手动设置点击事件,需要设置菜单代码的可以留言联系方式
企业微信接收与回复消息需要加密以及解密,官方有提供算法库,目前已有 c++/python/php/java/golang/c# 等语言版本,我用的是C#库
1.封装接收消息帮助类
private string sToken { get; set; }
private string sEncodingAESKey { get; set; }
Tencent.WXBizMsgCrypt Wxcpt { get; set; }
public ReceiveMsgHelper(string sToken, string sEncodingAESKey)
{
this.sToken = sToken;
this.sEncodingAESKey = sEncodingAESKey;
this.Wxcpt = new Tencent.WXBizMsgCrypt(sToken, sEncodingAESKey, corpid);
}
/// <summary>
/// 获取响应消息对象
/// </summary>
/// <param name="RequestStr"></param>
/// <returns></returns>
public HttpResponseMessage getHttpRespMsg(string RequestStr)
{
return new HttpResponseMessage
{
Content = new StringContent(RequestStr, Encoding.GetEncoding("UTF-8"), "text/xml")
};
}
/// <summary>
/// 验证VerifyURL
/// </summary>
/// <returns></returns>
public string VerifyURL(string msg_signature, string timestamp, string nonce, string echostr)
{
string sEchoStr = "";
int ret = Wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr, ref sEchoStr);
if (ret != 0)
{
LogHelper.Error("ERR: VerifyURL fail, ret: " + ret);
return string.Empty;
}
return sEchoStr;
}
/// <summary>
/// DecryptMsg,解密
/// </summary>
/// <returns></returns>
public string DecryptMsg(string msg_signature, string timestamp, string nonce, string ciphertext)
{
string sEchoStr = "";
int ret = Wxcpt.DecryptMsg(msg_signature, timestamp, nonce, ciphertext, ref sEchoStr);
if (ret != 0)
{
LogHelper.Error("ERR: DecryptMsg fail, ret: " + ret);
return string.Empty;
}
return sEchoStr;
}
/// <summary>
/// EncryptMsg ,加密
/// </summary>
/// <returns></returns>
public string EncryptMsg(string timestamp, string nonce, string text)
{
string sEchoStr = "";
int ret = Wxcpt.EncryptMsg(text, timestamp, nonce, ref sEchoStr);
if (ret != 0)
{
LogHelper.Error("ERR: EncryptMsg fail, ret: " + ret);
return string.Empty;
}
return sEchoStr;
}
这里我的应用id,以及接收配置字符串都写在了配置文件里
2.接收消息接口
private ReceiveMsgHelper wx
{
get { return new ReceiveMsgHelper(base.sToken, base.sEncodingAESKey); }
}
[AllowAnonymous, HttpPost, HttpGet]
public HttpResponseMessage Receive()
{
var msg_signature = HttpContext.Current.Request.QueryString["msg_signature"].ToString();
var timestamp = HttpContext.Current.Request.QueryString["timestamp"].ToString();
var nonce = HttpContext.Current.Request.QueryString["nonce"].ToString();
var RequestStr = "";//回复消息内容
//验证URL
if (HttpContext.Current.Request.HttpMethod.ToUpper() == "GET")
{
var echostr = HttpContext.Current.Request.QueryString["echostr"].ToString();
var sEchoStr = wx.VerifyURL(msg_signature, timestamp, nonce, echostr);
RequestStr = sEchoStr;
}
else
{
//捕捉事件
var evnentXml = string.Empty;
using (StreamReader sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
//读取
evnentXml = sr.ReadToEnd();
}
//解密
evnentXml = wx.DecryptMsg(msg_signature, timestamp, nonce, evnentXml);
LogHelper.Debug(evnentXml);
//转xml对象
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(evnentXml);
//获取回复消息内容
RequestStr = this.getRespDataImg(xmlDoc, timestamp, nonce);
if (string.IsNullOrEmpty(RequestStr))
{
return null;
}
}
//响应消息
return wx.getHttpRespMsg(RequestStr);
}
企业微信在配置的时候发送的请求是GET方式,但在接收时的请求是POST方式,所以API要同时允许两种请求方式
获取回复消息方法
private string getRespDataImg(XmlDocument xmlDoc, string timestamp, string nonce)
{
var sRespData = "";//回复消息文本
var ToUserName = xmlDoc.DocumentElement.SelectSingleNode("ToUserName").InnerText;
var FromUserName = xmlDoc.DocumentElement.SelectSingleNode("FromUserName").InnerText;
var CreateTime = xmlDoc.DocumentElement.SelectSingleNode("CreateTime").InnerText;
var MsgType = xmlDoc.DocumentElement.SelectSingleNode("MsgType").InnerText;//消息类型
if (MsgType != "event")//事件类型消息
{
return null;
}
var Event = xmlDoc.DocumentElement.SelectSingleNode("Event").InnerText;//事件类型
if (Event != "click")//点击事件
{
return null;
}
var EventKey = xmlDoc.DocumentElement.SelectSingleNode("EventKey").InnerText;//点击事件值
//获取图片的媒体id
string media_id = powerBIHelper.getMedia_idByTaskId(EventKey);
if (!string.IsNullOrEmpty(media_id))
{
sRespData = $@"<xml>
<ToUserName><![CDATA[{ToUserName}]]></ToUserName>
<FromUserName><![CDATA[{FromUserName}]]></FromUserName>
<CreateTime>{CreateTime}</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[{media_id}]]></MediaId>
</Image>
</xml>";
}
else
{
//查不到报表
sRespData = $@"<xml>
<ToUserName><![CDATA[{ToUserName}]]></ToUserName>
<FromUserName><![CDATA[{FromUserName}]]></FromUserName>
<CreateTime>{CreateTime}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[没有查询到报表哦!如有问题可以联系开发人员]]></Content>
</xml>";
}
//加密并返回
return wx.EncryptMsg(timestamp, nonce, sRespData);
}
更多消息格式请参考企业微信官方文档
如果在post接收企业微信消息时出现415错误,可以尝试在WebApiConfig文件中加上如下代码
var formatter = GlobalConfiguration.Configuration.Formatters.Where(f => f is System.Net.Http.Formatting.JsonMediaTypeFormatter).FirstOrDefault();
if (!formatter.SupportedMediaTypes.Any(mt => mt.MediaType == "text/xml"))
formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
config.Formatters.Add(formatter);