zoukankan      html  css  js  c++  java
  • js-sdk探索之微信网页分享

    微信是一个很不错的传播平台,最近公司需要做一个新年贺卡,使用html5制作一个很小的动画,然后发送给客户,不需要和后台有任何的联系,一个很简单的功能,需要利用微信的分享功能,毕竟微信分享的带小图片、简介、标题比发送一个链接要比一个光秃秃的链接要高大上的多。好了,废话不多说了,进入正题吧。

    刚开始我也到网上去搜了一下,看到好多这个版本的,我也贴一下:

    var shareData = {
            "appid": appid,     //公众号的appID
            "img_url": imgUrl,  //缩略图地址
            "img_width": "120", //图片的宽度
            "img_height": "120",//图片的高度
            "link": lineLink,   //分享的链接
            "desc": descContent,//摘要的信息
            "title": shareTitle //分享的标题,默认为网页标题
            };
        
        function shareFriend() {
            WeixinJSBridge.invoke('sendAppMessage',shareData, function(res) {
                //定义分享完成后的事
                alert(dasd);
            })
        }
        function shareTimeline() {
            WeixinJSBridge.invoke('shareTimeline',shareData, function(res) {
                   //_report('timeline', res.err_msg);
            });
        }
        // 当微信内置浏览器完成内部初始化后会触发WeixinJSBridgeReady事件。
        document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
            // 发送给好友
            WeixinJSBridge.on('menu:share:appmessage', function(argv){
                shareFriend();
            });
            // 分享到朋友圈
            WeixinJSBridge.on('menu:share:timeline', function(argv){
                shareTimeline();
            });
        }, false);

    可能这个版本在微信没有发布js-sdk时是有用的,但是现在微信好像把这个方法设置了权限,这个方法已经不可用了,所以我到微信官方去看了一下,微信js-sdk已经支持开发接口支持微信分享了,怎么实现,下面一一道来:

    微信官方js-sdk链接地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html 有兴趣可以自己去研究研究,下面只是我自己的一些经验,水平有限,有错误之处欢迎大家指出。

    1. 要使用js-sdk,首先你得拥有一个微信认证过的订阅号或者服务号(个人认为如果开发的还是服务号好),然后按照微信js-sdk api的步骤来,先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。js接口安全域名可以设置三个,意思是你的网页要想使用js-sdk,访问就必须在这个域名下(如果域名带有端口号,设置的时候也必须带有端口号,微信上虽然说只支持80端口,但是我用其他端口好像也可以)。

    image

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

    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    3.通过config接口注入权限验证配置,所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。这里只说分享朋友圈和分享给朋友接口。

    wx.config({
            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: appId, // 必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: nonceStr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名,见附录1
            jsApiList: [
            'onMenuShareTimeline',
            'onMenuShareAppMessage'
            ] // 必填,分享朋友圈和分享朋友接口名
        });

    4.通过ready接口处理成功验证。

    wx.ready(function () {
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
          var shareData = {
            title: title, // 分享标题
            desc: desc, // 分享描述
            link: link, //网页地址
            imgUrl: imgUrl, //小图片的地址
            success: function () { 
               // 用户确认分享后执行的回调函数
            },
            cancel: function () { 
               // 用户取消分享后执行的回调函数
            }
          };
          wx.onMenuShareAppMessage(shareData);
          wx.onMenuShareTimeline(shareData);
      });

    5.以上就是微信文档中的处理js-sdk接口的基本步骤,完成了这些,就可以完成一个如下的分享框:

    image

    6.上面的这些步骤都是微信文档上有的,copy就行,我个人觉得初次接触,微信js-sdk的config配置相对来说是要复杂一点。就是第三点里面的签名比较难一点,下面我就详细的说一下我是怎么获得配置的参数的(appid,timestamp,noncestr,signature);首先找到js-sdk生成签名的文档,阅读发现signature的生成是需要密钥的,就是我们公众号AppSecret,这个东西是不能被别人知道的,所以我们处理密钥一定要在后台处理,在html处理的话会泄漏你的公众号关注者的信息的。所以我们得在后台写一个接口,用来返回config里的配置信息;后台怎么处理呢?(后台是用java写的)

    1>首先随机生成一个字符串(noncestr)和一个随机时间戳(timestamp),这就解决了两个配置项;

    noncestr  = Double.toString(Math.random()).substring(2, 15);//随机字符串
    timeStamp =((int)(new Date().getTime()/1000))+"";//随机时间戳

    2>然后就的获得微信的基础支持,访问微信的https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET接口,获得返回来的access_token;

    public String getAccess_token(){
            System.out.println("重新请求access_token");
            String access_token = "";
            String str = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
            str += "appid=" + APPID + "&secret=" + APPSECRET;
            try {
                URL url = new URL(str);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(CONNECTTIMEOUT);
                connection.setReadTimeout(READTIME);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
                StringBuffer stringBuffer = new StringBuffer();
                String temp = "";
                while((temp = bufferedReader.readLine())!= null){
                    stringBuffer.append(temp);
                    System.out.println(temp);
                }
                String result = stringBuffer.toString();
                JSONObject root = JSONObject.fromObject(result);
                access_token = root.getString("access_token");
                bufferedReader.close();
                
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return access_token;
        }

    3>获得微信的access_token后,就可以获得jsapi_ticket了,访问微信的https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi接口,获得返回来的jsapi_ticket;

    public String getJsapi_ticket(String access_token){
            System.out.println("重新请求jsapi_ticket");
            String jsapi_ticket = "";
            String str = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";
            try {
                URL url = new URL(str);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(CONNECTTIMEOUT);
                connection.setReadTimeout(READTIME);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
                StringBuffer stringBuffer = new StringBuffer();
                String temp = "";
                while((temp = bufferedReader.readLine())!= null){
                    stringBuffer.append(temp);
                }
                String result = stringBuffer.toString();
                JSONObject root = JSONObject.fromObject(result);
                jsapi_ticket = root.getString("ticket");
                bufferedReader.close();
                
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return jsapi_ticket;
        }

    4>获得jsapi_ticket,noncestr,timestamp还有你的网页地址后就可以生成签名了;

    public WeiXinJsServer(String url,HttpServletRequest request) {
            this.noncestr  = Double.toString(Math.random()).substring(2, 15);
            this.timeStamp =((int)(new Date().getTime()/1000))+"";
            String access_token = getAccess_token();
            String Jsapi_ticket = getJsapi_ticket(access_token);
            String str = "jsapi_ticket=" + Jsapi_ticket + "&noncestr=" + noncestr + "&timestamp="+ timeStamp +"&url=" + url;
            this.signature = new SHA1().getDigestOfString(str.getBytes()); 
        }

    5>最后在奉上sha1算法;

    public class SHA1 { 
        private final int[] abcde = { 
                0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 
            }; 
        private int[] digestInt = new int[5]; 
        private int[] tmpData = new int[80]; 
        private int process_input_bytes(byte[] bytedata) { 
            System.arraycopy(abcde, 0, digestInt, 0, abcde.length); 
            byte[] newbyte = byteArrayFormatData(bytedata); 
            int MCount = newbyte.length / 64; 
            for (int pos = 0; pos < MCount; pos++) { 
                for (int j = 0; j < 16; j++) { 
                    tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4)); 
                } 
                encrypt(); 
            } 
            return 20; 
        } 
        private byte[] byteArrayFormatData(byte[] bytedata) { 
            int zeros = 0; 
            int size = 0; 
            int n = bytedata.length; 
            int m = n % 64; 
            if (m < 56) { 
                zeros = 55 - m; 
                size = n - m + 64; 
            } else if (m == 56) { 
                zeros = 63; 
                size = n + 8 + 64; 
            } else { 
                zeros = 63 - m + 56; 
                size = (n + 64) - m + 64; 
            } 
            byte[] newbyte = new byte[size]; 
            System.arraycopy(bytedata, 0, newbyte, 0, n); 
            int l = n; 
            newbyte[l++] = (byte) 0x80; 
            for (int i = 0; i < zeros; i++) { 
                newbyte[l++] = (byte) 0x00; 
            } 
            long N = (long) n * 8; 
            byte h8 = (byte) (N & 0xFF); 
            byte h7 = (byte) ((N >> 8) & 0xFF); 
            byte h6 = (byte) ((N >> 16) & 0xFF); 
            byte h5 = (byte) ((N >> 24) & 0xFF); 
            byte h4 = (byte) ((N >> 32) & 0xFF); 
            byte h3 = (byte) ((N >> 40) & 0xFF); 
            byte h2 = (byte) ((N >> 48) & 0xFF); 
            byte h1 = (byte) (N >> 56); 
            newbyte[l++] = h1; 
            newbyte[l++] = h2; 
            newbyte[l++] = h3; 
            newbyte[l++] = h4; 
            newbyte[l++] = h5; 
            newbyte[l++] = h6; 
            newbyte[l++] = h7; 
            newbyte[l++] = h8; 
            return newbyte; 
        } 
        private int f1(int x, int y, int z) { 
            return (x & y) | (~x & z); 
        } 
        private int f2(int x, int y, int z) { 
            return x ^ y ^ z; 
        } 
        private int f3(int x, int y, int z) { 
            return (x & y) | (x & z) | (y & z); 
        } 
        private int f4(int x, int y) { 
            return (x << y) | x >>> (32 - y); 
        } 
        private void encrypt() { 
            for (int i = 16; i <= 79; i++) { 
                tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^ 
                        tmpData[i - 16], 1); 
            } 
            int[] tmpabcde = new int[5]; 
            for (int i1 = 0; i1 < tmpabcde.length; i1++) { 
                tmpabcde[i1] = digestInt[i1]; 
            } 
            for (int j = 0; j <= 19; j++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[j] + 0x5a827999; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int k = 20; k <= 39; k++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[k] + 0x6ed9eba1; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int l = 40; l <= 59; l++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[l] + 0x8f1bbcdc; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int m = 60; m <= 79; m++) { 
                int tmp = f4(tmpabcde[0], 5) + 
                    f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                    tmpData[m] + 0xca62c1d6; 
                tmpabcde[4] = tmpabcde[3]; 
                tmpabcde[3] = tmpabcde[2]; 
                tmpabcde[2] = f4(tmpabcde[1], 30); 
                tmpabcde[1] = tmpabcde[0]; 
                tmpabcde[0] = tmp; 
            } 
            for (int i2 = 0; i2 < tmpabcde.length; i2++) { 
                digestInt[i2] = digestInt[i2] + tmpabcde[i2]; 
            } 
            for (int n = 0; n < tmpData.length; n++) { 
                tmpData[n] = 0; 
            } 
        } 
        private int byteArrayToInt(byte[] bytedata, int i) { 
            return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) | 
            ((bytedata[i + 2] & 0xff) << 8) | (bytedata[i + 3] & 0xff); 
        } 
        private void intToByteArray(int intValue, byte[] byteData, int i) { 
            byteData[i] = (byte) (intValue >>> 24); 
            byteData[i + 1] = (byte) (intValue >>> 16); 
            byteData[i + 2] = (byte) (intValue >>> 8); 
            byteData[i + 3] = (byte) intValue; 
        } 
        private static String byteToHexString(byte ib) { 
            char[] Digit = { 
                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 
                    'D', 'E', 'F' 
                }; 
            char[] ob = new char[2]; 
            ob[0] = Digit[(ib >>> 4) & 0X0F]; 
            ob[1] = Digit[ib & 0X0F]; 
            String s = new String(ob); 
            return s; 
        } 
        private static String byteArrayToHexString(byte[] bytearray) { 
            String strDigest = ""; 
            for (int i = 0; i < bytearray.length; i++) { 
                strDigest += byteToHexString(bytearray[i]); 
            } 
            return strDigest; 
        } 
        public byte[] getDigestOfBytes(byte[] byteData) { 
            process_input_bytes(byteData); 
            byte[] digest = new byte[20]; 
            for (int i = 0; i < digestInt.length; i++) { 
                intToByteArray(digestInt[i], digest, i * 4); 
            } 
            return digest; 
        } 
        public String getDigestOfString(byte[] byteData) { 
            return byteArrayToHexString(getDigestOfBytes(byteData)); 
        } 
        public static void main(String[] args) { 
            String data = "123456"; 
            System.out.println(data); 
            String digest = new SHA1().getDigestOfString(data.getBytes()); 
            System.out.println(digest);
        } 
    }

    6>最后在页面调用一下就可以了。

    $(document).ready(function(e) {
            var url = location.href;
             $.ajax({
                url:"http://test/WeiXinJsSdkConfiger",
                data:{
                    "url":url
                    }, //以键/值对的形式
                async : true,
                dataType : "jsonp",
                jsonp: "callbackparam",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
                jsonpCallback:"success_jsonpCallback",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
                success : function(data) {
                    wx.config({
                      debug: false,
                      appId: data.appid,
                      timestamp: data.timeStamp,
                      nonceStr: data.noncestr,
                      signature: data.signature,
                      jsApiList: [
                        'onMenuShareTimeline',
                        'onMenuShareAppMessage',
                      ]
                      });
                }
             });
            wx.ready(function(){ 
                var shareData = {
                title: '1111111', // 分享标题
                desc: '111111', // 分享描述
                link: location.hostname+location.pathname,
                imgUrl: '11111'
              };
              wx.onMenuShareAppMessage(shareData);
              wx.onMenuShareTimeline(shareData); 
            });
    });

    获得access_token和jsapi_ticket有必要的可缓存一下,个人建议这样,大概这样可以实现微信分享了,其实这样js-sdk中所有的函数都可以使用了,其实很简单的,又不明白的可以联系qq:980527632; 要源码的留邮箱

    因索要源码人数过多,来不及发送,故附上百度云盘资源:http://pan.baidu.com/s/1sj5JUVF

  • 相关阅读:
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Navicat查询哪些表有指定字段名
  • 原文地址:https://www.cnblogs.com/MorewalkSofar/p/4278123.html
Copyright © 2011-2022 走看看