微信图像接口:拍照或从手机相册中选图接口chooseImage+预览图片接口previewImage+上传图片接口uploadImage+下载图片接口downloadImage

微信JS-SDK说明文档

  • 后台获取拍照页面需先授权(原理同上一篇博客:微信网页授权)
//拍照页面
    @RequestMapping("/getTakePhotos")
    public ModelAndView getTakePhotos(HttpServletRequest request) {

        logger.info(">>>>>>>>>>>>>>>>获取拍照页面>>>>>>>>>>>>>>>>");

        ModelAndView modelAndView = new ModelAndView();

        //        部署服务器开启
        String code = request.getParameter("code");
        logger.info("code为:{}", code);
        if (StringUtils.isBlank(code)) {
            logger.info("进来这人没code,有问题");
            modelAndView.addObject("openId", "");
            modelAndView.addObject("errorInfo", "openId为空");
            modelAndView.setViewName("/mobile/404");

            return modelAndView;
        }

        String openid = "";
        try {

            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + ParamesAPI.appId+ "&secret=" + ParamesAPI.secret + "&code=" + code + "&grant_type=authorization_code";
            logger.info("url:{}", url);
            JSONObject result = HttpsClient.httpRequest(url, "GET", null);

            logger.info("获取openId的json:{}", result);
            openid = (String) result.get("openid");
            if (StringUtils.isEmpty(openid)) {
                logger.info("openid为空:{}", openid);
                /**
                 * 跳转错误页面
                 */
                modelAndView.setViewName("/mobile/404");
                return modelAndView;
            }
            request.getSession().setAttribute("openId", openid);

        } catch (Exception e) {
            logger.info("未知错误:{}", e);
            modelAndView.addObject("openId", "");
            modelAndView.addObject("errorInfo", "openId为空");
            modelAndView.setViewName("/mobile/404");
            return modelAndView;
        }

        modelAndView.setViewName("mobile/takePhotos");
        return modelAndView;
    }
  • 拍照页面takePhoto.jsp
    步骤一:绑定域名
    先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
    绑定域名
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<html>
<head>
    <meta charset="utf-8">
    <title>微信拍照title>
    <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <script type="text/javascript" src="resources/lib/jquery/jquery-1.11.0.min.js" />">script>
    
    <link href="resources/mui/css/mui.min.css" />" rel="stylesheet">
    
    <link href="resources/mui/css/app.css" />" rel="stylesheet">

head>
<body>
<div>
    <header class="mui-bar mui-bar-nav">
        <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left">a>
        <h1 class="mui-title">微信拍照h1>
    header>
    <div class="mui-content">
        <a href="javascript:;"  onclick="take_a_photo()">调用微信相机a><br>
    div>
    <br/><br/><br/><br/>
    <div>
        appId:<span id="appId">span><br/><br/>
        timestamp:<span id="timestamp">span><br/><br/>
        nonceStr:<span id="nonceStr">span><br/><br/>
        jsapi_ticket:<span id="jsapi_ticket">span><br/><br/>
        signature:<span id="signature">span><br/><br/>

        originalStr:<span id="originalStr">span><br/><br/>
        scan_result:<span id="result">span><br/><br/>
    div>
div>
body>
        <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js" type="text/javascript">script>//步骤二:引入JS文件
        <script type="text/javascript">
            $(function(){
                get_wx_config();
            })

            function get_wx_config(){
                //url(当前网页的URL,不包含#及其后面部分)
                var url = window.location.href.split('#')[0];
                var indata = {"url":url};
                $.post("" />", indata, function(data){
                    if(data.rs == 'f'){
                        alert("系统错误");
                    }else{
                        var result = data;
                        $("#appId").text(result.appId);
                        $("#timestamp").text(result.timestamp);
                        $("#nonceStr").text(result.nonceStr);
                        $("#jsapi_ticket").text(result.jsapi_ticket);
                        $("#signature").text(result.signature);
                        $("#originalStr").text(result.originalStr);

                        //步骤三:通过config接口注入权限验证配置
                        wx.config({
                            debug: true,
                            appId: result.appId,   // 必填,公众号的唯一标识
                            timestamp: result.timestamp, // 必填,生成签名的时间戳
                            nonceStr: result.nonceStr, // 必填,生成签名的随机串
                            signature: result.signature,// 必填,签名,见附录1
                            jsApiList: ["chooseImage", "previewImage", "uploadImage", "downloadImage"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                            // 基本思路是,上传图片到微信服务器->下载多媒体接口将图片下载到服务器->返回服务器存储路径->前台显示
                        });

                        // 步骤四:通过ready接口处理成功验证
                        wx.ready(function(){
                            alert("wx.config success.");
                        });

                        wx.error(function(res){
                            alert("wx.config failed.");
                            //alert(res);
                            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,
                            // 也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
                        });

                        // {"errMsg":"config:invalid signature"}
                    }
                },'json');
            }

            // 图片接口
            // 拍照、本地选图
            var images = {
                localId: [],
                serverId: []
            };

            // 拍照或者选择照片
            function take_a_photo(){
                wx.chooseImage({
                    count: 1, // 默认9,这里每次只处理一张照片
                    sizeType: ['original', 'compressed'],   // 可以指定是原图还是压缩图,默认二者都有
                    sourceType: ['album', 'camera'],        // 可以指定来源是相册还是相机,默认二者都有
                    success: function (res) {
                        images.localId = res.localIds;      // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
                        var i = 0, length = images.localId.length;
                        function upload() {
                            wx.uploadImage({
                                localId: images.localId[i],// 需要上传的图片的本地ID,由chooseImage接口获得
                                isShowProgressTips: 1, // 默认为1,显示进度提示
                                success: function(res) {
                                    i++;
                                    alert('已上传:' + i + '/' + length);
                                    images.serverId.push(res.serverId);// 返回图片的服务器端ID
                                    // res.serverId 就是 media_id,根据它去微信服务器读取图片数据:
                                    var indata = {"media_id":res.serverId};
                                    $.post("/wechat/admin/orderBase/getPhoto.json", indata, function(data){
                                        if(data.rs == 'f'){
                                            alert("系统错误");
                                        }else{
                                            alert(data);   // 返回 图片在我们自己的服务器的url
                                            wx.downloadImage({
                                                serverId: '', // 需要下载的图片的服务器端ID,由uploadImage接口获得
                                                isShowProgressTips: 1, // 默认为1,显示进度提示
                                                success: function (res) {
                                                    var localId = res.localId; // 返回图片下载后的本地ID
                                                }
                                            });
                                        }
                                    },'json');

                                    if (i < length) {
                                        upload();
                                    }
                                },
                                fail: function(res) {
                                    alert(JSON.stringify(res));
                                }
                            });
                        }
                        upload();
                    }
                });
            }
        script>
html>

-后台: 获取config接口注入权限接口

/**
     * 获取config接口注入权限
     */
    @RequestMapping("/getConfigInfo")
    @ResponseBody
    public JSONObject getConfigInfo(HttpServletRequest request,String url) {

        JSONObject jsonObject=new JSONObject();
        String noncestr = "Wm3WZYTPz0wzccnW";
        AccessToken accessToken=WeixinUtil.getAccessToken(ParamesAPI.appId,ParamesAPI.secret);
        String ticket= WeixinUtil.getJsapiTicket(accessToken.getToken(),request);

        if(ticket!=null){
            Date date=new Date();
            Long timestamp=date.getTime();
            StringBuilder sb = new StringBuilder("jsapi_ticket=");
            sb.append(ticket).append("&noncestr=").append(noncestr)
                    .append("×tamp=").append(timestamp).append("&url=").append(url);

            try {
                //指定sha1算法,加密
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                byte[] bt = sb.toString().getBytes();
                md.update(bt);
                //获取字节数组
                byte messageDigest[] = md.digest();
                // Create Hex String
                StringBuffer hexString = new StringBuffer();
                // 字节数组转换为 十六进制 数
                for (int i = 0; i < messageDigest.length; i++) {
                    String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                    if (shaHex.length() < 2) {
                        hexString.append(0);
                    }
                    hexString.append(shaHex);
                }
                String signature=hexString.toString().toUpperCase();
                /*String signature=bytes2Hex(md.digest());*/ //返回16进制字符串
                jsonObject.put("jsapi_ticket",ticket);
                jsonObject.put("appId",ParamesAPI.appId);
                jsonObject.put("timestamp",timestamp);
                jsonObject.put("nonceStr",noncestr);
                jsonObject.put("signature",signature);
                jsonObject.put("originalStr", sb.toString());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }

            /*MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 对接后的字符串进行sha1加密
            byte[] digest = md.digest(sb.toString().getBytes());
            String signature = SignUtil.byteToStr(digest).toLowerCase();*/

        }

        return jsonObject;

    }

JS-SDK使用权限签名算法:
jsapi_ticket
jsapi_ticket是公众号用于调用微信JS接口的临时票据,正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。
1. 获取access_token:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
2. 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回如下JSON:

{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

签名算法
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的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.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
如出现invalid signature 等错误详见附录5常见错误及解决办法。

相关博客地址:
1.调用微信相机:http://www.cnblogs.com/digdeep/p/5743378.html
2.signature的生成:http://blog.csdn.net/november22/article/details/54916933
3.SHA1加密、以及转化为十六进制:http://blog.csdn.net/w501631338/article/details/54406680

你可能感兴趣的:(微信开发)