美文网首页第三方-微信
网页分享到微信自定义标题,内容和图片

网页分享到微信自定义标题,内容和图片

作者: holy俊辉 | 来源:发表于2018-07-02 18:20 被阅读6469次

    @(I-前端学习)

    网页分享到微信中自定义标题,内容和图片

    随便说说:

    网页现在也可以通过微信中直接打开,这就是用到时微信的浏览器,也可以通过微信浏览器中右上角进行分享到朋友,朋友圈,QQ等。这是需要微信的JSSDK的机制所以还是要进行一些配置才可以,而这些配置是需要微信公众号的appId和appsecret的,所以如果没有这些,也是不能进行自定义的。

    实现过程

    1. 首先可以先阅读以下微信的JS-SDK的说明文档
      微信JS-SDK说明文档
    2. 绑定域名,登录微信公众平台,进入“公众号设置”的功能设置里面填写js接口安全域名,这个是要填写的是你微信浏览器要打开的域名地址。不能添加IP地址。
    3. 引入js文件
    4. 在需要调用js接口的页面接入JS文件 http://res.wx.qq.com/open/js/jweixin-1.2.0.js
    5. 通过config接口注入权限并验证配置
    6. 这一步算是整个步骤中最关键的一步,必须正确的配置信息才可以进行调用JS-SDK。
    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表
    });
    

    下面讲如何获取 timestamp, noceStr(记得这个驼峰结构),singature

    获取配置

    先说说最烦人的singature,对于初学小程序的简直要了老夫的命,这是啥玩意,还是签名,所以我会把自己踩的坑给大家说一下。
    获取签名实际是需要四步

    1. 根据appId和appsecret获取access_token;
    2. 使用access_token获取jsapi_ticket;
    3. 使用时间戳,随机数,jsapi_ticket和要访问的url按照签名算法拼接字符串;
    4. 对第三步的字符串进行SHA1加密,得到签名;
    第一步,获取access_token

    appId和appsecret可以在微信公众平台--开发-基本配置中查找

    public static String getAccess_token(String appId, String appSecret){
    
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
            String accessToken = null;
            try
            {
                URL urlGet = new URL(url);
                HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
                http.setRequestMethod("GET"); // 必须是get方式请求
                http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                http.setDoOutput(true);
                http.setDoInput(true);
                System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
                System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
                http.connect();
                InputStream is = http.getInputStream();
                int size = is.available();
                byte[] jsonBytes = new byte[size];
                is.read(jsonBytes);
                String message = new String(jsonBytes, "UTF-8");
                JSONObject jsonObj = JSONObject.fromObject(message);
                accessToken = jsonObj.getString("access_token");
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return accessToken;
        }
    
    第二步 获取jsapi_ticket
    /**
         * 获得ACCESS_TICKET
         * 
         * @Title: ACCESS_TICKET
         * @Description: 获得ACCESS_TICKET
         * @param @return 设定文件
         * @return String 返回类型
         * @throws
         */
        public static String getAccess_ticket(String access_token) {  
            String ticket = null;  
            String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//这个url链接和参数不能变  
            try {  
                URL urlGet = new URL(url);  
                HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();  
                http.setRequestMethod("GET"); // 必须是get方式请求  
                http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
                http.setDoOutput(true);  
                http.setDoInput(true);  
                System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒  
                System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒  
                http.connect();  
                InputStream is = http.getInputStream();  
                int size = is.available();  
                byte[] jsonBytes = new byte[size];  
                is.read(jsonBytes);  
                String message = new String(jsonBytes, "UTF-8");  
                JSONObject demoJson = JSONObject.fromObject(message);  
                System.out.println("JSON字符串:"+demoJson);  
                ticket = demoJson.getString("ticket");  
                is.close();  
            } catch (Exception e) {  
                    e.printStackTrace();  
            }  
            return ticket;  
        }  
        
    
    

    这里拿到对应的jsapi_ticket之后就可以进行参数排序和拼接字符串并加密

    第三步:SHA1加密
    public static String SHA1(String decript) {  
            try {  
                MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");  
                digest.update(decript.getBytes());  
                byte messageDigest[] = digest.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);  
                    }  
                    return hexString.toString();  
           
                } catch (NoSuchAlgorithmException e) {  
                    e.printStackTrace();  
                }  
                return "";  
        }  
    
    

    加密算法转载自:http://www.open-open.com/lib/view/open1392185662160.html

    第四步: 获取签名
    public static void main(String[] args) {  
        //1、获取AccessToken  
        String accessToken = getAccessToken();  
          
        //2、获取Ticket  
        String jsapi_ticket = getTicket(accessToken);  
          
        //3、时间戳和随机字符串  
        String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串  
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳  
          
        System.out.println("accessToken:"+accessToken+"\njsapi_ticket:"+jsapi_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+noncestr);  
          
        //4、获取url  
        String url="http://www.luiyang.com/add.html";  
        /*根据JSSDK上面的规则进行计算,这里比较简单,我就手动写啦 
        String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"}; 
        Arrays.sort(ArrTmp); 
        StringBuffer sf = new StringBuffer(); 
        for(int i=0;i<ArrTmp.length;i++){ 
            sf.append(ArrTmp[i]); 
        } 
        */  
          
        //5、将参数排序并拼接字符串  
        String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;  
         
        //6、将字符串进行sha1加密  
        String signature =SHA1(str);  
        System.out.println("参数:"+str+"\n签名:"+signature);  
    }  
    

    改写之后的代码,json格式返回。

    protected void doPost(HttpServletRequest request, HttpServletResponse response){
            
            //appId和appSecret
            String appId = "XXXXX";
            String appSecret = "XXXXX";
            
            //外部传入url获取url url需要是微信中打开的url否则会报错。
            String URL = request.getParameter("url"); 
            //转换url
            
            String url="";
            //需要转换解码url
            try {
                url = java.net.URLDecoder.decode(URL,"UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            //获取access_token
            String aeecss_token = HttpUtil.getAccess_token(appId, appSecret);
            
            //获取access_ticket
            String aeecss_ticket = HttpUtil.getAccess_ticket(aeecss_token);
            
            
             //3、时间戳和随机字符串  
            String nonceStr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串  
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳  
              
            System.out.println("accessToken:"+aeecss_token+"\njsapi_ticket:"+aeecss_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+nonceStr);  
              
            
            //4、获取url  
            //5、将参数排序并拼接字符串  
            String str = "jsapi_ticket="+aeecss_ticket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;  
             
            //6、将字符串进行sha1加密  
            String signature =SHA1(str);  
            System.out.println("参数:"+str+"\n签名:"+signature);  
            
            
            Map<String,String> map=new HashMap();
            map.put("appId",appId);
            map.put("timestamp",timestamp);
            map.put("accessToken",aeecss_token);
            map.put("ticket",aeecss_ticket);
            map.put("nonceStr",nonceStr);
            map.put("signature",signature);
            JSONObject jsonObject = JSONObject.fromObject(map);
            
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setContentType("application/json;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
    
            PrintWriter pw = null;
            try {
                pw = response.getWriter();
            } catch (IOException e1) {
                logger.error("**********reponse getWriter exception**********");
                e1.printStackTrace();
            }
            pw.write(jsonObject.toString());
            pw.close();
        }
    

    这一段代码是改写了,获取签名后把所有的信息都返回json格式了。概要的都有了,这是就可以配置config了,此时应该是:

     $.ajax({
                url: 'http://10.25.74.68:8088',
                type: 'POST',
                dataType: 'json',
                //url需要编码传入而且要是完整的url除#之后的
                data: {"url":encodeURIComponent(window.location.href.split("#")[0])}
            })
            .done(function(res) {
    
                wx.config({
                    debug: ture, //调试阶段建议开启
                    appId: res.appId,//APPID
                    timestamp: res.timestamp,//上面main方法中拿到的时间戳timestamp
                    nonceStr: res.nonceStr,//上面main方法中拿到的随机数nonceStr
                    signature: res.signature,//上面main方法中拿到的签名signature
                    //需要调用的方法接口
                    jsApiList: [ 'onMenuShareTimeline','onMenuShareAppMessage','onMenuShareWeibo','onMenuShareQQ','onMenuShareQZone']
                });
       }
    
    注意:
    1. url一定要是完整的url(当前网页的URL,不包含#及其后面部分)最好是使用window.location.href.split("#")获取得到,如果传入固定的好像会报invalid signature错误,所以为了安全起见还是直接传入当前的url
    2. 这个签名的有效时间为7200秒,也就是2个小时,因此当超过两个小时候,再访问也会报invalid signature错误。但是这个我还没有遇见,并不知道这么解决,其他说是需要缓存access_token和access_ticket
    3. 另外还有一个错误:invalid url domain
      这个跟生成签名时用的url有关系,官网的说法是:
      invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,如果使用了端口号,则配置的绑定域名也要加上端口号(一个appid可以绑定三个有效域名)
      这个url必须是:“公众号设置---功能设置----JS接口安全域名”中绑定的三个域名之一
    4. 如果以上配置都是正确,而且debug也设置为true了,在微信中访问连接会出现config:ok的界面,就说明配置成功了
    5. 有时也可以把ajax请求放在setTimeout中进行请求。

    自定义标题,内容和图片

        wx.ready(function(){
                    // alert("我已经进来了");
                    wx.onMenuShareTimeline({
                        title: title, // 分享标题
                        link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                        imgUrl: "https://img.haomeiwen.com/i3429385/09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享图标
                        success: function () {
                            // alert("成功")
                            // 用户点击了分享后执行的回调函数
                        }
                    });
                    wx.onMenuShareAppMessage({
                        title: title, // 分享标题
                        desc: descContent, // 分享描述
                        link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                        imgUrl: "https://img.haomeiwen.com/i3429385/09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享图标
                        type: '', // 分享类型,music、video或link,不填默认为link
                        dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                        success: function () {
                            // alert("成功")
                            // 用户点击了分享后执行的回调函数
                        }
                    });
                    wx.onMenuShareQQ({
                        title: title, // 分享标题
                        desc: descContent, // 分享描述
                        link: window.location.href, // 分享链接
                        imgUrl: "https://img.haomeiwen.com/i3429385/09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享图标
                        success: function () {
                            // alert("成功")
                            // 用户确认分享后执行的回调函数
                        },
                        cancel: function () {
                            // alert("失败")
                            // 用户取消分享后执行的回调函数
                            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
                        }
                    });
                });
    
    注意:
    1. 应该把自定义的内容卸载wx.ready(
      // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
      )里面,
    2. link该链接域名或路径必须与当前页面对应的公众号JS安全域名
    3. imgUrl:最好是绝对地址的图片,相对位置好像出不来 比如:'../assets/image/213.png'这样是出不来的

    验证工具:
    微信公众平台接口调试工具
    微信 JS 接口签名校验工具

    参考:
    解决微信JS-SDK扫一扫功能接入以及出现签名无效 invalid signature
    微信JS-SDK获取signature签名以及config配置

    相关文章

      网友评论

        本文标题:网页分享到微信自定义标题,内容和图片

        本文链接:https://www.haomeiwen.com/subject/pknluftx.html