微信公众号项目总结
微信公众平台是运营者通过公众号为微信用户提供资讯和服务的平台,而公众平台开发接口则是提供服务的基础,开发者在公众平台网站中创建公众号、获取接口权限后,才可以进行开发。
公众平台开发接口简单说,是微信公众平台向第三方开发者提供的一个用户资源数据及功能的访问/使用权限。通过对开发者提供开放统一的API接口环境,来帮助微信第三方开发者访问微信公众平台的功能和资源,以达到充分自由的运用微信公众平台用户资源及功能的目的。
1.开发前准备
1.1微信公众平台开发者文档
微信公众平台开发者文档是微信公众平台为开发者提供的帮助文档,开发者在开发中遇到的问题都可以在此文档中找到解决办法,开发中所有需要特别注意的事项在文档中均有提及,因此开发者需以其为准则。
网址:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432&token=&lang=zh_CN
1.2AppID和AppSecret
需要有一个公众号,从公众号中获取AppID和AppSecret。
AppID:是公众号的编号;
AppSecret:是公众号的密钥。
获取步骤:登录公众号-基本配置,会有如下提示:
1.3回调域名(获取用户信息时使用)
进入公众号开发者中心页配置授权回调域名。具体位置:登录公众号-接口权限-网页服务-网页账号-网页授权获取用户基本信息-修改
注意,这里仅需填写全域名(如www.qq.com、www.baidu.com),勿加 http:// 等协议头及具体的地址字段;
这个域名需要是一个备案过的域名。
1.4测试工具
如果嫌手机上测试麻烦,可以使用微信官方提供的web开发者工具直接在浏览器中进行调试。
前提是需要在微信公众号中绑定开发者账号:登录公众号-开发者工具-进入web开发者工具-绑定web开发者微信账号
使用说明及下载地址:
https://mp.weixin.qq.com/wiki?action=doc&id=mp1455784140&t=0.7272727088156665&token=&lang=zh_CN#6
2.公众号功能的开发步骤
(1)获取access_token(公众号全局唯一接口调用凭据);
(2)页面中引入js文件;
(3)通过config接口注入权限验证配置;
(4)通过ready接口处理成功验证;
(5)通过error接口处理失败验证;
(6)接口调用;
2.1获取acces_token(公众号全局唯一接口调用凭据)
2.1.1概述
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为7200秒,需定时刷新,重复获取将导致上次获取的access_token失效。
2.1.2access_token的管理
为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器;由于目前access_token的有效期为7200秒,因此需要定时刷新。
在这里有一个wechat4j框架,它的内部封装了对access_token的管理,包括获取access_token和access_token中控服务器的实现。
2.1.2.1wechat4j的配置
(1)创建一个web工程,导入jdk和相关的web工程jar包。
(2)下载wechat4j.jar包及其依赖jar包:
https://files.cnblogs.com/files/shuilangyizu/wechat4j-lib.rar
(3)创建wechat4j配置文件,配置你微信公众号的相关信息。
文件名称:wechat4j.properties;内容如下:
2.1.2.2access_token的获取
要获取access_token可以使用如下的方法:
String accessToken = TokenProxy.accessToken();
2.1.2.3access_token中控服务器
由中控服务器定时去刷新access_token,wechat4j的默认中控服务器是内存模式,即将access_token保存在内存中,定时刷新任务会提前200秒运行,防止到有效期之后运行过程中新access_token没有取得旧的access_token过期的情况发生,获得后会将其缓存为全局的。
2.2页面中引入js文件
在需要调用JS接口的页面引入如下JS文件,(支持https):
http://res.wx.qq.com/open/js/jweixin-1.0.0.js
如需使用摇一摇周边功能,请引入
http://res.wx.qq.com/open/js/jweixin-1.1.0.js
2.3通过config接口注入权限验证配置
微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。
微信JS SDK Demo 官方案例:
http://my.oschina.net/superkangning/blog/367484?fromerr=z6LEPSI3
通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名 jsApiList: ['checkJsApi','getLocation'] // 必填,需要使用的JS接口列表,多个以逗号“,”隔开,最后一个不需要加逗号 });
2.3.1JS-SDK使用权限签名(signature)算法
2.3.1.1jsapi_ticket
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。同样的wechat4j框架提供了对jsapi_ticket的管理,和access_token的管理机制相同。
2.3.1.2jsapi_ticket的获取
可以使用如下方法:
String jsapiTicket= TokenProxy.jsApiTicket();
2.3.1.3当前网页的url
当前网页的URL,不包含#及其后面部分,通过如下js代码在页面上获得,传递到后台进行处理。
var url = window.location.href;
2.3.1.4签名算法
获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg timestamp=1414587457 url=http://mp.weixin.qq.com?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
步骤2. 对string1进行sha1签名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事项
(1)签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
(2)签名用的url必须是调用JS接口页面的完整URL。
(3)出于安全考虑,开发者必须在服务器端实现签名的逻辑。
2.3.2权限验证成功
2.4通过ready接口处理成功验证
wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready 函数中。 });
2.5通过error接口处理失败验证
wx.error(function(res){ // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 });
2.6接口调用
2.6.1判断当前客户端版本是否支持指定JS接口
wx.checkJsApi({ jsApiList: ['chooseImage'], // 需要检测的JS接口列表, success: function(res) { // 以键值对的形式返回,可用的api值true,不可用为false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} } });
备注:checkJsApi接口是客户端6.0.2新引入的一个预留接口,第一期开放的接口均可不使用checkJsApi来检测。
2.6.2接口调用说明
所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用参数:
(1)success:接口调用成功时执行的回调函数。
(2)fail:接口调用失败时执行的回调函数。
(3)complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
(4)cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
(5)trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
备注:不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。
以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:
调用成功时:"xxx:ok" ,其中xxx为调用的接口名
用户取消时:"xxx:cancel",其中xxx为调用的接口名
调用失败时:其值为具体错误信息
3.微信公众号开发中所用到的接口
(1)getLocation:获取定位;
(2)chooseImage:选择图片;
(3)uploadImage:上传图片;
(4)startRecord:开始录音;
(5)stopRecord:结束录音;
(6)playVoice:开始播放录音;
(7)stopVoice:结束播放录音;
(8)onVoicePlayEnd:监测语音播放完毕;
(9)uploadVoice:上传录音文件;
3.1 getLocation:获取定位
3.1.1使用场景
当公众号需要获取用户位置信息的时候,就需要使用到此接口,定位成功后可以返回用户所在位置的经度,纬度,速度和位置精度等信息。
3.1.2使用方法
//调用微信获取用户位置信息的接口 wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 speed = res.speed; // 速度,以米/每秒计 accuracy = res.accuracy; // 位置精度 }, cancel: function (res) { alert('用户拒绝授权获取地理位置'); } });
如果需要显示在地图上或者要的到具体的地址信息,那么还需要进一步处理。微信公众号所使用的是百度地图,百度地图的API地址如下:
下面是js示例:
http://developer.baidu.com/map/jsdemo.htm#a1_2
3.2 chooseImage:选择图片
3.2.1使用场景
当公众号需要用户上传图片的时候,首先需要用户拍照或从手机相册中选图,而此接口会调起手机自带的相册和相机,选图成功后返回返回选定照片的本地ID列表。
3.2.2使用方法
wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { var localIds = res.localIds;// 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 } });
选择图片接口使用成功之后返回的选定照片的本地ID列表可以用于上传图片,上传图片就要调用上传图片接口,将图片上传至微信服务器上。
3.3 uploadImage:上传图片
3.3.1使用场景
当公众号用户选择好图片之后需要将图片先上传至微信服务器,上传图片接口需要拿到选择图片接口返回的选择图片本地ID,根据图片的本地ID将对应的图片传至微信服务器,上传成功后返回服务器端ID。
3.3.2使用方法
//图片上传 wx.uploadImage({ localId: localId,// 需要上传图片的本地ID,由chooseImage接口获得 isShowProgressTips: 1,// 默认为1,显示进度提示 success: function (res) { var serverId = res.serverId; // 返回图片的服务器端ID } });
微信只将使用图片上传接口上传的图片在微信服务器上面保存三天时间,因此如果需要将图片进行保存在指定的服务器上面就需要将图片进行下载保存。而通过上传图片接口上传完成返回的服务器端ID可以用于下载图片,页面可以直接通过下载图片接口进行下载图片,公众号项目的需求是是要在后台处理下载图片的,下载完成后通过流的形式写入到指定目录下。在后台通过下面网页中的下载多媒体接口下载图片:
https://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html
也可以通过下面网页中的素材管理中的获取临时素材接口下载图片:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738727&token=&lang=zh_CN
3.4 startRecord:开始录音
3.4.1使用场景
当公众号需要用户上传录音的时候,这就需要调用触发开始录音接口,此接口触发后开始录音音频文件,如果不触发结束录音接口,录音将一直持续。
3.4.2使用方法
wx.startRecord({ success: function(){ localStorage.rainAllowRecord = 'true';//记录用户是否授权 }, cancel: function () { alert('用户拒绝授权录音'); } });
3.5 stopRecord:结束录音
3.5.1使用场景
当用户触发开始录音接口之后想要结束录音就必须触发结束录音接口,否则录音将不会停止,结束录音接口触发成功后,返回录音文件本地ID。
3.5.2使用方法
//结束录音接口 wx.stopRecord({ success: function (res) { var localId = res.localId; }, fail: function (res) { alert(JSON.stringify(res)); } });
录音结束之后返回的录音文件本地ID可以用于上传录音,播放录音;上传录音就要调用上传录音接口,将录音文件上传至微信服务器上;播放录音需要调用开始播放录音接口。
3.6 playVoice:开始播放录音
3.6.1使用场景
当用户录制完语音文件之后,需要对所录制的语音进行试听,此时就可以调用开始播放录音接口,调用成功后,如果在播放过程中没有触发停止播放录音或者没有触发暂停播放录音,录音将一直播放完毕。
3.6.2使用方法
wx.playVoice({ localId: localId // 需要播放的音频的本地ID,由stopRecord接口获得 });
如果在录音播放过程中需要结束播放,可以调用结束播放录音接口,调用之后就会结束播放录音,如果不触发结束播放录音,而要在录音结束之后做其他处理,还可以在语音结束之后自动调用监测语音播放完毕接口,进行其他处理。
3.7 stopVoice:结束播放录音
3.7.1使用场景
当用户正在试听录音文件并且还没有试听结束的时候,可能会需要主动的去结束录音文件的播放,这个时候就可以调用结束播放录音接口来主动结束录音文件的播放。
3.7.2使用方法
wx.stopVoice({ localId: data.id // 需要停止的音频本地ID,由stopRecord接口获得 });
3.8 onVoicePlayEnd:监测语音播放完毕
3.8.1使用场景
当用户播放录音文件的时候,在语音结束后可能需要提示一个语音播放结束或者进行其他的自动的操作,这个时候就可以使用监测语音播放完毕接口来进行监测录音文件播放结束状态。
3.8.2使用方法
//监听语音播放完毕接口 wx.onVoicePlayEnd({ success: function (res) { var localId = res.localId; // 返回音频的本地ID } });
这个自动监测语音播放完毕接口必须放在wx.ready(function(){ });内。
3.9 uploadVoice:上传录音文件
3.9.1使用场景
当用户用户选择好录音之后就可以调用上传录音文件接口,上传录音文件接口需要拿到由stopRecord接口获得的音频文件本地ID,根据音频文件的本地ID将对应的音频文件传至微信服务器,上传成功后返回服务器端ID。
3.9.2使用方法
wx.uploadVoice({ localId: voiceLocalId, // 需要上传的音频的本地ID,由stopRecord接口获得 isShowProgressTips: 1, // 默认为1,显示进度提示 success: function (res) { var voiceServerId = res.serverId; // 返回录音文件服务器端ID } });
同样的,微信只将使用上传录音文件接口上传的录音文件在微信服务器上面保存三天时间,因此如果需要将录音文件保存在指定的服务器上面就需要将录音文件下载保存。而通过上传录音文件接口上传完成返回的服务器端ID可以用于下载录音文件,页面可以直接通过下载图片接口进行下载录音文件,公众号项目的需求是要在后台处理下载录音文件的,下载完成后通过流的形式写入到指定目录下。在后台通过下面网页中的下载多媒体接口下载音频文件:
https://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html
也可以通过下面网页中的素材管理中的获取临时素材接口下载音频文件:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738727&token=&lang=zh_CN
4.微信公众号开发中遇到的问题
4.1信息整合问题
这个问题是一开始接触微信公众号开发的时候遇到的,当时对微信公众号开发完全没有概念,况且身边没有人做过这方面的开发,只能在网上去找关于微信公众号开发的相关信息。网上的信息很庞杂,即使有微信公众号开发者文档,但是不知道从哪里着手,不知道怎么组织前后台。最后通过阅读大量的微信公众号开发博文,慢慢的摸索到了开发的路径,通过实践验证了以上总结的步骤。
4.2通过微信定位接口获取用户定位显示在百度地图上显示定位不准的问题
微信定位接口可以获取到用户的经纬度,直接将此经纬度显示在百度地图上表现出定位不准的问题。
因为微信定位获取到的用户经纬度和百度所使用的经纬度并不是同一个标准,所以出现了偏差,如果想要统一两者,就需要将微信定位接口获得的经纬度进行转换,转换方式如下:
wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 speed = res.speed; // 速度,以米/每秒计 accuracy = res.accuracy; // 位置精度 var map = new BMap.Map("allmap");//初始化百度地图 var point = new BMap.Point(longitude, latitude);//将经纬度转化为百度经纬度 var geoc = new BMap.Geocoder(); //获取百度地址解析器 translateCallback = function(point) { //回调函数 $("#Latitude").attr("value", point.lat); $("#longitude").attr("value", point.lng); geoc.getLocation(point, function(rs) { var addComp = rs.addressComponents; var Address = addComp.province + addComp.city + addComp.district + addComp.street + addComp.streetNumber; $("#locAddress").val(Address); baiduLocation(point); }); } //3: 将经纬度转换为百度的经纬度 setTimeout(function() { //此转换方法需要调用百度地图的一个js:src="http://developer.baidu.com/map/jsdemo/demo/convertor.js" BMap.Convertor.translate(point, 0, translateCallback);//真实经纬度转成百度坐标 }, 2000); }, cancel: function (res) { alert('用户拒绝授权获取地理位置'); } });
4.3公众号中公众报灾提醒问题(模板消息)
客户之前提过一个需求,当有新的公众报灾消息的时候用公众号给指定用户发送提醒消息。
一直都只以为公众号不能够实现此功能,因为公众号一个月群发消息的条数是有限制的:服务号每个月可以群发四条;订阅号每天可以群发一条。后来翻看开发者文档知道公众号可以在用户触发的情况下给用户发送模板消息;目前在特殊情况下允许主动下发的消息只有故障类和灾害警示警告类通知,除此之外都要经过用户同意或用户有触发行为才能下发模板消息。正好公众报灾属于灾害警示警告了通知。符合要求。
从这个问题中体现出来的另外一个问题是微信公众平台开发者文档的重要性。