前言
昨天玩了文本消息的接收,今天想试试自定义菜单。
思路
微信开发文档告诉我们:
公众平台的接口分为两类:
1、 消息接口:公众平台将用户操作的信息发送给开发者配置的 URL,并接收回复。
2、 API 接口:由开发者主动调用的接口。
文档上也很清晰地梳理了接口,昨天的文本消息处理是属于消息接口,而今天的自定义菜单是属于API接口。
如下是操作方式:
1.获取访问凭证 access_token
access_token 是公众号的全局唯一票据,公众号调用各接口时都需使用 access_token。获取访问凭证需要传入 appID 和 appsecret。
access_token 有效期目前为 2 个小时,需要定时刷新,且刷新后将导致上次获取的凭证失效。
由于获取访问凭证 API 接口有频率限制,频繁刷新可能导致超过限额,影响正常业务,因此需要对访问凭证进行缓存。
所以需要对 access_token 的操作进行封装:
1、 获取最新可用的 access_token
2、 access_token 过期前需要有自动刷新机制
3、 提供主动刷新接口给业务点调用,这是为了防止业务方的误刷新 access_token(如本地运行程序进行测试,导致服务器缓存的凭证失效),或者微信平台修改access_token 的策略导致access_token 提前过期
Demo 中:
AccessTokenUtil 类对 access_token 的访问进行了封装,使用定时任务进行刷新。
HttpUtil 类负责替换 url 参数中 access_token,使用 httpclient 类库发起 https 请求。
并且在凭证无效时重新获取凭证并发起请求。
2.创建自定义菜单
Demo 中创建“点灯” 、 “灭灯” 两个 CLICK 类型菜单。创建 CLICK菜单时,需要指定每个菜单对应的 key 值,用于在服务端收到消息时区分用户点击了哪个菜单。
代码见 Tools 类中 createMenu 方法。
创建自定义菜单后,由于微信客户端缓存,需要 24 小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
代码处理
于是就移植AccessTokenUtil、HttpUtil、Tools这几个类就可以了。
在config.properties中设置appID、appsecret。然后再接收文本消息为“菜单”时就创建这个菜单。当然,这个方式不是最好的,建议就直接在main函数里放一下,调试一次就好了,以后就可以屏蔽掉了。
// 文本消息
if (MsgType.TEXT.equals(msgType)) {
// 可以在此处进行关键字自动回复
String content = "收到文本消息: " + reqMap.get("Content");
if (reqMap.get("Content").equals("菜单")) {
Tools.createMenu();
}
return XmlResp.buildText(fromUser, toUser, content);
}
结果测试出现了如下错误:
菜单:{"button":[{"type":"click","name":"点灯","key":"V1001_LIGHT_ON"},{"type":"click","name":"灭灯","key":"V1002_LIGHT_OFF"}]}
refresh token...
result={"access_token":"yq9uUHzPF7Dhuw6CC3OcIvRs9v5j8h47QKItdFPRnQt5nqZd0d36oZZihniOlqzJznEd8MA21prq-rL3PWWN7BzerD7ceQ0lFdt3LCfjdcY","expires_in":7200}
result={"errcode":48001,"errmsg":"api unauthorized hint: [q3sRHa0075vr20]"}
创建菜单返回:{"errcode":48001,"errmsg":"api unauthorized hint: [q3sRHa0075vr20]"}
result={"errcode":48001,"errmsg":"api unauthorized hint: [ZpramA0076vr22]"}
查询菜单:{"errcode":48001,"errmsg":"api unauthorized hint: [ZpramA0076vr22]"}
原来是没有权限,仔细一看,自定义菜单确实是需要微信认证才行。
于是申请了测试帐号,重新输入了appID、appsecret。这才通过。