接着上篇说的,在使用jssdk之前,需要先验签,也就是获取签名,而获取签名就需要几个参数,时间戳,随机数,token等,而token一天的获取次数是有限的,
所以需要在项目中保存获取到的token,每次请求token之前先获取缓存的token,比较一下是否过期,过期的话再请求获取。
这篇主要说说,jssdk的调用,
所有jssdk的使用都是基础验签成功,并且js必须放在wx.ready{function(){ }}里面。
在我的项目中目前只用到了选择照片,预览照片,照片的上传下载,语音的上传下载等
window.onload = function() { $.ajax({ contentType : "application/x-www-form-urlencoded; charset=utf-8", type : "post", url : "weixin?getsignature", data : { url : location.href.split(‘#‘)[0] }, dataType : "json", success : function(data) { console.log(data.appId + "\n " + data.nonceStr + "\n " + data.signature); console.log("==data==" + data); wx.config({ debug : false,// 打开调试 appId : data.appId, timestamp : data.timestamp, nonceStr : data.nonceStr, signature : data.signature, jsApiList : [ ‘startRecord‘, ‘stopRecord‘, ‘onVoiceRecordEnd‘, ‘playVoice‘, ‘pauseVoice‘, ‘stopVoice‘, ‘onVoicePlayEnd‘, ‘uploadVoice‘, ‘downloadVoice‘, ‘chooseImage‘, ‘previewImage‘, ‘uploadImage‘, ‘downloadImage‘ ] }); } }); } var maxCount = 9; // 5.1 拍照、本地选图 var images = { localId : [], serverId : [] }; // 定义变量 var START, END, recordTimer; var localStorage = { rainAllowRecord : ‘true‘ } var voice = { localId : [] } wx.ready(function() { console.log("ready...."); // 最大上传图片数量 // document.querySelector(‘#chooseImage‘).onclick = function() { wx.chooseImage({ count : 9, // 默认同时选择9张照片 sizeType : [ ‘original‘, ‘compressed‘ ], // 可以指定是原图还是压缩图,默认二者都有 sourceType : [ ‘album‘, ‘camera‘ ], // 可以指定来源是相册还是相机,默认二者都有 success : function(res) { images.localId = res.localIds;// 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 console.log(res.localIds); //如果选择多张照片,该res.localIds是一个数组,可以遍历显示到页面上,如果想要预览照片,在wx.ready里面才能预览照片 $(res.localIds).each(function(index, val) { $(".chat-thread").append("<li class=‘right‘ ><div class=‘stu_answer_item‘><span class=‘stu_answer_item_text‘><img class=‘answer_image‘ onclick=‘showImage(this)‘ width=‘60px‘ height=‘60px‘ src=‘" + val + "‘/></span></div></li>"); }); //展示区域,动态显示到最底部 $(‘.chat-thread‘).scrollTop($(‘.chat-thread‘)[0].scrollHeight); //选择完照片直接上传到微信服务器,这里没有做照片的选择删除操作 $("#uploadImage").click(); console.log(‘已选择 ‘ + res.localIds.length + ‘ 张图片‘); console.log(‘一共 ‘ + images.localId.length + ‘ 张图片‘); } }); }; /** * 5.3 上传图片路径需要修改 */ document.querySelector(‘#uploadImage‘).onclick = function() { if (images.localId.length == 0) { console.log(‘请先选择图片‘); return; } var i = 0, length = images.localId.length; images.serverId = []; function upload() { wx.uploadImage({ localId : images.localId[i], success : function(res) { i++; images.serverId.push(res.serverId); console.log("res.serverId") console.log(res.serverId) // images.serverId = res.serverId; // 返回图片的服务器端ID var answervalues = $("#answervalues").val(); // 给服务端id加图片标志方便后台处理,nvalue是上传到后台的数据,用冒号分割数据处理,是文本就直接保存,后缀名一致的时候表示是图片或者语音需要下载到我的服务器端方便项目中调用
原因是在微信服务器端保存的数据期限较短, var nvalue = answervalues + ‘:‘ + res.serverId + ".SUFFIX_JPG_JPEG_PICTURE"; $("#answervalues").val(nvalue); if (i < length) { upload();// 递归上传 } }, fail : function(res) { console.log(JSON.stringify(res)); } }); } upload(); }; // TODO 5.4 下载图片,该功能尽量少用,微信服务器下载有次数限制,如果使用量少的话可以使用 document.querySelector(‘#downloadImage‘).onclick = function() { if (images.serverId.length === 0) { console.log(‘请先上传图片‘); return; } var i = 0, length = images.serverId.length; images.localId = []; function download() { wx.downloadImage({ serverId : images.serverId[i], success : function(res) { i++; console.log(‘已下载:‘ + i + ‘/‘ + length); images.localId.push(res.localId); if (i < length) { download(); } } }); } download(); };
/**录音键,在页面上写一个按钮,按下的时候录音*/ $(‘#wenwen‘).on(‘touchstart‘, function(event) { console.log("按住录音。。"); event.preventDefault(); //给按下图标变化 $(‘.wenwen_text‘).css(‘background‘, ‘#c1c1c1‘); $(‘.wenwen_text span‘).css(‘color‘, ‘#fff‘); $(‘.saying‘).show(); //记录按下时间,时间过短则不使用录音功能 START = new Date().getTime(); //这里是0.3秒 recordTimer = setTimeout(function() { wx.startRecord({ success : function() { localStorage.rainAllowRecord = ‘true‘; }, cancel : function() { console.log(‘用户拒绝授权录音‘); } }); }, 300); }); // 松手结束录音 $(‘#wenwen‘).on(‘touchend‘, function(event) { event.preventDefault(); END = new Date().getTime(); $(‘.wenwen_text‘).css(‘background‘, ‘#fff‘); $(‘.wenwen_text .circle-button‘).css(‘color‘, ‘#666‘); $(‘.saying‘).hide(); console.log("结束录音"); if ((END - START) < 300) { END = 0; START = 0; // 小于300ms,不录音 console.log("小于300ms,不录音"); clearTimeout(recordTimer); } else { console.log("大于300ms,录音"); wx.stopRecord({ success : function(res) { voice.localId = res.localId;
//录音结束上传录音 uploadVoice(res.localId); }, fail : function(res) { console.log(JSON.stringify(res)); } }); } }); // 上传录音 function uploadVoice(reslocalId) { // 调用微信的上传录音接口把本地录音先上传到微信的服务器 // 不过,微信只保留3天,而我们需要长期保存,我们需要把资源从微信服务器下载到自己的服务器 wx.uploadVoice({ localId : voice.localId, // 需要上传的音频的本地ID,由stopRecord接口获得 isShowProgressTips : 1, // 默认为1,显示进度提示 success : function(res) { //上传成功后再页面显示一个图标用于播放录音 $(".chat-thread").append("<li class=‘right‘ ><div class=‘stu_answer_item‘><span class=‘stu_answer_item_text‘><img class=‘answer_voice‘ onclick=‘play_voice(this)‘ width=‘60px‘ height=‘25px‘ src=‘image/yj/media.png‘/><input type=\"text\" value=‘" + reslocalId + "‘ style=\"display: none;\"></span></div></li>"); $(‘.chat-thread‘).scrollTop($(‘.chat-thread‘)[0].scrollHeight); var value = $("#answervalues").val(); var nvalue = value + ‘:‘ + res.serverId + ".SUFFIX_MP3_RADIO_VOICES"; $("#answervalues").val(nvalue); } }); } // 注册微信播放录音结束事件【一定要放在wx.ready函数内】 wx.onVoicePlayEnd({ success : function(res) { stopWave(); } }); }); // 切换输入文字 function to_write() { $(‘.wenwen_btn img‘).attr(‘src‘, ‘image/wx/yy_btn.png‘); $(‘.wenwen_btn‘).attr(‘onclick‘, ‘to_say()‘); $(‘.write_box,.wenwen_help button‘).show(); $(‘.circle-button,.wenwen_help a‘).hide(); $(‘.write_box input‘).focus(); for_bottom(); } // 切换输入语音 function to_say() { $(‘.write_list‘).remove(); $(‘.wenwen_btn img‘).attr(‘src‘, ‘image/wx/jp_btn.png‘); $(‘.wenwen_btn‘).attr(‘onclick‘, ‘to_write()‘); $(‘.write_box,.wenwen_help button‘).hide(); $(‘.circle-button,.wenwen_help a‘).show(); } // 发送文字到缓存区显示 function up_say() { $(‘.write_list‘).remove(); var a = $(‘.write_box input‘).val().replace(":", ":"); if (a != "") { if (a.indexOf("{") != -1 || a.indexOf("}") != -1 || a.indexOf("\\") != -1 || a.indexOf("/") != -1 || a.indexOf("\"") != -1 || a.indexOf("]") != -1 || a.indexOf("[") != -1) { console.log("<fmt:message key=‘special_character‘/>"); return; } else { $(".chat-thread").append("<li class=‘right‘><div class=‘stu_answer_item‘><span class=‘stu_answer_item_text‘>" + a + "</span></div></li>"); } var value = $("#answervalues").val(); var nvalue = value + ‘:‘ + a; $("#answervalues").val(nvalue); $(‘.write_box input‘).val(‘‘); $(‘.write_box input‘).focus(); $(‘.chat-thread‘).scrollTop($(‘.chat-thread‘)[0].scrollHeight); } } // 显示输入input的文字,单独显示在一个div中,方便查看 function keyup() { var footer_height = $(‘.wenwen-footer‘).outerHeight(), text = $(‘.write_box input‘).val(), str = ‘<div class="write_list">‘ + text + ‘</div>‘; if (text == ‘‘ || text == undefined) { $(‘.write_list‘).remove(); } else { $(‘.wenwen-footer‘).append(str); $(‘.write_list‘).css(‘bottom‘, footer_height); } } function for_bottom() { var speak_height = $(‘.speak_box‘).height(); $(‘.speak_box,.speak_window‘).animate({ scrollTop : speak_height }, 500); } // 绑定图片点击事件 function showImage(node) { var thisimg = $(node).attr(‘src‘); var imglist = $(‘.answer_image‘); var srcs = new Array(); for (var i = 0; i < imglist.length; i++) { srcs.push(imglist.eq(i).attr(‘src‘)); } console.log(‘srcs=‘ + srcs); console.log(‘thisImage=‘ + thisimg); wx.ready(function() { wx.previewImage({ current : thisimg, // 当前显示图片的http链接 urls : srcs // 需要预览的图片http链接列表 }); }); } // 播放录音 function play_voice(node) { var voice_localId = $(node).parent().find("input").val(); wx.ready(function() { wx.playVoice({ localId : voice_localId }); }); }
function submit(){
//这个是包含了文本,语音的serverId,图片的serverId
var value = $("#answervalues").val();
$.ajax({
contentType : "application/x-www-form-urlencoded; charset=utf-8",
type : "post",
url : "xxx?xxxx",
data : {
answer: value
},
success : function(result) {
}
});
}
后台的处理
/** * 下载文件 * * @param media_id * 微信jssdk上传成功返回的serverId * @param answer * @param asmId */ public void downloadMedia(String media_id, StuAnswerItem answer, String asmId) { String access_token = weixinService.getAccessToken(); String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + access_token + "&media_id=" + media_id; //下载路径,自定义 String uploadFileDir = Constants.PATH_FILE + Utils.groupUserId(getCurrentUserId()) + "/" + asmId + "_a/" + asmId + "0/"; Utils.makeSureDirExists(uploadFileDir);//不存在的话可以创建该路径 // 微信音频文件默认是amr格式,需要将serverId下载成amr格式之后再转换成mp3格式,由于项目的原因这里只是做大概的
描述,更简单的是直接上传到服务器,不需要判断是图片或者语音,而我这里事先处理了相应的数据,到这里是需要判断,该文件的类型,
String fileName = answer.getAnswerItem().replace("mp3", "amr"); fileName = uploadFileDir + fileName; System.out.println("文件路径+名称==" + fileName); // 下载图片到本地服务器 download(url, fileName, answer.getAnswerType()); } /** * 下载多媒体文件到服务器 * * @param url * 微信语音图片下载url * @param filename * 保存至服务器的路径和文件名 * @param mediaType * 自定义多媒体的类型,此处根据上面定义的2代表图片,3代表音频 * @return */ public boolean download(String url, String filename, int mediaType) { try { HttpGet httpGet = new HttpGet(url); HttpResponse response = client.execute(httpGet); if (response.getStatusLine().getStatusCode() == 200) { System.out.println("url下载请求code===200"); InputStream is = response.getEntity().getContent(); OutputStream out = new FileOutputStream(filename); byte[] b = new byte[1024]; int size = is.read(b); while (size > 0) { out.write(b, 0, size); size = is.read(b); } out.close(); is.close(); System.out.println("download success!!"); //如果是语音消息,则需要将下载下来的格式转换为mp3格式,方便安卓和iso的调用,没做过比较,amr格式的音频在iso中的兼容性似乎不理想,这里直接转 if (mediaType == 3) { changeToMp3(filename, filename.replace("amr", "mp3")); } } httpGet.releaseConnection(); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 把amr格式的语音转换成MP3, * * @Title: changeToMp3 * @Description: TODO(把amr格式的语音转换成MP3) * @author pll * @param @param sourcePath amr格式文件路径 * @param @param targetPath 存放mp3格式文件路径 * @return void 返回类型 * @throws */ public static void changeToMp3(String sourcePath, String targetPath) { System.out.println("sourcePath====" + sourcePath); System.out.println("targetPath====" + targetPath); File source = new File(sourcePath); File target = new File(targetPath); AudioAttributes audio = new AudioAttributes(); Encoder encoder = new Encoder(); audio.setCodec("libmp3lame"); EncodingAttributes attrs = new EncodingAttributes(); attrs.setFormat("mp3"); attrs.setAudioAttributes(audio); try { encoder.encode(source, target, attrs); System.out.println("====change to mp3 successful===="); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } catch (InputFormatException e) { System.out.println(e.getMessage()); } catch (EncoderException e) { System.out.println(e.getMessage()); } // System.out.println("删除amr文件"); source.delete(); }
特别标注一下,项目中,amr格式转mp3格式是使用ffmpeg,需要下载一个包jave-ffmpegjave-1.0.2.jar
jar包链接