微信公众号开发:消息处理
前言:
回顾服务器配置的内容,我们已经可以自己完成公众号服务器的配置。配置完成之后,我们就可以通过调用的方式,完成对消息管理的处理。当用户关注公众号或者发送消息的时候,我们应该启用默认回复,要不然用户得不到回应,
从而导致丢失体验。所以这一章节,我们将通过消息管理的方式,对用户的信息进行处理,完成公众号消息回复功能,实现公众号与用户之间的完整对话。
了解:
微信公众平台对信息做了比较清晰的分类,最基本的包括请求(request)和响应(response)两大类信息,这两类信息有分为文字、语音、图片等格式。senparc.weixin.mp提供了messagehandler消息处理类,这些类型在以枚举的方式区分,
同时根据严格命名规则命名了所有类型的requestmessage和responsemessage。在senparc里也详细说明了如何这个类的
开始:
第一步:
新建一个usermessagehandler.cs,需要继承senparc.weixin.mp.messagehandlers<tc>这个抽象类,并重写所有方法:
public class usermessagehandler : messagehandler<usermessagecontext> { /// <summary> /// 构造函数 /// </summary> /// <param name="inputstream">构造函数的inputstream用于接收来自微信服务器的请求流(如果需要在外部处理,这里也可以传入xdocument)</param> /// <param name="postmodel">微信公众服务器post过来的加密参数集合(不包括postdata)</param> public usermessagehandler(stream inputstream, postmodel postmodel) : base(inputstream, postmodel) { } public override iresponsemessagebase defaultresponsemessage(irequestmessagebase requestmessage) { /* 所有没有被处理的消息会默认返回这里的结果 */ var responsemessage = this.createresponsemessage<responsemessagetext>();//responsemessagetext也可以是news等其他类型 responsemessage.content = "这条消息来自defaultresponsemessage。"; return responsemessage; } }
using senparc.weixin.context; using senparc.weixin.mp.entities; using system; using system.collections.generic; using system.linq; using system.web; namespace weixinhandler { public class usermessagecontext: messagecontext<irequestmessagebase, iresponsemessagebase> { public usermessagecontext() { /* * 注意:即使使用其他类实现imessagecontext, * 也务必在这里进行下面的初始化,尤其是设置当前时间, * 这个时间关系到及时从缓存中移除过期的消息,节约内存使用 */ base.messagecontextremoved += usermessagecontext_messagecontextremoved; } /// <summary> /// 当上下文过期,被移除时触发的时间 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void usermessagecontext_messagecontextremoved(object sender, senparc.weixin.context.weixincontextremovedeventargs<irequestmessagebase, iresponsemessagebase> e) { /* 注意,这个事件不是实时触发的(当然你也可以专门写一个线程监控) * 为了提高效率,根据weixincontext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除 */ var messagecontext = e.messagecontext as custommessagecontext; if (messagecontext == null) { return;//如果是正常的调用,messagecontext不会为null } //todo:这里根据需要执行消息过期时候的逻辑,下面的代码仅供参考 //log.infoformat("{0}的消息上下文已过期",e.openid); //api.sendmessage(e.openid, "由于长时间未搭理客服,您的客服状态已退出!"); } } }
重写的方法对应了接收不同的request类型,构造函数的inputstream用于接收来自微信服务器的请求流
第二步:
基本用户不同类型的请求,比如用户向我们发送一条信息,那么会最终会调用ontextrequest这个方法,所以在不同的重写方法内,实现自己的方法。
比如:我们对于文字(text)信息进行这样的处理,在usermessagehandler中我们可以重写方法ontextrequest:
public override iresponsemessagebase ontextrequest(requestmessagetext requestmessage) { var responsemessage = base.createresponsemessage<responsemessagetext>(); responsemessage.content = "您刚刚发送了文字信息:" + requestmessage.content; //requestmessage.content即用户发过来的文字内容 return responsemessage; }
对于图片信息进行这样的处理,在usermessagehandler中我们可以重写方法onimagerequest
/// <summary> /// 处理图片请求 /// </summary> /// <param name="requestmessage"></param> /// <returns></returns> public override iresponsemessagebase onimagerequest(requestmessageimage requestmessage) { var responsemessage = createresponsemessage<responsemessagenews>(); responsemessage.articles.add(new article() { title = "您刚才发送了图片信息", description = "您发送的图片将会显示在边上", picurl = requestmessage.picurl, url = "https://www.cnblogs.com/i3yuan/" }); return responsemessage; }
对于语音信息进行这样的处理,在usermessagehandler中我们可以重写方法onvoicerequest
/// <summary> /// 处理语音请求 /// </summary> /// <param name="requestmessage"></param> /// <returns></returns> public override iresponsemessagebase onvoicerequest(requestmessagevoice requestmessage) { //获取公众号 accesstokenresult account = senparc.weixin.mp.commonapis.commonapi.gettoken(appid, appsecret); var responsemessage = createresponsemessage<responsemessagemusic>(); //上传缩略图 var uploadresult = senparc.weixin.mp.advancedapis.mediaapi.uploadtemporarymedia(account.access_token, uploadmediafiletype.image, server.getmappath("~/images/logo.jpg")); //设置音乐信息 responsemessage.music.title = "天籁之音"; responsemessage.music.description = "播放您上传的语音"; responsemessage.music.musicurl = "http://sdk.weixin.senparc.com/media/getvoice?mediaid=" + requestmessage.mediaid; responsemessage.music.hqmusicurl = "http://sdk.weixin.senparc.com/media/getvoice?mediaid=" + requestmessage.mediaid; responsemessage.music.thumbmediaid = uploadresult.media_id; return responsemessage; }
对于视频信息进行这样的处理,在usermessagehandler中我们可以重写方法onvideorequest
/// <summary> /// 处理视频请求 /// </summary> /// <param name="requestmessage"></param> /// <returns></returns> public override iresponsemessagebase onvideorequest(requestmessagevideo requestmessage) { var responsemessage = createresponsemessage<responsemessagetext>(); responsemessage.content = "您发送了一条视频信息,id:" + requestmessage.mediaid; return responsemessage; }
对于地理信息进行这样的处理,在usermessagehandler中我们可以重写方法onlocationrequest
/// <summary> /// 处理位置请求 /// </summary> /// <param name="requestmessage"></param> /// <returns></returns> public override iresponsemessagebase onlocationrequest(requestmessagelocation requestmessage) { var locationservice = new locationservice(); var responsemessage = locationservice.getresponsemessage(requestmessage as requestmessagelocation); return responsemessage; }
对于链接信息进行这样的处理,在usermessagehandler中我们可以重写方法onlinkrequest
/// <summary> /// 处理链接消息请求 /// </summary> /// <param name="requestmessage"></param> /// <returns></returns> public override iresponsemessagebase onlinkrequest(requestmessagelink requestmessage) { var responsemessage = responsemessagebase.createfromrequestmessage<responsemessagetext>(requestmessage); responsemessage.content = string.format(@"您发送了一条连接信息: title:{0} description:{1} url:{2}", requestmessage.title, requestmessage.description, requestmessage.url); return responsemessage; }
第三步:
在action中使用messagehandler,返回对用户的处理,在上一节中我们已经新建了wxcontroller.cs,在其中通过post的方式处理用户的请求
[httppost] [actionname("index")] public task<actionresult> post(postmodel postmodel) { return task.factory.startnew<actionresult>(() => { if (!checksignature.check(postmodel.signature, postmodel.timestamp, postmodel.nonce, token)) { return new weixinresult("参数错误!"); } var messagehandler = new usermessagehandler(request.inputstream); messagehandler.execute(); //执行微信处理过程 return new fixweixinbugweixinresult(messagehandler); }).continuewith<actionresult>(task => task.result); } }
messagehandler.execute();用于执行整个信息处理过程,其中会调用重写的onxxrequest方法
效果:
测试发送文本
通过测试公众号,我们可以发现,当我们发送文本的时候,系统会对用户的信息进行处理,完成公众号消息回复功能,实现公众号与用户之间的完整对话。
测试发送图文消息
public override iresponsemessagebase ontextrequest(requestmessagetext requestmessage) { var responsemessage = createresponsemessage<responsemessagenews>(); responsemessage.articles.add(new article() { title = "灌篮高手", description = "灌篮高手", picurl = "http://images.cnblogs.com/cnblogs_com/i3yuan/1462639/o_timg%20(1).jpg", url = "https://www.cnblogs.com/i3yuan/" }); return responsemessage; }
总结:
1.通过messagehandler的简单处理,我们就可以进行对用户文本消息的处理,完成公众号与用户的会话
2.发送不同的消息,处理不同的回复,实现更多类型的消息回复
上一篇: JQuery省市联动效果实现过程详解
下一篇: Yii2处理密码加密及验证