【文章摘要】
Senparc.Weixin.MP虽然是微信公众号的SDK,但由于易信公众号和新浪微博粉丝服务平台也提供了微信兼容接口,所以也可以使用其快速实现相应的服务,当然微博由于与微信存在差异,如果不改动原始SDK,则需要对一些地方进行调整。本文使用Senparc.Weixin.MP快速实现新浪微博粉丝服务平台的接口。
【文章索引】
【一、新浪微博粉丝服务平台接口说明】
关于怎么申请新浪微博粉丝服务平台就不详细介绍了,蓝V认证后就可以使用粉丝服务平台了,如果需要使用开发模式调用接口的话,还需要在微博开放平台创建一个应用,类型选择“微服务应用”->“粉丝服务平台”,待应用注册好后,就可以获取到应用的AppKey和AppSecret了。然后在微博的“管理中心”->“粉丝服务”->“高级功能”中可以选择设置为开发模式,与微信公众号不同的是,微信在使用开发模式时需要自定义Token并在验证消息时与其他参数放置一起创建签名Signature,而微博在使用开发模式时需要填写刚才创建的应用的AppKey,然后创建Signature时使用的是对应的AppSecret。在第一次设置微博粉丝服务平台时,微博会对设置的服务器地址进行验证,即通过GET方式传入echostr参数,然后你需要将参数返回出来,当然你也可以对其来源真伪进行验证。
微博粉丝服务平台的管理界面与微信公众号几乎一模一样,连图标都神似。粉丝服务平台与微信的公众号也非常类似,底部菜单,消息事件推送等等都是一样的;与微信相比,在推送的信息中更是直接返回微博用户的uid,而不是像微信一样只返回对于当前应用唯一的OpenID。
对于刚配置好的粉丝服务平台,默认使用的消息推送接口是JSON类型的,不过很贴心的是,微博也提供了兼容微信的XML接口,如果原来开发过微信公众号的话,可以极大程度地复用代码。如果需要切换不同的格式,请参考 http://open.weibo.com/wiki/Eps/push/set_format 这个文档,需要将access_token和format=xml两个参数POST到接口中,看起来很复杂,其实实现起来很简单,自己写一个或者找一个能POST参数的程序即可;而access_token也不像微信一样需要通过OAuth2.0去获取,而是在微博的粉丝服务平台的管理页面中直接显示(有效期一年),如下图。
除此之外,自定义菜单接口也与微信的类似,同样是传入上述的access_token,以及将菜单的JSON代码传入menus参数即可创建菜单。以下主要介绍消息和事件推送这个比较核心的内容。
【二、Senparc.Weixin.MP使用介绍】
Senparc.Weixin.MP是一个基于FreeBSD的开源的微信公众平台SDK,官方网站是:http://weixin.senparc.com,GitHub是:http://github.com/JeffreySu/WeiXinMPSDK。同时,在NuGet上也提供了发布版,可以很方便的使用NuGet管理。除此之外,作者也有一份官方的说明文档,http://www.cnblogs.com/szw/archive/2013/05/14/weixin-course-index.html。
微博的粉丝服务平台与微信公众号一样,对于用户发送的内容以及点击菜单等的事件都会推送到粉丝服务平台开发者模式中设置的地址。与微信一样,对于首次验证地址使用的是GET请求方式,对于日后的推送使用的都是POST方式。
对于每次请求,首先需要验证来源的真伪,Senparc.Weixin.MP已经将该功能封装在CheckSignature类中,例如使用HttpHandler的话可以直接使用如下代码检查来源是否有效:
String signature = Request.QueryString["signature"]; String timestamp = Request.QueryString["timestamp"]; String nonce = Request.QueryString["nonce"]; Boolean isRight = CheckSignature.Check(signature, timestamp, nonce, "APP_SECRET");
当验证来源有效后,即可使用Senparc.WeiXin.MP的MessageHandler来实现对消息的处理,通常我们需要继承该类实现自定义的回复,例如以下代码可以将所有用户发送的信息都回复“默认回复消息”:
1 public class WeiboMessageHandler : MessageHandler<MessageContext> 2 { 3 private ResponseMessageText responseMessage; 4 5 public WeiboMessageHandler(Stream inputStream) 6 : base(inputStream) 7 { 8 this.responseMessage = this.CreateResponseMessage<ResponseMessageText>(); 9 } 10 11 public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) 12 { 13 this.responseMessage.Content = "默认回复消息"; 14 return responseMessage; 15 } 16 }
然后我们可以在HttpHanlder中通过如下代码调用MessageHandler,获取处理后的结果并输出:
1 if (String.Equals("POST", Request.HttpMethod.ToUpperInvariant()))//POST方法进行回复信息 2 { 3 WeiboMessageHandler messageHandler = new WeiboMessageHandler(Request.InputStream); 4 messageHandler.Execute(); 5 6 Response.Output.Write(messageHandler.ResponseDocument.ToString()); 7 }
除此之外,在继承的MessageHandler中,还可以重载以下方法实现不同的功能:
1、IResponseMessageBase OnTextRequest(RequestMessageText requestMessage):文字消息
2、IResponseMessageBase OnEventRequest(IRequestMessageEventBase requestMessage):事件消息
3、IResponseMessageBase OnEvent_ClickRequest(RequestMessageEvent_Click requestMessage):菜单点击事件消息
4、IResponseMessageBase OnEvent_ViewRequest(RequestMessageEvent_View requestMessage):菜单点击链接消息
5、IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage):用户订阅事件消息
6、IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage):用户取消订阅事件消息
例如在每个requestMessage中都可以获取FromUserName,对于微信是只能保证每个应用内唯一的OpenID,而在微博中则是用户的uid。对于文字消息,requestMessage中有Content属性可以获取用户发送的文字内容,并根据用户发送的不同内容返回不同的结果;对于事件消息有Event属性可以获取事件类型;对于菜单点击事件和链接消息,则有EventKey属性可以分别表示菜单事件名称和点击菜单后跳转的Url地址,尤其是对于点击事件,可以根据不同的EventKey返回不同的内容;而在用户订阅和取消订阅的方法中可以往自己的数据库中写入相关标记。除了可以重载上述的方法外,还有好多方法可以重载,在这就不一一介绍了,对于没有单独处理的消息(如没有重载相应方法或在其他地方进行处理),则默认会返回DefaultResponseMessage中的消息。
需要说明的是,在微博粉丝服务平台中,对于用户发送的消息,只有Text、Image、Voice和Position(Location)四种类型,而没有Video和Link两种类型;而对于事件消息,与微信相同的有关注(subscribe)、取消关注(unsubscribe)、扫描二维码(subscribe或SCAN)以及菜单点击事件(CLICK)和菜单点击链接(VIEW)几种,没有微信的打开聊天窗口自动上报地理位置信息的事件(LOCATION),但是多了用户关注(follow)和取消关注(unfollow)两个事件。
【三、对于微博特有事件的处理】
Senparc.WeiXin.MP采用了重载的方式使得非常简单就能实现微信公众号,但是微博和微信在推送的信息方面有所出入。对于微博少的而言,倒无所谓,但对于微博比微信多的两个事件(关注和取消关注)就需要做额外的处理了。当然修改Senparc.WeiXin.MP的源代码是一种方案,但对于使用NuGet管理或者不想对原有代码进行修改时,需要采用以下的办法。
由于Senparc.WeiXin.MP本身不支持follow和unfollow类型,所以通过MessageHandler中的RequestMessage或者OnEventRequest方法中的requestMessage都获取不到正确的Event属性,其Event属性始终为Enter,如果我们不对此进行处理的话Senparc.WeiXin.MP也会默认会按Enter事件进行处理。所以我们需要从原始数据中读取信息,例如如下代码:
1 public override IResponseMessageBase OnEventRequest(IRequestMessageEventBase requestMessage) 2 { 3 String key = this.RequestDocument.Root.Element("Event").Value.ToLowerInvariant(); 4 5 switch (key) 6 { 7 case "follow"://关注 8 return this.OnEvent_FollowRequest(requestMessage); 9 case "unfollow"://取消关注 10 return this.OnEvent_UnfollowRequest(requestMessage); 11 } 12 13 //其他事件处理代码 14 15 return base.OnEventRequest(requestMessage); 16 } 17 18 public IResponseMessageBase OnEvent_FollowRequest(IRequestMessageEventBase requestMessage) 19 { 20 //处理用户关注事件 21 22 return this.responseMessage; 23 } 24 public IResponseMessageBase OnEvent_UnfollowRequest(IRequestMessageEventBase requestMessage) 25 { 26 //处理用户取消关注事件 27 28 return this.responseMessage; 29 }
当然,对于Senparc.WeiXin.MP的老版本,RequestMessageEventBase的继承关系出现了一个错误(RequestMessageEventBase本应该实现IRequestMessageEventBase但却没有实现)。当事件类型系统不识别时,执行MessageHanlder的Execute()会发生空指针错误,更新到最新的7.0.18及以后的版本即可解决该问题。
【参考链接】