【PHP+微信开发】微信JS-SDK + PHP实现录音、上传、语音识别
先看效果图:先录音,录音成功之后,把录音追加到列表,点击列表可以播放;录音完成之后上传录音,上传成功再语音识别。微信官方文档https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html实现流程:一、 公众号配置1.JS安全域名配置:登陆微信公众平台:公众号设置 -> 功能设置 -> JS安...
先看效果图:先录音,录音成功之后,把录音追加到列表,点击列表可以播放;录音完成之后上传录音,上传成功再语音识别。
微信官方文档 概述 | 微信开放文档
实现流程:
一、 公众号配置
1.JS安全域名配置:
登陆微信公众平台:公众号设置 -> 功能设置 -> JS安全域名,域名写到根域名就行,把下载的txt文件放到域名对应的根目录下
2.配置ip白名单
二、代码展示
1.前端代码
用到了'startRecord', 'stopRecord', 'playVoice', 'uploadVoice', 'translateVoice'五个接口,先调用 startRecord 开始录音,再调用 stopRecord 停止录音,会返回一个音频的本地Id,把录音追加的Html录音列表中,方便播放录音,使用 playVoice 播放录音列表中的录音,再使用 uploadVoice 把录音上传到微信服务器上,会返回微信服务器上的serverId(感觉上传录音没有使用到),通过使用本地音频id去识别语音
<!DOCTYPE html>
<html>
<head>
<title>语音识别</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<script type="text/javascript" src="/static/index/js/jquery.js"></script>
<script src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<link rel="stylesheet" type="text/css" href="/static/index/layui/css/layui.css">
<style>
button{
height: 40px;
width: 120px;
margin: 25px;
}
#ul{
margin-top: 15px;
height: 40px;
line-height: 40px;
text-align: center;
padding: 5px;
}
#ul li{
width: 80%;
}
#ullist button{
width:98%;
height:40px;
border-radius:5;
text-align: center;
margin: 5px;
}
</style>
</head>
<body>
<div class="container" style="width:100%">
<div class="row">
<ul class="list-unstyled" id="ullist">
</ul>
</div>
<div id="btn" class="navbar-fixed-bottom" style="user-select:none:align-content:center">
<center>
<button id="talk_btn" type="button" class="layui-btn">录 音</button>
<button id="uploadVoice" type="button" class="layui-btn layui-btn-normal">上传 录音</button><br>
<button id="translateVoice" type="button" class="layui-btn layui-btn-danger" style="width:90%;">语音 识别</button><br>
</center>
</div>
</div>
<script type="text/javascript">
// 全局变量
var recordTimer = 300;
var voice={
localId:'',
serverId:''
}
wx.config({
debug: false,
appId: '{$signPackage.appId}',
timestamp: {$signPackage.timestamp},
nonceStr: '{$signPackage.nonceStr}',
signature: '{$signPackage.signature}',
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'startRecord', 'stopRecord', 'playVoice', 'uploadVoice', 'translateVoice'
]
});
// 在这里调用 API
wx.ready(function () {
var START;
var END;
// 开始录音
$("#talk_btn").on('touchstart',function (event) {
// console.log(event)
event.preventDefault();
START = new Date().getTime();
// 延迟后录音,避免误操作
recordTimer = setTimeout(function () {
wx.startRecord({
success:function () {
// 授权录音
localStorage.rainAllowRecord = 'true';
},
cancel:function () {
console.log('用户拒绝了录音');
}
});
},300)
});
//松手结束录音
$('#talk_btn').on('touchend', function(event){
event.preventDefault();
END = new Date().getTime();
if((END - START) < 3000){
END = 0;
START = 0;
alert('录音时间不能少于3秒');
//小于300ms,不录音
clearTimeout(recordTimer);
}else{
var mytime = new Date().toLocaleTimeString(); //获取当前时间
wx.stopRecord({
success: function (res) {
voice.localId = res.localId;
console.log(voice.localId)
var str="<li audioid='"+voice.localId+"'><button class='layui-btn layui-btn-primary'>音频任务"+mytime+"</button></li>";
$("#ullist").append(str);//显示到列表
},
fail: function (res) {
alert(JSON.stringify(res));
}
});
}
});
});
wx.error(function (res) {
console.log(res)
});
//list播放语音
$("ul").on("click", "li", function() {
var audioid = $(this).attr("audioid");
wx.playVoice({
localId: audioid
});
})
// 上传语音
$("#uploadVoice").click(function(){
//调用微信的上传录音接口把本地录音先上传到微信的服务器
wx.uploadVoice({
localId:voice.localId, // 需要上传的音频的本地ID,由stopRecord接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success:function(res){
if(res.errMsg == 'uploadVoice:ok'){
voice.serverId = res.serverId
alert('录音上传成功');
}else{
alert(res.errMsg)
}
}
})
})
// 语音识别
$("#translateVoice").click(function(){
wx.translateVoice({
localId:voice.localId, // 需要识别的音频的本地Id,由录音相关接口获得
isShowProgressTips:1, // 默认为1,显示进度提示
success:function(res){
console.log(res)
if(res.errMsg == "translateVoice:ok"){
alert(res.translateResult); // 语音识别的结果
}else{
alert(res.errMsg)
}
}
})
})
</script>
</body>
</html>
后端代码(php)
Wechat.php 此类主要是获取accessToken和jsapiTicket
<?php
namespace app\index\controller;
use think\Controller;
/**
* 微信类
*/
class Wechat extends Controller
{
protected $APPID = 'XXXXXXXXXXXXX';
protected $APPSECRET = 'xxxxxxxxxxxxxxxxxx';
/**
* 微信服务器配置时 验证token的url
*/
public function checkToken()
{
header("Content-type: text/html; charset=utf-8");
//1.将timestamp,nonce,toke按字典顺序排序
$timestamp = $_GET['timestamp'];
$nonce = $_GET['nonce'];
$token = 'asd123456zxc';
$signature = $_GET['signature'];
$array = array($timestamp,$nonce,$token);
//2.将排序后的三个参数拼接之后用sha1加密
$tmpstr = implode('',$array);
$tmpstr = sha1($tmpstr);
//3.将加密后的字符串与signature进行对比,判断该请求是否来自微信
if($tmpstr == $signature){
echo $_GET['echostr'];
exit;
}
}
/**
* curl请求
*/
public function http_curl($url, $type = 'get', $res = 'json', $arr = ''){
$cl = curl_init();
curl_setopt($cl, CURLOPT_URL, $url);
curl_setopt($cl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($cl, CURLOPT_SSL_VERIFYHOST, false);
if($type == 'post'){
curl_setopt($cl, CURLOPT_POST, 1);
curl_setopt($cl, CURLOPT_POSTFIELDS, $arr);
}
$output = curl_exec($cl);
curl_close($cl);
return json_decode($output, true);
if($res == 'json'){
if( curl_error($cl)){
return curl_error($cl);
}else{
return json_decode($output, true);
}
}
}
/**
* 获取 AccessToken
*/
public function getAccessToken()
{
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->APPID."&secret=".$this->APPSECRET;
// 先判断 access_token 文件里的token是否过期,没过期继续使用,过期就更新
$data = json_decode($this->get_php_file(ROOT_PATH."public".DS."wxtxt".DS."access_token.txt"));
// 过期 更新
if ($data->expire_time < time()) {
$res = $this->http_curl($url);
$access_token = $res['access_token'];
if ($access_token) {
// 在当前时间戳的基础上加7000s (两小时)
$data->expire_time = time() + 7000;
$data->access_token = $res['access_token'];
$this->set_php_file(ROOT_PATH."public".DS."wxtxt".DS."access_token.txt",json_encode($data));
}
}else{
// 未过期 直接使用
$access_token = $data->access_token;
}
return $access_token;
}
/**
* 获取 JsApiTicket
*/
public function getJsApiTicket()
{
// 先判断 jsapi_ticket是否过期 没过期继续使用,过期就更新
$data = json_decode($this->get_php_file(ROOT_PATH."public".DS."wxtxt".DS."jsapi_ticket.txt"));
if ($data->expire_time < time()) {
// 过期 更新
$accessToken = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
$res = $this->http_curl($url);
$ticket = $res['ticket'];
if ($ticket) {
$data->expire_time = time() + 7000;
$data->jsapi_ticket = $ticket;
$this->set_php_file(ROOT_PATH."public".DS."wxtxt".DS."jsapi_ticket.txt",json_encode($data));
}
}else{
$ticket = $data->jsapi_ticket;
}
return $ticket;
}
// 获取存储文件中的token ticket
private function get_php_file($filename) {
return trim(file_get_contents($filename));
}
// 把token ticket 存储到文件中
private function set_php_file($filename, $content) {
$fp = fopen($filename, "w");
fwrite($fp, $content);
fclose($fp);
}
}
Wxmedia.php 此类是返回语音识别的配置信息
<?php
namespace app\index\controller;
use think\Controller;
use app\index\controller\Wechat;
/**
* 微信语音识别
*/
class Wxmedia extends Wechat
{
/**
* 语音识别
*/
public function index()
{
$signPackage = json_decode($this->getSignPackage(),true);
$this->assign('signPackage',$signPackage);
return $this->fetch();
}
/**
* 生成签名
*/
public function getSignPackage()
{
// 实例化微信操作类
$wx = new Wechat();
// 获取 ticket
$jsapiTicket = $wx->getJsApiTicket();
// 注意 URL 一定要动态获取,不能 hardcode.
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
// 当前页面的url
$url = $protocol.$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI];
$timestamp = time(); //生成签名的时间戳
$nonceStr = $this->createNonceStr(); //生成前面的随机串
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
// 对string进行sha1加密
$signature = sha1($string);
$signPackage = array(
"appId" => $wx->APPID,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"signature" => $signature
);
return json_encode($signPackage);
}
/**
* 生成签名的随机串
*/
private function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
}
思路说明:
1.公众号配置:JS安全域名、IP白名单
2.获取AccessToken,需要判断过期时间
3.获取JsApiTicket,拿获取到的AccessToken换取JsApiTicket,需要判断过期时间
4.生成签名,需要jsapiTicket+随机字符串+时间戳+当前URL 组合并sha1加密
5.组合微信JSAPI需要的参数:appId、随机字符串、时间戳、签名
更多推荐
所有评论(0)