zoukankan      html  css  js  c++  java
  • Java企业微信开发_07_JSSDK多图上传

    一、本节要点

    1.1可信域名

     所有的JS接口只能在企业微信应用的可信域名下调用(包括子域名),可在企业微信的管理后台“我的应用”里设置应用可信域名。这个域名必须要通过ICP备案,不然jssdk会配置失败

    1.2JS-SDK使用权限签名算法

    1.2.1 签名生成规则如下:

    (1)参与签名的字段包括:

              noncestr(随机字符串),

             有效的jsapi_ticket,

              timestamp(时间戳),

              url(当前网页的URL,不包含#及其后面部分) 。

    (2)对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

    (3)对string1进行sha1签名,得到signature:

    1.2.2示例:

    (1)待签名参数:

          noncestr=Wm3WZYTPz0wzccnW

          jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg

          timestamp=1414587457

          url=http://mp.weixin.qq.com

    (2)字典序

    string1=jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com

    (3)sha1加密

    signature=sha1(string1)

    1.2.3代码示例:

     1     /**
     2      * 3.获取微信的JSSDK配置信息
     3      * @param request
     4      * @return
     5      */
     6     public static Map<String, Object> getWxConfig(HttpServletRequest request) {
     7         Map<String, Object> ret = new HashMap<String, Object>();
     8         //1.准备好参与签名的字段
     9 
    10         String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串
    11         //System.out.println("nonceStr:"+nonceStr);
    12         String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    13         String jsapi_ticket =getJsapiTicket(accessToken);// 必填,生成签名的H5应用调用企业微信JS接口的临时票据
    14         //System.out.println("jsapi_ticket:"+jsapi_ticket);
    15         String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳
    16         //System.out.println("timestamp:"+timestamp);
    17         String url=request.getRequestURL().toString();
    18         //System.out.println("url:"+url);
    19         
    20         //2.字典序           ,注意这里参数名必须全部小写,且必须有序
    21         String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "&timestamp=" + timestamp + "&url=" + url;
    22 
    23         //3.sha1签名
    24         String signature = "";
    25         try {
    26             MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    27             crypt.reset();
    28             crypt.update(sign.getBytes("UTF-8"));
    29             signature = byteToHex(crypt.digest());
    30             //System.out.println("signature:"+signature);
    31         } catch (NoSuchAlgorithmException e) {
    32             e.printStackTrace();
    33         } catch (UnsupportedEncodingException e) {
    34             e.printStackTrace();
    35         }
    36         ret.put("appId", WeiXinParamesUtil.corpId);
    37         ret.put("timestamp", timestamp);
    38         ret.put("nonceStr", nonceStr);
    39         ret.put("signature", signature);
    40         return ret;
    41     }
    42 
    43 
    44     /**
    45      * 方法名:byteToHex</br>
    46      * 详述:字符串加密辅助方法 </br>
    47      * 开发人员:souvc  </br>
    48      * 创建时间:2016-1-5  </br>
    49      * @param hash
    50      * @return 说明返回值含义
    51      * @throws 说明发生此异常的条件
    52      */
    53     private static String byteToHex(final byte[] hash) {
    54         Formatter formatter = new Formatter();
    55         for (byte b : hash) {
    56             formatter.format("%02x", b);
    57         }
    58         String result = formatter.toString();
    59         formatter.close();
    60         return result;
    61 
    62     }
    63     
    64     
    65     
    66     private static String getExt(String contentType){
    67         if("image/jpeg".equals(contentType)){
    68             return ".jpg";
    69         }else if("image/png".equals(contentType)){
    70             return ".png";
    71         }else if("image/gif".equals(contentType)){
    72             return ".gif";
    73         }
    74         
    75         return null;
    76     }
    View Code

    二、代码实现

    2.1 配置可信域名

    在登录企业微信后台,配置应用:企业应用->自建应用->选择你的应用->网页授权及JS-SDK->输入你的域名。

    这样安全域名就配置好了。

    2.2 JSSDK的前端页面—JSSDKUploadPics.jsp

    此页面完整代码:

    <%@ page language="java" import="java.util.*"
        contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
    <%@page language="java" import="com.ray.util.WeiXinUtil"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    
    <head>
    <title>上传报销单</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <script src="js/jquery-3.2.1.min.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    <style type="text/css">
    html {
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%;
        -webkit-user-select: none;
        user-select: none;
    }
    
    body {
        line-height: 1.6;
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        background-color: #f1f0f6;
    }
    
    * {
        margin: 0;
        padding: 0;
    }
    
    button {
        font-family: inherit;
        font-size: 100%;
        margin: 0;
        *font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    
    ul, ol {
        padding-left: 0;
        list-style-type: none;
    }
    
    a {
        text-decoration: none;
    }
    
    .label_box {
        background-color: #ffffff;
    }
    
    .label_item {
        padding-left: 15px;
    }
    
    .label_inner {
        padding-top: 10px;
        padding-bottom: 10px;
        min-height: 24px;
        position: relative;
    }
    
    .label_inner:before {
        content: " ";
        position: absolute;
        left: 0;
        top: 0;
         200%;
        height: 1px;
        border-top: 1px solid #ededed;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-transform: scale(0.5);
        transform: scale(0.5);
        top: auto;
        bottom: -2px;
    }
    
    .lbox_close {
        position: relative;
    }
    
    .lbox_close:before {
        content: " ";
        position: absolute;
        left: 0;
        top: 0;
         200%;
        height: 1px;
        border-top: 1px solid #ededed;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-transform: scale(0.5);
        transform: scale(0.5);
    }
    
    .lbox_close:after {
        content: " ";
        position: absolute;
        left: 0;
        top: 0;
         200%;
        height: 1px;
        border-top: 1px solid #ededed;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-transform: scale(0.5);
        transform: scale(0.5);
        top: auto;
        bottom: -2px;
    }
    
    .lbox_close .label_item:last-child .label_inner:before {
        display: none;
    }
    
    .btn {
        display: block;
        margin-left: auto;
        margin-right: auto;
        padding-left: 14px;
        padding-right: 14px;
        font-size: 18px;
        text-align: center;
        text-decoration: none;
        overflow: visible;
        /*.btn_h(@btnHeight);*/
        height: 42px;
        border-radius: 5px;
        -moz-border-radius: 5px;
        -webkit-border-radius: 5px;
        box-sizing: border-box;
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        color: #ffffff;
        line-height: 42px;
        -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
    }
    
    .btn.btn_inline {
        display: inline-block;
    }
    
    .btn_primary {
        background-color: #437DBA;
    }
    
    .btn_primary:not (.btn_disabled ):visited {
        color: #ffffff;
    }
    
    .btn_primary:not (.btn_disabled ):active {
        color: rgba(255, 255, 255, 0.9);
        background-color: #3b78b9;
    }
    
    button.btn {
         100%;
        border: 0;
        outline: 0;
        -webkit-appearance: none;
    }
    
    button.btn:focus {
        outline: 0;
    }
    
    .wxapi_container {
        font-size: 16px;
    }
    
    h1 {
        font-size: 14px;
        font-weight: 400;
        line-height: 2em;
        padding-left: 15px;
        color: #8d8c92;
    }
    
    .desc {
        font-size: 14px;
        font-weight: 400;
        line-height: 2em;
        color: #8d8c92;
    }
    
    .wxapi_index_item a {
        display: block;
        color: #3e3e3e;
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    }
    
    .wxapi_form {
        background-color: #ffffff;
        padding: 0 15px;
        margin-top: 30px;
        padding-bottom: 15px;
    }
    
    h3 {
        padding-top: 16px;
        margin-top: 25px;
        font-size: 16px;
        font-weight: 400;
        color: #3e3e3e;
        position: relative;
    }
    
    h3:first-child {
        padding-top: 15px;
    }
    
    h3:before {
        content: " ";
        position: absolute;
        left: 0;
        top: 0;
         200%;
        height: 1px;
        border-top: 1px solid #ededed;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-transform: scale(0.5);
        transform: scale(0.5);
    }
    
    .btn {
        margin-bottom: 15px;
    }
    </style>
    
    
    </head>
    <body>
        <%
            Map<String, Object> res = new HashMap<String, Object>();
            res = WeiXinUtil.getWxConfig(request);
            request.setAttribute("appId", res.get("appId"));
            request.setAttribute("timestamp", res.get("timestamp"));
            request.setAttribute("nonceStr", res.get("nonceStr"));
            request.setAttribute("signature", res.get("signature"));
        %>
    
    <body>
        <div class="wxapi_container">
    
            <form action="" method="POST"></form>
    
    
    
            <div class="lbox_close wxapi_form">
                <h3 id="menu-basic">基础接口</h3>
                <span class="desc">判断当前客户端是否支持指定JS接口</span>
                <button class="btn btn_primary" id="checkJsApi">checkJsApi</button>
    
                <span class="desc">上传图片接口</span>
                <button class="btn btn_primary" id="uploadImage">uploadImage</button>
                <span class="desc">下载图片接口</span>
                <button class="btn btn_primary" id="downloadImage">downloadImage</button>
    
    
                <span class="desc">调起微信扫一扫接口</span>
                <button class="btn btn_primary" id="scanQRCode1">scanQRCode(直接返回结果)</button>
    
                <span class="desc">测试按钮</span>
                <button class="btn btn_primary" id="ceshi">ceshi</button>
    
            </div>
        </div>
    
        <script>
            /*
             * 注意:
             * 所有的JS接口只能在应用配置的安全域名下面使用。   
             *
             */
            wx.config({
                beta : true,
                debug : true,
                appId : '${appId}',
                timestamp : '${timestamp}',
                nonceStr : '${nonceStr }',
                signature : '${signature}',
    
                jsApiList : [ 'checkJsApi', 'chooseImage', 'previewImage',
                        'uploadImage', 'downloadImage', 'scanQRCode', ]
            });
    
            //通过ready接口处理成功验证
            wx.ready(function() {
                // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
                $("#ceshi").click(function() {
                    alert("ceshi11111111");
                });
    
            });
    
            // 1 判断当前版本是否支持指定 JS 接口,支持批量判断
            $("#checkJsApi").click(function() {
                wx.checkJsApi({
                    jsApiList : [ 'getNetworkType', 'previewImage' ],
                    success : function(res) {
                        alert(JSON.stringify(res));
                    }
                });
            });
    
            //2.拍照或从手机相册中选图接口
            var images = {
                localId : [],
                serverId : []
            };
            $("#uploadImage").click(function() {
                wx.chooseImage({
                    success : function(res) {
                        images.localId = res.localIds;
                        alert('已选择 ' + res.localIds.length + ' 张图片');
    
                        uploadImg();
                    }
                });
            });
    
            // 5.3 上传图片
            function uploadImg() {
                if (images.localId.length == 0) {
                    alert('请先使用 chooseImage 接口选择图片');
                    return;
                }
                var i = 0, length = images.localId.length;
                images.serverId = [];
    
                function upload() {
                    wx
                            .uploadImage({
                                localId : images.localId[i],
                                success : function(res) {
                                    i++;
                                    alert('已上传:' + i + '/' + length);
                                    images.serverId.push(res.serverId);
                                    //将serverId上传至服务器
                                    alert("ajax请求即将执行--");
    
                                    $
                                            .ajax({
                                                type : "POST",
                                                url : "http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/uploadExpenseAccaoutServlet",
                                                data : {
                                                    serverId : res.serverId
                                                },
                                                dataType : "text",
                                                success : function(data) {
                                                    alert(data);
                                                }
    
                                            });
    
                                    if (i < length) {
                                        upload();
                                    }
                                },
                                fail : function(res) {
                                    alert(JSON.stringify(res));
                                }
                            });
                }
                upload();
            };
    
            //点击扫描按钮,扫描二维码并返回结果
            document.querySelector('#scanQRCode1').onclick = function() {
                wx
                        .scanQRCode({
                            desc : 'scanQRCode desc',
                            needResult : 1,
                            success : function(res) {
                                //扫码后获取结果参数:htpp://xxx.com/c/?6123,截取到url中的防伪码后,赋值给Input
                                var result = res.resultStr;
                                alert(result);
    
                                $
                                        .ajax({
                                            type : "POST",
                                            url : "http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/qrservlet",
                                            data : {
                                                result : res.resultStr
                                            },
                                            dataType : "text",
                                            success : function(data) {
                                                alert(data);
                                            }
    
                                        });
    
                            }
                        });
            };
        </script>
    
    
    </body>
    </html>
    View Code

     此页面主要包括:

    (1)引入JS文件:

    在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js

    <script src="js/jquery-3.2.1.min.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    View Code

    (2)调用后台WeiXinUtil.getWxConfig(HttpServletRequest request)方法,获取企业微信的JSSDK配置信息

        <%
            Map<String, Object> res = new HashMap<String, Object>();
            res = WeiXinUtil.getWxConfig(request);
            request.setAttribute("appId", res.get("appId"));
            request.setAttribute("timestamp", res.get("timestamp"));
            request.setAttribute("nonceStr", res.get("nonceStr"));
            request.setAttribute("signature", res.get("signature"));
        %>
    View Code

    (3)通过config接口注入权限验证配置

    wx.config({
                beta : true,
                debug : true,
                appId : '${appId}',
                timestamp : '${timestamp}',
                nonceStr : '${nonceStr }',
                signature : '${signature}',
    
                jsApiList : [ 'checkJsApi', 'chooseImage', 'previewImage',
                        'uploadImage', 'downloadImage', 'scanQRCode', ]
            });
    View Code

    (4)选择图片与图片上传,以及通过ajax调用后台servlet

        //2.拍照或从手机相册中选图接口
            var images = {
                localId : [],
                serverId : []
            };
            $("#uploadImage").click(function() {
                wx.chooseImage({
                    success : function(res) {
                        images.localId = res.localIds;
                        alert('已选择 ' + res.localIds.length + ' 张图片');
    
                        uploadImg();
                    }
                });
            });
    
            // 5.3 上传图片
            function uploadImg() {
                if (images.localId.length == 0) {
                    alert('请先使用 chooseImage 接口选择图片');
                    return;
                }
                var i = 0, length = images.localId.length;
                images.serverId = [];
    
                function upload() {
                    wx
                            .uploadImage({
                                localId : images.localId[i],
                                success : function(res) {
                                    i++;
                                    alert('已上传:' + i + '/' + length);
                                    images.serverId.push(res.serverId);
                                    //将serverId上传至服务器
                                    alert("ajax请求即将执行--");
    
                                    $
                                            .ajax({
                                                type : "POST",
                                                url : "http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/uploadExpenseAccaoutServlet",
                                                data : {
                                                    serverId : res.serverId
                                                },
                                                dataType : "text",
                                                success : function(data) {
                                                    alert(data);
                                                }
    
                                            });
    
                                    if (i < length) {
                                        upload();
                                    }
                                },
                                fail : function(res) {
                                    alert(JSON.stringify(res));
                                }
                            });
                }
                upload();
            };
    View Code

     2.3 获取企业微信JSSDK配置信息—WeiXinUtil.java

    此类完整代码:

    package com.ray.util;
    
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.net.ConnectException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.servlet.http.HttpServletRequest;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.ray.pojo.AccessToken;
    
    
    
    
    import net.sf.json.JSONException;
    import net.sf.json.JSONObject;
    
    public class WeiXinUtil {
    
        private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);  
        //微信的请求url
        //获取access_token的接口地址(GET) 限200(次/天)  
        public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";  
        //获取jsapi_ticket的接口地址(GET) 限200(次/天)  
        public final static String jsapi_ticket_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESSTOKEN";  
    
    
    
        /**
         * 1.发起https请求并获取结果 
         *  
         * @param requestUrl 请求地址 
         * @param requestMethod 请求方式(GET、POST) 
         * @param outputStr 提交的数据 
         * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
         */  
        public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
            JSONObject jsonObject = null;  
            StringBuffer buffer = new StringBuffer();  
            try {  
                // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
                TrustManager[] tm = { new MyX509TrustManager() };  
                SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
                sslContext.init(null, tm, new java.security.SecureRandom());  
                // 从上述SSLContext对象中得到SSLSocketFactory对象  
                SSLSocketFactory ssf = sslContext.getSocketFactory();  
    
                URL url = new URL(requestUrl);  
                HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
                httpUrlConn.setSSLSocketFactory(ssf);  
    
                httpUrlConn.setDoOutput(true);  
                httpUrlConn.setDoInput(true);  
                httpUrlConn.setUseCaches(false);  
                // 设置请求方式(GET/POST)  
                httpUrlConn.setRequestMethod(requestMethod);  
    
                if ("GET".equalsIgnoreCase(requestMethod))  
                    httpUrlConn.connect();  
    
                // 当有数据需要提交时  
                if (null != outputStr) {  
                    OutputStream outputStream = httpUrlConn.getOutputStream();  
                    // 注意编码格式,防止中文乱码  
                    outputStream.write(outputStr.getBytes("UTF-8"));  
                    outputStream.close();  
                }  
    
                // 将返回的输入流转换成字符串  
                InputStream inputStream = httpUrlConn.getInputStream();  
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");  
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    
                String str = null;  
                while ((str = bufferedReader.readLine()) != null) {  
                    buffer.append(str);  
                }  
                bufferedReader.close();  
                inputStreamReader.close();  
                // 释放资源  
                inputStream.close();  
                inputStream = null;  
                httpUrlConn.disconnect();  
                jsonObject = JSONObject.fromObject(buffer.toString());  
            } catch (ConnectException ce) {  
                log.error("Weixin server connection timed out.");  
            } catch (Exception e) {  
                log.error("https request error:{}", e);  
            }  
            return jsonObject;  
        }  
    
       /**
         * 2.发送https请求之获取临时素材 
         * @param requestUrl
         * @param savePath  文件的保存路径,此时还缺一个扩展名
         * @return
         * @throws Exception
         */
        public static File getFile(String requestUrl,String savePath) throws Exception {  
            //String path=System.getProperty("user.dir")+"/img//1.png";
        
            
                // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
                TrustManager[] tm = { new MyX509TrustManager() };  
                SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
                sslContext.init(null, tm, new java.security.SecureRandom());  
                // 从上述SSLContext对象中得到SSLSocketFactory对象  
                SSLSocketFactory ssf = sslContext.getSocketFactory();  
    
                URL url = new URL(requestUrl);  
                HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
                httpUrlConn.setSSLSocketFactory(ssf);  
    
                httpUrlConn.setDoOutput(true);  
                httpUrlConn.setDoInput(true);  
                httpUrlConn.setUseCaches(false);  
                // 设置请求方式(GET/POST)  
                httpUrlConn.setRequestMethod("GET");  
    
                httpUrlConn.connect();  
    
                //获取文件扩展名
                String ext=getExt(httpUrlConn.getContentType());
                savePath=savePath+ext;
                System.out.println("savePath"+savePath);
                //下载文件到f文件
                File file = new File(savePath);
    
                
                // 获取微信返回的输入流
                InputStream in = httpUrlConn.getInputStream(); 
                
                //输出流,将微信返回的输入流内容写到文件中
                FileOutputStream out = new FileOutputStream(file);
                 
                int length=100*1024;
                byte[] byteBuffer = new byte[length]; //存储文件内容
                
                int byteread =0;
                int bytesum=0;
                
                while (( byteread=in.read(byteBuffer)) != -1) {  
                    bytesum += byteread; //字节数 文件大小 
                    out.write(byteBuffer,0,byteread);  
                    
                }  
                System.out.println("bytesum: "+bytesum);
                
                in.close();  
                // 释放资源  
                out.close();  
                in = null;  
                out=null;
                
                httpUrlConn.disconnect();  
    
                
                return file;
        }  
        
        
    
        /**
         * @desc :2.微信上传素材的请求方法
         *  
         * @param requestUrl  微信上传临时素材的接口url
         * @param file    要上传的文件
         * @return String  上传成功后,微信服务器返回的消息
         */
        public static String httpRequest(String requestUrl, File file) {  
            StringBuffer buffer = new StringBuffer();  
    
            try{
                //1.建立连接
                URL url = new URL(requestUrl);
                HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  //打开链接
    
                //1.1输入输出设置
                httpUrlConn.setDoInput(true);
                httpUrlConn.setDoOutput(true);
                httpUrlConn.setUseCaches(false); // post方式不能使用缓存
                //1.2设置请求头信息
                httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
                httpUrlConn.setRequestProperty("Charset", "UTF-8");
                //1.3设置边界
                String BOUNDARY = "----------" + System.currentTimeMillis();
                httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY);
    
                // 请求正文信息
                // 第一部分:
                //2.将文件头输出到微信服务器
                StringBuilder sb = new StringBuilder();
                sb.append("--"); // 必须多两道线
                sb.append(BOUNDARY);
                sb.append("
    ");
                sb.append("Content-Disposition: form-data;name="media";filelength="" + file.length()
                + "";filename=""+ file.getName() + ""
    ");
                sb.append("Content-Type:application/octet-stream
    
    ");
                byte[] head = sb.toString().getBytes("utf-8");
                // 获得输出流
                OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream());
                // 将表头写入输出流中:输出表头
                outputStream.write(head);
    
                //3.将文件正文部分输出到微信服务器
                // 把文件以流文件的方式 写入到微信服务器中
                DataInputStream in = new DataInputStream(new FileInputStream(file));
                int bytes = 0;
                byte[] bufferOut = new byte[1024];
                while ((bytes = in.read(bufferOut)) != -1) {
                    outputStream.write(bufferOut, 0, bytes);
                }
                in.close();
                //4.将结尾部分输出到微信服务器
                byte[] foot = ("
    --" + BOUNDARY + "--
    ").getBytes("utf-8");// 定义最后数据分隔线
                outputStream.write(foot);
                outputStream.flush();
                outputStream.close();
    
    
                //5.将微信服务器返回的输入流转换成字符串  
                InputStream inputStream = httpUrlConn.getInputStream();  
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    
                String str = null;  
                while ((str = bufferedReader.readLine()) != null) {  
                    buffer.append(str);  
                }  
    
                bufferedReader.close();  
                inputStreamReader.close();  
                // 释放资源  
                inputStream.close();  
                inputStream = null;  
                httpUrlConn.disconnect();  
    
    
            } catch (IOException e) {
                System.out.println("发送POST请求出现异常!" + e);
                e.printStackTrace();
            } 
            return buffer.toString();
        }
    
        /** 
         * 2.发起http请求获取返回结果 
         *  
         * @param requestUrl 请求地址 
         * @return 
         */  
        public static String httpRequest(String requestUrl) {  
            StringBuffer buffer = new StringBuffer();  
            try {  
                URL url = new URL(requestUrl);  
                HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
    
                httpUrlConn.setDoOutput(false);  
                httpUrlConn.setDoInput(true);  
                httpUrlConn.setUseCaches(false);  
    
                httpUrlConn.setRequestMethod("GET");  
                httpUrlConn.connect();  
    
                // 将返回的输入流转换成字符串  
                InputStream inputStream = httpUrlConn.getInputStream();  
                //InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);  
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    
                String str = null;  
                while ((str = bufferedReader.readLine()) != null) {  
                    buffer.append(str);  
    
                }  
                bufferedReader.close();  
                inputStreamReader.close();  
                // 释放资源  
                inputStream.close();  
                inputStream = null;  
                httpUrlConn.disconnect();  
    
            } catch (Exception e) {  
            }  
            return buffer.toString();  
        }  
    
    
        /** 
         * 3.获取access_token 
         *  
         * @param appid 凭证 
         * @param appsecret 密钥 
         * @return 
         */  
        public static AccessToken getAccessToken(String appid, String appsecret) {  
            AccessToken accessToken = null;  
    
            String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret);  
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
            // 如果请求成功  
            if (null != jsonObject) {  
                try {  
                    accessToken = new AccessToken();  
                    accessToken.setToken(jsonObject.getString("access_token"));  
                    accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
                } catch (JSONException e) {  
                    accessToken = null;  
                    // 获取token失败  
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
                }  
            }  
            return accessToken;  
        }  
    
        /**
         * 4. 获取JsapiTicket
         * @param accessToken
         * @return
         */
        public static String getJsapiTicket(String accessToken){
    
    
            String requestUrl = jsapi_ticket_url.replace("ACCESSTOKEN", accessToken);  
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
    
            String  jsapi_ticket="";
            // 如果请求成功  
            if (null != jsonObject) {  
                try {  
                    jsapi_ticket=jsonObject.getString("ticket");  
    
                } catch (JSONException e) {  
    
                    // 获取token失败  
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
                }  
            }  
            return jsapi_ticket;  
        }
    
        /**
         * 3.获取企业微信的JSSDK配置信息
         * @param request
         * @return
         */
        public static Map<String, Object> getWxConfig(HttpServletRequest request) {
            Map<String, Object> ret = new HashMap<String, Object>();
            //1.准备好参与签名的字段
    
            String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串
            //System.out.println("nonceStr:"+nonceStr);
            String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
            String jsapi_ticket =getJsapiTicket(accessToken);// 必填,生成签名的H5应用调用企业微信JS接口的临时票据
            //System.out.println("jsapi_ticket:"+jsapi_ticket);
            String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳
            //System.out.println("timestamp:"+timestamp);
            String url=request.getRequestURL().toString();
            //System.out.println("url:"+url);
            
            //2.字典序           ,注意这里参数名必须全部小写,且必须有序
            String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "&timestamp=" + timestamp + "&url=" + url;
    
            //3.sha1签名
            String signature = "";
            try {
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(sign.getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
                //System.out.println("signature:"+signature);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            ret.put("appId", WeiXinParamesUtil.corpId);
            ret.put("timestamp", timestamp);
            ret.put("nonceStr", nonceStr);
            ret.put("signature", signature);
            return ret;
        }
    
    
        /**
         * 方法名:byteToHex</br>
         * 详述:字符串加密辅助方法 </br>
         * 开发人员:souvc  </br>
         * 创建时间:2016-1-5  </br>
         * @param hash
         * @return 说明返回值含义
         * @throws 说明发生此异常的条件
         */
        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;
    
        }
        
        
        
        private static String getExt(String contentType){
            if("image/jpeg".equals(contentType)){
                return ".jpg";
            }else if("image/png".equals(contentType)){
                return ".png";
            }else if("image/gif".equals(contentType)){
                return ".gif";
            }
            
            return null;
        }
    }
    View Code

    获取获取企业微信JSSDK配置信息的方法为:

    public static Map<String, Object> getWxConfig(HttpServletRequest request) 

    2.4创建跳转菜单按钮

    完整代码:

    MenuService.java

    package com.ray.service;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.google.gson.Gson;
    import com.ray.pojo.menu.Button;
    import com.ray.pojo.menu.CommonButton;
    import com.ray.pojo.menu.ComplexButton;
    import com.ray.pojo.menu.Menu;
    import com.ray.pojo.menu.ViewButton;
    import com.ray.util.WeiXinUtil;
    
    import net.sf.json.JSONObject;
    
    
    public class MenuService {
        private static Logger log = LoggerFactory.getLogger(MenuService.class);  
        // 菜单创建(POST) 限100(次/天)  
        public static String create_menu_url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN&agentid=AGENTID";  
    
        /** 
         * 1.创建菜单 
         *  
         * @param menu 菜单实例 
         * @param accessToken 有效的access_token 
         * @return 0表示成功,其他值表示失败 
         */  
        public void createMenu(String accessToken,Menu menu,int agentId) {  
    
            //1.获取json字符串:将Menu对象转换为json字符串
            Gson gson = new Gson(); 
            String jsonMenu =gson.toJson(menu);      //使用gson.toJson(user)即可将user对象顺序转成json
            System.out.println("jsonMenu:"+jsonMenu);
    
    
            //2.获取请求的url  
            create_menu_url = create_menu_url.replace("ACCESS_TOKEN", accessToken)
                    .replace("AGENTID", String.valueOf(agentId));  
    
            //3.调用接口,发送请求,创建菜单  
            JSONObject jsonObject = WeiXinUtil.httpRequest(create_menu_url, "POST", jsonMenu);  
            System.out.println("jsonObject:"+jsonObject.toString());
    
            //4.错误消息处理
            if (null != jsonObject) {  
                if (0 != jsonObject.getInt("errcode")) {  
                    log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
                }  
            }  
     
        }  
    
        /** 
         * 2.组装菜单数据 
         *  
         * @return 
         */  
        public  Menu getMenu() {  
        /*    ViewButton btn11 = new ViewButton();  
            btn11.setName("添加报销单");  
            btn11.setType("view");  
            btn11.setUrl("http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/uploadExpenseAccaout.jsp");  
    */
            ViewButton btn11 = new ViewButton();  
            btn11.setName("JSSDK多图上传");  
            btn11.setType("view");  
            btn11.setUrl("http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/JSSDKUploadPics.jsp");  
    
            ViewButton btn21 = new ViewButton();  
            btn21.setName("JSSDK测试(全)");  
            btn21.setType("view");  
            btn21.setUrl("http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/jsapiTicktAll.jsp");  
    
            ViewButton btn22 = new ViewButton();  
            btn22.setName("PC端网页授权");  
            btn22.setType("view");  
            btn22.setUrl("https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=ww92f5da92bb24696e&agentid=1000002&redirect_uri=http%3A%2F%2F5nffqn.natappfree.cc%2FWeiXin_QiYe_Demo%2Fwebauthorization.jsp&state=state");  
    
            
            
            CommonButton btn12 = new CommonButton();  
            btn12.setName("扫一扫");  
            btn12.setType("click");  
            btn12.setKey("12");  
    
            
            
            CommonButton btn13 = new CommonButton();  
            btn13.setName("翻译功能");  
            btn13.setType("click");  
            btn13.setKey("13");  
    
            ViewButton btn14 = new ViewButton();  
            btn14.setName("上传图片");  
            btn14.setType("view");  
            btn14.setUrl("http://5nffqn.natappfree.cc/WeiXin_SanFenBaiXue/uploadimg.jsp");  
    
    
    
            ViewButton btn15 = new ViewButton();  
            btn15.setName("上传图片2");  
            btn15.setType("view");  
            btn15.setUrl("http://5nffqn.natappfree.cc/WeiXin_SanFenBaiXue/index2.jsp");  
    
        
        
    
            
    
            CommonButton btn23 = new CommonButton();  
            btn23.setName("美女电台");  
            btn23.setType("click");  
            btn23.setKey("23");  
    
            CommonButton btn24 = new CommonButton();  
            btn24.setName("人脸识别");  
            btn24.setType("click");  
            btn24.setKey("24");  
    
            CommonButton btn25 = new CommonButton();  
            btn25.setName("聊天唠嗑");  
            btn25.setType("click");  
            btn25.setKey("25");  
    
            CommonButton btn31 = new CommonButton();  
            btn31.setName("Q友圈");  
            btn31.setType("click");  
            btn31.setKey("31");  
    
            CommonButton btn33 = new CommonButton();  
            btn33.setName("幽默笑话");  
            btn33.setType("click");  
            btn33.setKey("33");  
    
            CommonButton btn34 = new CommonButton();  
            btn34.setName("用户反馈");  
            btn34.setType("click");  
            btn34.setKey("34");  
    
            CommonButton btn35 = new CommonButton();  
            btn35.setName("关于我们");  
            btn35.setType("click");  
            btn35.setKey("35");  
    
            ViewButton btn32 = new ViewButton();  
            btn32.setName("周边搜索");  
            btn32.setType("view");  
            btn32.setUrl("http://liufeng.gotoip2.com/xiaoqrobot/help.jsp");  
    
            ComplexButton mainBtn1 = new ComplexButton();  
            mainBtn1.setName("正在做功能");  
            mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13, btn14, btn15 });  
    
            ComplexButton mainBtn2 = new ComplexButton();  
            mainBtn2.setName("测试");  
            mainBtn2.setSub_button(new Button[] { btn21, btn22, btn23, btn24, btn25 });  
    
            ComplexButton mainBtn3 = new ComplexButton();  
            mainBtn3.setName("更多");  
            mainBtn3.setSub_button(new Button[] { btn31, btn33, btn34, btn35, btn32 });  
    
            /** 
             * 这是企业号目前的菜单结构,每个一级菜单都有二级菜单项<br> 
             *  
             * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br> 
             * 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:<br> 
             * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); 
             */  
            Menu menu = new Menu();  
            menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 });  
    
            return menu;  
        }  
    
    }
    View Code

    MenuTest.java

    package com.ray.test;
    
    import org.junit.Test;
    
    import com.ray.pojo.menu.Menu;
    import com.ray.service.MenuService;
    import com.ray.util.WeiXinParamesUtil;
    import com.ray.util.WeiXinUtil;
    
    public class MenuTest {
        
      @Test    
      public void testCreateMenu(){
          //1.组装菜单
          MenuService ms=new MenuService();
          Menu menu=ms.getMenu();
          
          //2.获取access_token:根据企业id和应用密钥获取access_token
          String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
          System.out.println("accessToken:"+accessToken);
          
          //3.创建菜单
          ms.createMenu( accessToken, menu, WeiXinParamesUtil.agentId);
          
         
        
      }
      
      
      
      
    }
    View Code

    创建跳转菜单按钮,点击后,跳转到 JSSDKUploadPics.jsp页面

    (1)在MenuService.java中添加一个跳转按钮。

        ViewButton btn11 = new ViewButton();  
            btn11.setName("JSSDK多图上传");  
            btn11.setType("view");  
            btn11.setUrl("http://5nffqn.natappfree.cc/WeiXin_QiYe_Demo/JSSDKUploadPics.jsp");  
    View Code

    (2)运行MenuTest类中的testCreateMenu,来创建菜单。

    2.5 总结一下JSSDK完整过程

    这样JSSDK完整过程如下:

    (1)点击菜单按钮跳转到JSSDKUploadPics.jsp页面

    (2)调用后台方法获取微信配置信息

    (3)通过config接口注入(2)中获取的权限验证配置

    (4)弹出JSSDK配置成功的提示框

    (5)选择图片并上传到微信服务器

    (6)上传图片到微信服务器后,将微信服务器返回的图片的serverID(即mediaId)通过ajax方式传到后台servlet

    (7)在servlet中,根据接收的serverID,进行获取临时素材并存到本地的操作(这一步请见下一节)

    至此JSSDK的配置已经成功,我们可以调用微信JSSDK提供的众多接口了。

  • 相关阅读:
    php configure help
    ubuntu下编译安装PHP
    【转】Ubuntu编译安装mysql源码
    Java 处理异常 9 个最佳实践,你知道几个?
    HashMap工作原理
    LinkedList
    SpringMVC常用注解@Controller,@Service,@repository,@Component
    HTML5 APP应用实现图片上传及拍照上传功能
    bootstrap-datepicker 与bootstrapValidator同时使用时,选择日期后,无法正常触发校验
    js
  • 原文地址:https://www.cnblogs.com/shirui/p/7501375.html
Copyright © 2011-2022 走看看