微信公众号开发之jssdk接入和实现微信录音功能

微信提供了jssdk,可以实现微信内转发朋友圈,获取位置,录音等功能,使用jssdk首先需要接入,对网页做个验证,当前网页是否符合调用jssdk的要求,验证过程为:

1.网页向后台服务器发送验证请求

2.服务器接收到请求后获取jsapiTicket、timestamp、nonceStr三个参数,然后根据这三个参数获取signature,将timestamp、nonceStr和signature三个参数返回给前端,其中jsapiTicket是通过微信服务器获取的,获取方法看代码,nonceStr是一个随机字符串,可以写死也可以生成,signature生成方法看代码

3.前端收到后台服务器返回的数据后,调用wx.config方法向微信服务器发送请求,判断验证是否通过

4.如果验证通过会回调wx.ready方法,可以将按钮的监听放在wx.ready方法中

验证接入通过后可以调用微信提供的录音方法,录音完成后jssdk提供了播放和上传录音的接口,上传指的是上传到微信服务器,方法执行完毕后返回微信服务器的serverId,开发者可以在自己服务器上访问"https://api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + serverId,将语音文件下载到自己的服务器上。

 

代码

首先在微信公众平台是哪个配置“js安全域名”,配置完成后,此域名下的所有页面均可以接入jssdk

 需要在html里引入jssdk相关的js文件:

Index.html

html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>首页title>
    <link rel="stylesheet" href="css/jquery-weui.min.css">
    <link rel="stylesheet" href="css/weui.min.css">
    <link rel="stylesheet" href="css/mainPage.css">
head>
<body>
首页,可以放 几个按钮,用来测试相关功能
<script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js">script>
<script src="js/taskPage.js">script>
body>
html>

 

Index.js

$(function () {

    getsignature();

   });

  var isRecord = true;

  var localId;//本地保存

  var serverId;//上传后返回的服务器id

  var taskId; //任务id,ajax回调中赋值

  var voiceId;//语音id,ajax回调中赋值

  function getsignature() {

    $.ajax({

        url: "/getConfig",

        type: "get",

        dataType: "json",

        data: {url: location.href.split('#')[0]},

        success: function (result) {

            wx.config({

                debug: false,

                appId: 'wx51457f1fae702d88',

                timestamp: result.timestamp,

                nonceStr: result.nonceStr,

                signature: result.signature,

                jsApiList: ['startRecord', 'stopRecord', 'playVoice', 'uploadVoice']

            });

        }

    });

};

wx.ready(function () {

    isRecord = true;

});

  

  function beginRecord() {

    wx.startRecord({

        success: function () {

            localStorage.rainAllowRecord = 'true';

            isRecord = false;

        },

        cancel: function () {

            $.toptip('用户拒绝录音授权', 'error');

        }

    });

};

  

  function stopRecord() {

    wx.stopRecord({

        success: function (res) {

            localId = res.localId;

            showAction();

            isRecord = true;

        },

        fail: function (res) {

            alert(JSON.stringify(res));

        }

    });

};

  function showAction() {

    $.actions({

        actions: [{

            text: "上传",

            onClick: function() {

                upload();

            }

        },{

            text: "重新录音",

            onClick: function() {

                isRecord = true;

            }

        }

        ]

    });

};

  

  function upload() {

    //调用微信的上传录音接口把本地录音先上传到微信的服务器

    //不过,微信只保留3天,而我们需要长期保存,我们需要把资源从微信服务器下载到自己的服务器

    wx.uploadVoice({

        localId: localId, // 需要上传的音频的本地ID,由stopRecord接口获得

        isShowProgressTips: 1, // 默认为1,显示进度提示

        //可以在success回调里把id传给自己的服务器后台,然后走微信服务器里下载

        success: function (res) {

            isRecord = true;

            serverId = res.serverId; // 返回音频的服务器端ID

            //把录音在微信服务器上的id(res.serverId)发送到自己的服务器供下载。

            var url = '/downloadFromWechatServer';

            var data = {};

            var type = 'json';

            data.serverId = serverId;

            $.post(url,

                data,

                function (result, status) {

                    if (result.respCode == 000) {

                        $.toptip('上传成功', 'success');

                    }

                },

                type

            );

        }

    });

};

WechatController.java

@RequestMapping(value = "/getConfig", produces = "application/json")

  @ResponseBody

  public Map getSignature(HttpServletRequest request, HttpServletResponse respons) {

    String url = request.getParameter("url");

    String signature = null;

    String jsapiTicket = WechatUtil.getJsapiTicket();

    Long timestampLong = System.currentTimeMillis();

    String timestamp = timestampLong.toString().substring(0, 10);

    String nonceStr = "sxascdsscfvd";

    signature = WechatUtil.getJssdkConfigSignature(jsapiTicket, timestamp, nonceStr, url);

    Map map = new HashMap<>();

    map.put("timestamp", timestamp.toString());

    map.put("nonceStr", nonceStr);

    map.put("signature", signature);

    return map;

}
@RequestMapping("/downloadFromWechatServer")
    @ResponseBody
    public Map downloadFromWechatServer(HttpServletRequest request, HttpServletResponse respons) {
        Map map = new HashMap<>();
        String serverId = request.getParameter("serverId");
        WechatUtil.downloadFromWechat(voice.getPath(), serverId, contentIndex);
        map.put("respCode", "000");
        map.put("respDesc", "保存成功");
        return map;
    }
 

 

WechatUtil.java

/*获取全局accessToken*/

  public static String getAccessToken(){

    //判断accessToken是否已经过期,如果过期需要重新获取

    if(accessToken==null||expiresTime < new Date().getTime()){

        //发起请求获取accessToken

        String result = HttpUtil.get(GET_ACCESSTOKEN_URL.replace("APPID", APPID).replace("APPSECRET", SECRET));

        //把json字符串转换为json对象

        JSONObject json = JSON.parseObject(result);

        //缓存accessToken

        accessToken = json.getString("access_token");

        //设置accessToken的失效时间

        long expires_in = json.getLong("expires_in");

        //失效时间 = 当前时间 + 有效期(提前一分钟)

        expiresTime = new Date().getTime()+ (expires_in-60) * 1000;

    }

    return accessToken;

}
/*获取jsapi_ticket*/

  public static String getJsapiTicket(){

    //发起请求到指定的接口

    String accessToken = getAccessToken();

    System.out.println("accesstoken:"+accessToken);

    String jsapiTicketJson = HttpUtil.get(GET_TICKET_URL.replace("ACCESS_TOKEN",accessToken));

    JSONObject json = JSONObject.parseObject(jsapiTicketJson);

    String jsapiTicket = json.getString("ticket");

    return jsapiTicket;

}
/*获取jssdk-config的签名*/

  public static String getJssdkConfigSignature(String jsapi_ticket,String timestamp,String noncestr,String url){

    String signature = null ;

    String string1 = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url;

    //使用sha1加密

    System.out.println(string1);

    byte[] bytes = string1.getBytes();

    signature = DigestUtils.sha1Hex(bytes);

    System.out.println(signature);

    return signature;

}
/*从微信服务器上下载语音*/

  public static void downloadFromWechat(String path,String serverId,int index){

    String accessToken = getAccessToken();

    String url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + serverId;

    FileUtil.saveUrlAs(url, path, "GET", index);

}

HttpUtil.java

  

  import java.io.BufferedReader;

  import java.io.DataOutputStream;

  import java.io.IOException;

  import java.io.InputStreamReader;

  import java.net.HttpURLConnection;

  import java.net.URL;

  import java.util.Map;

  

  /*用来发送java http请求*/

  public class HttpUtil {

  

    public static String CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded;charset=utf-8";

  

    public static String CONTENT_TYPE_FORM_DATA = "multipart/form-data;charset=utf-8";

  

    public static String CONTENT_TYPE_PLAIN = "text/plain;charset=utf-8";

  

    public static String CONTENT_TYPE_JSON = "application/json;charset=utf-8";

  

    /**

     * @Name: post。

     * @Description: 发送post请求,并返回响应数据。

     * @Parameters: URL,要访问的url。

     * @Parameters: parms,访问参数,Map形式。

     * @Return: String,响应数据。

     */

    public static String post(String URL, Map params) {

        StringBuilder parm = new StringBuilder();

        if (params != null && !params.isEmpty()) {

            for (Map.Entry entry : params.entrySet()) {

                parm.append(entry.getKey()).append("=").append(entry.getValue()).append("&");

            }

        }

        return post(URL, parm.toString());

    }

  

    /**

     * @Name: post。

     * @Description: 发送post请求,并返回响应数据。

     * @Parameters: URL,要访问的url。

     * @Parameters: parm,访问参数。

     * @Return: String,响应数据。

     * @Author: PeiFeng

     * @Version: V1.00

     * @Create Date: 2017-8-8

     */

    public static String post(String URL, String parm) {

  

        HttpURLConnection conn = null;

        // 数据输出流,输出参数信息

        DataOutputStream dataOut = null;

        // 数据输入流,处理服务器响应数据

        BufferedReader dataIn = null;

  

        try {

            java.net.URL url = new URL(URL);

  

            // 将url以open方法返回的urlConnection连接强转为HttpURLConnection连接(标识一个url所引用的远程对象连接)

            // 此时cnnection只是为一个连接对象,待连接中

            conn = (HttpURLConnection) url.openConnection();

            // 设置连接输出流为true,默认false (post请求是以流的方式隐式的传递参数)

            conn.setDoOutput(true);

            // 设置连接输入流为true

            conn.setDoInput(true);

            // 设置请求方式为post

            conn.setRequestMethod("POST");

            // post请求缓存设为false

            conn.setUseCaches(false);

            // 设置该HttpURLConnection实例是否自动执行重定向

            conn.setInstanceFollowRedirects(true);

            // 设置内容的类型,设置为经过urlEncoded编码过的from参数

            conn.setRequestProperty("Content-Type", HttpUtil.CONTENT_TYPE_FORM_URLENCODED);

            conn.setRequestProperty("accept", "*/*");

            // conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;

            // MSIE 6.0; Windows NT 5.1;SV1)");

  

            // 建立连接

            // (请求未开始,直到connection.getInputStream()方法调用时才发起,以上各个参数设置需在此方法之前进行)

            conn.connect();

  

            // 创建输入输出流,用于往连接里面输出携带的参数,(输出内容为?后面的内容)

            dataOut = new DataOutputStream(conn.getOutputStream());

            // 将参数输出到连接

            dataOut.writeBytes(parm != null ? parm : "");

            // 输出完成后刷新并关闭流

            dataOut.flush();

            // 连接发起请求,处理服务器响应 (从连接获取到输入流并包装为bufferedReader)

            dataIn = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

            String line;

            // 用来存储响应数据

            StringBuilder sb = new StringBuilder();

            // 循环读取流

            while ((line = dataIn.readLine()) != null) {

                sb.append(line).append(System.getProperty("line.separator"));

            }

            return sb.toString();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                // 重要且易忽略步骤 (关闭流,切记!)

                if (dataOut != null) {

                    dataOut.close();

                }

                if (dataIn != null) {

                    dataIn.close();

                }

                // 销毁连接

                if (conn != null) {

                    conn.disconnect();

                }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        return null;

    }

    /**

     * @Name: get。

     * @Description: 发送get请求,并返回响应数据。

     * @Parameters: URL,要访问的url。

     * @Return: String,响应数据。

     * @Author: PeiFeng

     * @Version: V1.00

     * @Create Date: 2017-8-8

     */

    public static String get(String URL) {

        HttpURLConnection conn = null;

        BufferedReader dataIn = null;

        try {

            // 把字符串转换为URL请求地址

            URL url = new URL(URL);

            // 打开连接

            conn = (HttpURLConnection) url.openConnection();

            // 连接会话

            conn.connect();

            // 获取输入流

            dataIn = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

            String line;

            StringBuilder sb = new StringBuilder();

            while ((line = dataIn.readLine()) != null) {// 循环读取流

                sb.append(line);

            }

            return sb.toString();

  

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                // 重要且易忽略步骤 (关闭流,切记!)

                if (dataIn != null) {

                    dataIn.close();

                }

                // 销毁连接

                if (conn != null) {

                    conn.disconnect();

                }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        return null;

    }

}

 

FileUtil.java

public static File saveUrlAs(String url, String filePath, String method, int index) {

    System.out.println("filePath:" + filePath);

    //System.out.println("fileName---->"+filePath);

    //创建不同的文件夹目录

    File file = new File(filePath);

    //判断文件夹是否存在

    if (!file.exists()) {

        //如果文件夹不存在,则创建新的的文件夹

        file.mkdirs();

    }

    FileOutputStream fileOut = null;

    HttpURLConnection conn = null;

    InputStream inputStream = null;

    try {

        // 建立链接

        URL httpUrl = new URL(url);

        conn = (HttpURLConnection) httpUrl.openConnection();

        //以Post方式提交表单,默认get方式

        conn.setRequestMethod(method);

        conn.setDoInput(true);

        conn.setDoOutput(true);

        // post方式不能使用缓存

        conn.setUseCaches(false);

        //连接指定的资源

        conn.connect();

        //获取网络输入流

        inputStream = conn.getInputStream();

        BufferedInputStream bis = new BufferedInputStream(inputStream);

        //判断文件的保存路径后面是否以/结尾

        if (!filePath.endsWith("/")) {

            filePath += "/";

        }

        //写入到文件(注意文件保存路径的后面一定要加上文件的名称)

        fileOut = new FileOutputStream(filePath + index + ".amr");

        BufferedOutputStream bos = new BufferedOutputStream(fileOut);

  

        byte[] buf = new byte[4096];

        int length = bis.read(buf);

        //保存文件

        while (length != -1) {

            bos.write(buf, 0, length);

            length = bis.read(buf);

        }

        bos.close();

        bis.close();

        conn.disconnect();

    } catch (Exception e) {

        e.printStackTrace();

        System.out.println("抛出异常!!");

    }

    return file;

}

 

 

你可能感兴趣的:(java)