JAVA实现微信公众号调用摄像头保存图片到本地也可以选择本地图片

一、实现思路

1.使用微信JS-SDK工具包: <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

2.点击a链接,触发click事件调用拍照接口【chooseImage】和上传图片接口【uploadImage】,拿到mediaId

3.调用后台接口拿到返回的图片流保存到服务器

官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140&token=&lang=zh_CN

二、实现步骤

1.绑定域名

登录微信公众号平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。(如:xt.lab.cn)

如果没有测试公众号的话可以通过以下链接去注册一个,并配置JS接口安全域名

测试号管理:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

 

在本页面还要配置一下微信认证网页授权,注意授权回调页面域名不带http和www,格式比如 baidu.com

 

2.在调用摄像头页面引入相关js文件

<script src="<%=request.getContextPath()%>/staticfile/js/jquery.min.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

3.过congfig接口注入权限验证配置,并添加a链接(用来触发click事件)

<!-- a链接,触发调用摄像头 -->
<a href="javascript:" id="takePicture1" style="font-size: 26px">拍照</a>


<!-- 通过config接口注入权限验证配置 -->
<input type="hidden" id="appId" value="${appId }"/>
<input type="hidden" id="timestamp" value="${timestamp }"/>
<input type="hidden" id="nonceStr" value="${nonceStr }"/>
<input type="hidden" id="signature" value="${signature }"/>

<script>
$(function(){
    wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: $('#appId').val(), // 必填,公众号的唯一标识
        timestamp: $('#timestamp').val(), // 必填,生成签名的时间戳
        nonceStr: $('#nonceStr').val(), // 必填,生成签名的随机串
        signature: $('#signature').val(),// 必填,签名,见附录1
        jsApiList: ['chooseImage', 'uploadImage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });
});
</script>

 

4.JS-SDK使用权限签名算法,生成第三步中 config接口 所需参数 
注意:java代码使用jfinal3.1框架,使用到的缓存插件、参数获取等语法不一致,自适应相应修改。

获取access_token(官方:有效期7200秒,开发者必须在自己的服务全局缓存access_token)、jsapi_ticket、签名sign
后台代码:

    /**
     * 初始化信息页面,获取config接口 所需参数 
     * @param request
     * @param modelMap
     * @return
     */
    @RequestMapping("/configDetail")
    public String assessList(HttpServletRequest request, ModelMap modelMap){
        Map<String,String> params = getJsSdk(getJsTicket(),getUrl(request));
        modelMap.put("timestamp",params.get("timestamp"));
        modelMap.put("nonceStr",params.get("nonceStr"));
        modelMap.put("signature",params.get("signature"));
        modelMap.put("appId", WgjConstants.WX_APPID);
        return "/wx/detail.ftl";
    }

    /**
     * 保存图片到服务器,返回图片地址
     */
    @RequestMapping(value = "/getLicensePlate")
    @ResponseBody
    public Map getLicensePlate(HttpServletRequest request) throws IOException {
        Map map = new HashMap<>();
        String mediaId = request.getParameter("mediaId");
        // 保存图片到服务器,返回图片地址
        String fileUrl = saveImageToDisk(mediaId );
        map.put("fileUrl",fileUrl);

        return map;
    }


/**
 * 保存图片至服务器 
 * @param mediaId
 * @return 文件名
 */
public String saveImageToDisk(String mediaId){
    String filename = "";
    InputStream inputStream = getMedia(mediaId);
    byte[] data = new byte[1024];
    int len = 0;
    FileOutputStream fileOutputStream = null;
    try {
        //服务器存图路径
        String path = PathKit.getWebRootPath() + "/vehicleupload/";
        filename = System.currentTimeMillis() + WeixinSignUtil.getNonceStr() + ".jpg";
        fileOutputStream = new FileOutputStream(path + filename);
        while ((len = inputStream.read(data)) != -1) {
            fileOutputStream.write(data, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (fileOutputStream != null) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return filename;
}

 /**
     * 生成随机串
     */
public static String getNonceStr() {
	    String currT = getCurrTime();  
	    String strT = currT.substring(8, currT.length());  
	    String strRandom = buildRandom(4) + "";  
	    return strT + strRandom;
	}

    /**
     * 获取图片流
     */
    private InputStream getMedia(String mediaId) {
        String url = "https://api.weixin.qq.com/cgi-bin/media/get";
        String access_token = getAccessToken();
        String params = "access_token=" + access_token + "&media_id=" + mediaId;
        InputStream is = null;
        try {
            String urlNameString = url + "?" + params;
            URL urlGet = new URL(urlNameString);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            http.connect();
            // 获取文件转化为byte流
            is = http.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return is;
    }


    /**
     * 获取token
     *
     * @return
     */
    public String getAccessToken() {
        Gson gson = new Gson();
        HttpUtil http = new HttpUtil();
        String token_url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
        String tokenParam = http.get(String.format(token_url,"你的APPID","你的SECRET"));
        logger.info("重新请求token:" + tokenParam);
        
        Map param = gson.fromJson(tokenParam, Map.class);
        String val = param.get("access_token").toString();
        logger.info("重新获取到的token:" + val);
        return val;
    }


    /**
     * 获取ticket
     * @return
     * @throws Exception
     */
    public String getJsTicket() {
        String ticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";
        String jsTicket = http.get(String.format(ticket_url, getAccessToken()));
        logger.info("重新请求jsTicket:" + jsTicket);
        Map<String, Object> map = gson.fromJson(jsTicket, Map.class);
        String val = map.get("ticket").toString();
        logger.info("重新获取到的ticket:" + val);
        return val;
    }

    /**
     * 获取jssdk签名
     *
     * @param jsapiTicket ticket
     * @param url         请求界面的完整url,请去掉url“#”后面的所有字符
     * @return
     */
    public Map<String, String> getJsSdk(String jsapiTicket, String url) {
        Map<String, String> params = new HashMap<String, String>();
        String nonceStr = createNonceStr();
        String timestamp = createTimestamp();
        String string1, signature = "";
        // 注意这里参数名必须全部小写,且必须有序
        string1 = String.format("jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", jsapiTicket, nonceStr, timestamp, url);
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException", e.getMessage());
        } catch (UnsupportedEncodingException e) {
            logger.error("UnsupportedEncodingException", e.getMessage());
        }
        params.put("url", url);
        params.put("jsapi_ticket", jsapiTicket);
        params.put("nonceStr", nonceStr);
        params.put("timestamp", timestamp);
        params.put("signature", signature);
        return params;
    }

    /**
     * 生成签名的时间戳
     *
     * @return
     */
    private static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * 生成签名的随机串
     *
     * @return
     */
    private static String createNonceStr() {
        return UUID.randomUUID().toString();
    }

    /**
     * 生成签名字符串
     *
     * @param hash
     * @return
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

5.调用摄像头,获取mediaid,拿到图片流

$("#takePicture1").on('click',function(){
        wx.chooseImage({
            count: 1, // 默认9
            sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
            sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
            success: function (res) {
                var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
                wx.uploadImage({
                    localId: localIds.toString(), // 需要上传的图片的本地ID,由chooseImage接口获得
                    isShowProgressTips: 1, // 默认为1,显示进度提示
                    success: function (res) {
                        var mediaId = res.serverId; // 返回图片的服务器端ID,即mediaId
                        var params="mediaId="+mediaId;
                        //将获取到的 mediaId 传入后台 getLicensePlate,保存图片到服务器,并返回图片地址
                        $.ajax({
                            type:'post',
                            dataType:'json',
                            data:params,
//                            url:'/wx/assess/getLicensePlate.json',
                            success:function (d) {
                                alert(b.fileUrl);
                            },error:function () {
                            }
                        })
                    },
                    fail: function (res) {
                        alertModal('上传图片失败,请重试')
                    }
                });
            }
        });
      });

在此代码就编写完成了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值