玩一玩微信公众号开发(二) 管理凭据和自定义菜单

管理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开发微信公众号的同学可能有一点参考价值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容