在微信公眾號里打開的網頁,想要調用手機掃一掃,語音功能,這需要用到微信JS-SDK。因為是在微信里打開,受微信控制,所以只能用官方提供的sdk了。
注意-_- 坑:多個頁面用到接口,必須都配一次config,url要是當前網頁完整路徑(現在是單頁面,即www.abc.com/log,www.abc.com/list),不包括#后面的。
准備工作:
1. 認真讀官方文檔,可以減少不少坑。 (文檔也有坑,字多,有的過時了,沒更新。)
2.在公眾號后台,配置JS接口安全域名,並把文件(下圖第3點)下載到自己服務器。
3. 后端提供了接口,獲取微信的簽名等信息,用來配置config ( 前端直接調接口就行,生成簽名這些只能有后台去調微信接口,官方文檔也有寫到)
正式開發:
【掃一掃】
1.在每個用到微信接口的頁面,都需要單獨調用一次后台接口,配置一次config。 因為每次簽名所需要的url,必須是頁面完整的url。
我用到的是vue,所以在created生命周期去請求配置config。
const pageUrl = window.location.href; // 當前頁面的url const vx_url="/wx/auth"; // 這是后台提供的接口。 const data={ url:pageUrl } this.$api.get(vx_url, data).then((result) => { if (result.success) { this.$wx.config({ debug: false, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 appId: 'wx222222', // 必填,公眾號的唯一標識 timestamp:result.data.timestamp , // 必填,生成簽名的時間戳 nonceStr: result.data.noncestr, // 必填,生成簽名的隨機串 signature: result.data.signature,// 必填,簽名 jsApiList: ['scanQRCode'] // 必填,需要使用的JS接口列表 }); } });
2. 在點擊按鈕后去調用微信接口,這種方式可以直接調用,不用寫在ready里。
this.$wx.scanQRCode({ needResult: 1, // 默認為0,掃描結果由微信處理,1則直接返回掃描結果, scanType: ["qrCode"], success: (res)=> {// console.log('掃描結果',res); } });
【語音】
1.配置config
created() { const pageUrl = window.location.href; const vx_url = "/wx/auth"; const data = { url: pageUrl } this.$api.get(vx_url, data).then((result) => { if (result.success) { this.$wx.config({ debug: false, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 appId: 'wx2222', // 必填,公眾號的唯一標識 timestamp: result.data.timestamp, // 必填,生成簽名的時間戳 nonceStr: result.data.noncestr, // 必填,生成簽名的隨機串 signature: result.data.signature, // 必填,簽名 jsApiList: ['startRecord', 'stopRecord', 'uploadVoice', 'onVoiceRecordEnd' ] // 必填,需要使用的JS接口列表 }); } }); }
2.開始錄音
sendVoice(event) { event.preventDefault(); if (util.judgeEquipment().isWeixin) { this.$wx.startRecord({ success: () => { this.isSend = true; this.isReord = true; const touch = event.touches[0], //獲取第一個觸點 x = Number(touch.pageX), //頁面觸點X坐標 y = Number(touch.pageY); //頁面觸點Y坐標 // 記錄觸點初始位置 this.startX = x; this.startY = y; this.startTime = new Date().getTime(); this.voiceTxt = '松開 發送'; this.$wx.onVoiceRecordEnd({ // 錄音時間超過一分鍾沒有停止的時候會執行 complete 回調 complete: function(res) { this.resetVoiceOption(); this.uploadVoice(res.localId); } }); } }); } },
3.手指移動
touchmove(event) { const touch = event.touches[0], //獲取第一個觸點 x = Number(touch.pageX), //頁面觸點X坐標 y = Number(touch.pageY); //頁面觸點Y坐標 // 記錄移動位置 this.endX = x; this.endY = y; if (this.startY - this.endY < 0) { // 向上滑 this.recordStatusTxt = recordingTxt; this.isSend = true; } else { // 向下滑 this.recordStatusTxt = cancelRecordTxt; this.isSend = false; } },
4.結束錄音
touchend(e) { e.preventDefault(); this.resetVoiceOption(); this.endTime = new Date().getTime(); const diffTime = this.endTime - this.startTime; if (this.startTime === 0 || diffTime < 500) { this.$toast("錄音時間太短", "none", 1500); return } const recordTime = Math.ceil(diffTime / 1000); // 錄音多少秒
this.$wx.stopRecord({ success: (res) => { if (this.isSend) { this.uploadVoice(res.localId); } } }); },
5.上傳語音
由於微信服務器只會保留語音文件3天,所以需要后台去微信服務器下載到自己服務器。后端從微信下載語音接口文檔 https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_temporary_materials.html
uploadVoice(_localId) { this.$wx.uploadVoice({ localId: _localId, // 需要上傳的音頻的本地ID,由stopRecord接口獲得 isShowProgressTips: 0, // 1顯示進度提示,0不顯示 success: (resp) => { const url = '/wx/downloadVoice' // 后台提供的接口。先把語音上傳到微信服務器,然后把serverId發給后台,后台通過這id去微信服務器下載語音到自己服務器,再返回url給前端 const data = { mediaId:resp.serverId } this.$api.get(url, data).then((result) => { if (result.success) { // 返回是 .amr console.log(result.data) } }); } }); },
6.重置
resetVoiceOption(){ this.isReord = false; this.voiceTxt = '按住 說話'; this.recordStatusTxt = recordingTxt; this.startX = 0; this.startY = 0; this.endX = 0; this.endY = 0; },
7.播放
由於微信錄音文件是.amr格式,h5音頻標簽無法播放的。
方案1:后台從微信服務器下載回來語音文件時,直接轉換成MP3格式
方案2:前端使用‘benz-amr-recorder’這個庫,可以播放
const BenzAMRRecorder = require('benz-amr-recorder'); const amr = new BenzAMRRecorder(); // url是后台返回的 https://www.abc.com/7A1BAEEB.amr amr.initWithUrl(src).then(() => { amr.play(); // 播放 // const amrDuration = Math.ceil(amr.getDuration()); // console.log('音頻時長', amrDuration); // 獲取音頻時長 }); amr.onEnded(() => {// console.log(播放結束) })
附:官網事例demo
補上HTML和data部分的代碼:
用的是uni-app <view class="input"> <input v-if="featuresType == 0" class="txt" placeholder="請輸入文字" v-model="commentText" confirm-type="send" @confirm="sendTxt" /> <input disabled :placeholder="voiceTxt" v-else class="btn-voice" @longpress="sendVoice" @touchend="touchend" @touchmove="touchmove" /> </view>
data(){
return{
}
}