玩一玩微信公众号开发(二) 管理凭据和自定义菜单
管理access_token
access_token介绍
在前面我们成功的使用了Spring Boot Web程序和微信对接。但是这仅仅是一个开始,我们还需要获取access_token,也就是凭据,才能进行之后的工作。微信开发文档有如下介绍。
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
微信开发文档建议我们使用一个中控服务器,获取和刷新token均由服务器进行,我们的程序只从中控服务器获取access_token。由于每次获取access_token都会刷新一个新token,因此如果在程序中直接获取,可能造成token不一致和过期问题。
Spring Boot缓存配置
当然实际上并不是一定要另外整一个服务器。我们利用Spring的缓存功能,也可以比较好的完成任务。下面就来介绍一下。
首先,现在Spring Boot项目中添加下面的依赖,启用Spring的缓存功能。
compile('org.springframework.boot:spring-boot-starter-cache')
上面的依赖仅仅启用了Spring Boot的缓存抽象和自动配置功能。我们还需要选择具体的缓存实现。Spring Boot支持多种Java 缓存实现。我随便挑了个caffeine,它是由Guava库独立出来的缓存库,使用Java 8编写,我看着不错。
compile 'com.github.ben-manes.caffeine:caffeine:2.4.0'
Spring Boot会自动配置caffeine,所以我们可以完全透明的使用它。当然,还需要进行一点配置。由于微信的access_token的过期时间为7200秒,所以我们的缓存需要在这之前获取新的token。因此这里将caffeine的过期时间配置为7000秒,在application.properties
中设置即可。
spring.cache.caffeine.spec=expireAfterWrite=7000s
缓存是配置好了,但是这就能直接使用了吗?当然不是,我们还需要编写获取token的服务。获取access_token需要微信公众平台开发者页面上的appid和appsecret,我们先要获取到它,然后配置到application.properties
中。
yitian.study.weixin.appid=XXXXXXXXXXXXX
yitian.study.weixin.appsecret=XXXXXXXXXXXXX
获取凭据
获取access_token需要向https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
发送一个GET请求,并包含appid和appsecret两个参数。如果成功获取到token,微信服务器会返回下面这样的json。
{"access_token":"ACCESS_TOKEN","expires_in":7200}
如果出现错误,则会返回错误信息json。
{"errcode":40013,"errmsg":"invalid appid"}
所以Kotlin代码可以写成这样。在方法上使用了@Cacheable注解,Spring会将方法结果缓存起来,下次直接使用缓存结果。
@Service
class AccessTokenService(@Value("\${yitian.study.weixin.appid}") val appId: String,@Value("\${yitian.study.weixin.appsecret}") val appSecret: String,@Autowired val objectMapper: ObjectMapper
) {@Cacheable("access_token")fun refreshAccessToken(): String {val requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret"val json = URL(requestUrl).readText()try {val result = objectMapper.readValue(json, AccessTokenResult::class.java)return result.accessToken} catch (ex: JsonMappingException) {val error = objectMapper.readValue(json, ErrorResult::class.java)throw AccessTokenException(ex, error.toString())}}
}
在上面的代码中注入了Spring Boot自动配置的ObjectMapper,用于将结果json转换为Kotlin对象。上面用到的Bean和异常定义在下面。
data class ErrorResult(@JsonProperty("errcode") val errorCode: Int,@JsonProperty("errmsg") val errorMessage: String
) {
}data class AccessTokenResult(@JsonProperty("access_token") val accessToken: String,@JsonProperty("expires_in") val expiresIn: Int) {
}class AccessTokenException(val ex: Throwable, val msg: String) : Throwable(msg, ex) {}
这样,access_token的管理工作就算完成了。以后我们需要获取access_token,直接从AccessTokenService调用就行了。
自定义菜单
对于个人性质的订阅号,没有自定义菜单等高级功能。所以下面我改用微信测试号来验证这些功能。另外,我们可以使用微信公众平台的在线调试工具来帮助我们开发。
从微信开发文档的截图来看,我猜它很久没更新过了。怪不得写的并不咋地,我看了半天也没明白怎么创建自定义菜单。从网上找了一篇微信公众平台开发(八) 自定义菜单功能开发,虽然用的是PHP语言,但是讲的还可以。
新建菜单
首先先看看微信文档的注意事项。
1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“…”代替。
3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
需要创建菜单的时候,我们需要向微信发送一个[https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN](https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN)
的POST请求,
请求体是类似这样的JSON。这些按钮的type属性可以指定为多种按钮类型,有不同的作用。这些按钮类型和JSON属性的详细信息直接参考官方文档吧。
{"button": [{"name": "实用功能","sub_button": [{"type": "click","name": "天气预报","key": "weather_forecast"},{"type": "click","name": "说个笑话","key": "speak_jokes"}]},{"type": "media_id","name": "捐赠作者","media_id": "g78zk9TnnoFBaGJV4jpEDqR2y-fDNgOOFQkiCfrZIbA"}]
}
如果添加菜单成功,就会返回这样的JSON字符串。
{"errcode":0,"errmsg":"ok"}
如果出现错误,就会返回错误码和错误信息。
{"errcode":40018,"errmsg":"invalid button name size"}
本来我想着找一个比较好用的Java/Kotlin的HTTP传输库来进行这些接口的操作。但是找了半天居然没发现比较好用的,只有一个比较旧的Apache HttpClient,最近更新时间还是2011年。怪不得我看网上关于Java开发微信的资源比较少,原来真的挺麻烦的。
所以呢,这个功能就这样作罢吧。如果需要更新菜单可以使用在线调试工具,这个倒是比较方便。
查询自定义菜单
这个倒是比较简单。我们只要向下面的URL发送GET请求即可,微信服务器就会将对应的自定义菜单的JSON格式返回给我们。
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
删除自定义菜单
删除自定义菜单也很简单,同样的,向下面的URL发送GET请求即可。
https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
结语
本来微信开发还有很多内容。但是到了这里我就完全不想写了。一来与微信交互需要发送多种类型的HTTP请求给微信服务器。但是我找了一下没找到好用的Java或Kotlin类库。二来微信的官方开发文档写的实在是捉急,例子残缺不全,很多地方也没讲明白。我强行硬啃Spring英文文档都能看个八九不离十。但是我看微信的官方中文文档居然有地方看不懂。所以这系列就到此为止了。谢谢大家的支持!
代码放在csdn代码库上了,虽然不是一个完整的项目,但是包含了与微信对接和管理凭据的一点代码。对于想用Java或Kotlin开发微信公众号的同学可能有一点参考价值。
玩一玩微信公众号开发(二) 管理凭据和自定义菜单相关推荐
- 【微信公众号开发】【3】自定义菜单
前言: 1,目前公众号类型分为两种:服务号和订阅号(服务号主要面向企业.政府和其他组织,而订阅号主要面向媒体和个人) 区别:只有服务号可以申请自定义菜单:服务号每月只能群发四条消息,而订阅号每天能群发 ...
- 微信公众号开发整理(五)--自定义菜单
1.自定义菜单功能: 数据结构类型参照微信公众平台数据格式,这里不做分析: 创建相应的实体类: public class Button { //菜单类型 private String type; // ...
- PHP 一一 微信公众号开发(二次开发)
两个星期前,学校请了传智播客的老师给我们做实训,讲了一个微信公众号开发,感觉挺有意思,在这里做一下记录,以便以后复习. 一.了解微信公众平台 1. 什么是微信公众平台? 微信公众平台是腾讯为了让用户申 ...
- 微信公众平台开发教程(五)自定义菜单
请尊重作者版权,如需转载,请标明出处. 应大家强烈要求,将自定义菜单功能课程提前. 一.概述: 如果只有输入框,可能太简单,感觉像命令行.自定义菜单,给我们提供了很大的灵活性,更符合用户的操作习惯.在 ...
- 微信公众号开发(二)---验证服务与回复消息
经过第一个阶段的工作,公众号服务器方面的配置已经完成,接下来就是开发环境的搭建了. 准备工作请看上一篇文章: 0. 消息的传递路径 1. 启动XShell,开启端口转发 按照上一篇文章对XShell进 ...
- 微信公众号开发(四)——点击菜单回复图片和语音
先讲回复图片,语音类似. 这个发送图片,并不是点击输入框右侧的"➕",去选择本地照片,而是要把图片上传的公众号的服务器. 按照开发文档https://developers.weix ...
- 微信公众号的搭建-第五天-自定义菜单
1. 在微信公众平台上面开发者文档中的自定义菜单可以查看包括创建.查询.删除.自动推送的接口及注意事项 一级菜单最多三个,二级菜单最多5个,一级菜单最多显示4个汉字,二级菜单最多显示7个汉字 看完之后 ...
- 微信公众号开发系列-玩转微信开发-目录汇总
引言 最遗憾的不是把理想丢在路上,而是理想从未上路. 每一个将想法变成现实的人,都值得称赞和学习.致正在奔跑的您! 在现在这个无处不在的互联网背景下,各种应用已不再仅仅局限于网页或桌面应用了,IOS. ...
- 微信公众号开发C#系列-12、微信前端开发利器:WeUI
本文目录 1.前言 2.WeUI基本介绍 2.1 WeUI概述 2.2 为什么选择jQuery WeUI 3.jQuery WeUI基本用法 4.其他基础组件展示 4.1.switch开关 4.2.文 ...
- 微信公众号开发系列-13、基于RDIFramework.NET框架整合微信开发应用效果展示
微信公众号开发系列-13.基于RDIFramework.NET框架整合微信开发应用效果展示 1.前言 通过前面一系列文章的学习,我们对微信公众号开发已经有了一个比较深入和全面的了解. 微信公众号开发为 ...
最新文章
- 大学生应该学习python和linux而不是matlab和windows
- C#WinForm App自动更新(Live Update)架构
- LOL快要凉?腾讯电竞应如何破除游戏生命周期诅咒
- DB2数据库表追加字段
- 行内元素和块级元素的区别
- Spring:延迟初始化
- java面试要点---ArrayList list = new ArrayList(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象。
- 关于“单元组”数量的计算
- 新加坡圣淘沙亲子游自助游景点购票攻略
- h5 ios Safair下载文件自动添加.html导致文件乱码问题,ios不能使用接口播放视频的问题
- 蓝绿发布、金丝雀发布、A/B测试
- Linux 定时任务shell脚本定时移动服务器日志文件到指定目录下
- svn服务器搭建(一) VisualSVN-Server
- Linux常用基础指令、Linux常用工具(软件包)使用带图详解
- WmiPrvSe.exe 的 cpu 占用
- python中的拉链函数:zip()、zip(*)
- 网络工程师笔记——密钥分配
- 刷脸支付提高技术服务水平以及用户黏性
- 【蓝桥杯单片机】DS1302模块
- (附源码)ssm驾校考试车预约管理系统 毕业设计 271506
热门文章
- 3加3减!让商家好好做生意,阿里绝对是认真的!
- 《Sequence Models》课堂笔记
- web服务器没有对应站点,原因:您的请求在Web服务器中没有找到对应的站点的解决方法...
- Go语言设计与实现 -- 内存管理器
- sshxcute_Java 使用SSH连接Linux 使用passwd命令修改密码
- Prometheus使用cAdvisor监控Docker容器指标
- C# #region简单使用
- GNS3 思科(Cisco)PIX虚拟防火墙简单配置
- 硬核照片显示,魔方即视感
- BUUCTF RE WP31-32 [WUSTCTF2020]level1、[GWCTF 2019]xxor