没搞过公众号开发,在此对各种知识盲点做个笔记。
公众号区别
服务号:每月可群发一条信息,显示在聊天列表。 订阅号:没日可群发一条信息,显示在订阅号文件夹中。
企业和组织一般选择服务号,媒体和个人一般选择订阅号。
公众号测试开发
可以申请公众平台测试账号,通过使用ngrok反向代理工具来进行本地开发。不过微信硬件产品开发必须使用正式的公众号才能测试。
各种认证加解密
验证微信服务器
在微信公众号里修改服务器URL时,微信服务器会向第三方服务器发送该条消息来验证双方。
- signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
- timestamp 时间戳
- nonce 随机数
- echostr 随机字符串
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
通信消息加解密
使用在公众号填写的 EncodingAESKey 字段基于AES加解密算法实现的。
这是通信双方的消息加密,要求不高的不采用也可。
基础接口的凭证
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发页中获得)。
微信网页授权
使用Oauth2.0协议来实现每个微信访问者ID的动态参数。
在自定义菜单URL链接中,必须是https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 格式的链接,不然无法使用微信的Oauth协议。
在用户同意后会获取到一个code。这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则获取到网页授权access_token的同时,也获取到了openid,继而可以获取到微信用户的其它信息。
另外非常重要的一点是,必须在微信公众号的 设置-公众号设置-功能设置-网页授权域名 填写你的微信网页重定向URL的域名地址或父级路径。
还要下载一个MP_verify_JM0rbIIizuRcT9p9.txt放在重定向URL的域名地址或父级路径里,确保外部可以访问。
微信网页JS接口使用的认证
要想使用微信JS的各种接口,必须先获取jsapi_ticket。
jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
上面参与签名的URL的参数也要一起写进去,post的表格就不用了。
另外非常重要的一点是,必须在微信公众号的 设置-公众号设置-功能设置-JS接口安全域名 填写你的微信网页URL的域名地址。
在用时JS接口时有一点很重要:
wx.config({
beta: true,//这个字段一定要填,而且是true,不填的话无法使用wx.invoke()接口
debug : false,
appId: '',
timestamp: '',
nonceStr: '',
signature: '',
jsApiList : ['configWXDeviceWiFi','hideOptionMenu']
});