js处理微信分享配置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js处理微信分享配置相关的知识,希望对你有一定的参考价值。

参考技术A

整理一下通过h5做微信分享相关配置。

登录微信公众号, 获取AppID , 配置白名单 ,然后 配置JS接口安全域名 。

登录公众号后,左侧菜单栏选择:开发 => 基本配置,直接复制开发者ID(AppID)即可:

注意使用公网IP

左侧菜单栏选择:设置 => 公众号设置:

网页授权主要是获取微信openId使用,如果只是用分享操作,本步可以略过。

网页授权介绍

大致步骤是:

在配置完前面AppId、白名单及安全域名后,开始处理网页授权。
网页授权这一块儿内容主要是后端需要处理的内容较多,前端还是很简单的,仅需要跳入微信链接即可。为什么要走这一步呢因为有些操作,例如微信支付、播放微信录音、获取微信地址、微信卡券、商品、小店等等许多功能必须在微信浏览器汇总打开操作才可以,因此需要跳入微信浏览器及微信链接来处理后续操作。当配置后,链接便只有在微信浏览器中打开才会生效了,不然会提示:

链接如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appId&redirect_uri==$URL&response_type=code&scope=snsapi_base#wechat_redirect

参数分解

可见,上面需要填入的变量有二,一个是前面回去的AppId,另外一个则是url,需要写的是与配置域名所对应域名下的url,并且要进行urlEncode编码处理使用。

在拿到上述完整链接后,通过 window.location.href = $url 进行网页授权即可。在授权成功后,页面会重定向到自己设置的url页面去,然后在该连接上会有code值,取出即可:

将拿到的code值传给后端即可,看具体需求决定是否前端使用openId,如果非必要则不在前端获取保存或者由后端加密后传给前端使用。

大致分为五个步骤:

在步骤 1.3 中已经配置。

在需要调用JS接口的页面引入如下JS文件: https://res.wx.qq.com/open/js/jweixin-1.6.0.js

备注:支持使用 AMD/CMD 标准模块加载方法加载

配置需要如下几个参数:

那这些参数从哪儿来呢?依旧不用担心,依然是交给后端处理,后端返回时间戳、随机串及签名,其他的自己配置即可。

通过后端获取需要进行一个小交互,将此时的链接地址(window.location.href)传给后端即可。

于是就有了上述的除了最后一个以外的所有参数。最后一个 jsApiList 则是写分享接口,如我们想要分享到朋友圈、QQ、腾讯微博这3个,那就写:

可以发现,我们其实多配置了一个 checkJsApi ,这个是一个判断配置,可以判断当前客户端版本是否支持指定JS接口。

签名算法
所有JS接口列表

接下来就可以写分享信息配置了。配置信息一般都是通过 wx.ready 处理的:

例如我们要分享到朋友圈,配置则如下:

注意:不要出现 诱导分享

同样,一般都是通过 wx.error 处理失败相关信息:

其实微信分享(地理位置、扫一扫、卡券等微信各类接口)都是通过上述步骤配置的,可举一反三,在面对不同需求时通过微信开发文档来进行更为复杂的操作。

微信JS SDK配置授权,实现分享接口

微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享、扫一扫、卡券、支付等微信特有的能力。7月份的时候,因为这个分享的证书获取问题深深的栽了一坑,后面看到“config:ok”的时候真的算是石头落地,瞬间感觉世界很美好..

这篇文章是微信开发的很多前置条件,包括了服务端基于JAVA的获取和缓存全局的access_token,获取和缓存全局的jsapi_ticket,以及前端配置授权组件封装,调用分享组件封装。

配置授权思路:首先根据access_token获取jsapi_ticket,在通过获取到的jsapi_ticket以及随机生成的字符串、时间戳,再加上需要授权的页面地址url,进行SHA-1加密,返回加密字符串,最后根据加密串调用微信提供的config接口。

配置JS接口安全域名

公众平台--公众号设置--功能设置--js接口安全域名

技术分享

 

获取、缓存全局的access_token

技术分享
  /**
     * 微信全局票据 ---->>>> access_token
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String getBaseAccessToken() throws ClientProtocolException, IOException{
        
        try {
            String value = redisService.get("WEIXIN_BASE_ACCESS_TOKEN");
            if (!StringUtils.isEmpty(value)) {
                LOGGER.info("Get base access_token from redis is successful.value:{}",value);
                return value;
            }else{
                synchronized (this) {
                    //缓存中没有、或已经失效
                    String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+WX_APPID+"&secret="+ WX_APPSECRET;
                    String rs = apiService.doGet(url);
                    
                    JSONObject obj_content = JSONObject.parseObject(rs);
                    String accessToken = obj_content.getString("access_token");
                    Integer time = Integer.parseInt(obj_content.getString("expires_in").toString());
                    
                    //写缓存
                    redisService.set("WEIXIN_BASE_ACCESS_TOKEN", accessToken, time - 3600);
                    LOGGER.info("Set base access_token to redis is successful.parameters time:{},realtime",time,time-3600);
                    return accessToken;
                }
            }
        } catch (Exception e) {
            LOGGER.error("Get base access_token from redis is error.");
        }
        return null;
    }
技术分享

先从缓存中取key为“WX_BASE_ACCESS_TOKEN” ,如果命中直接返回值,反之通过httpclient发送GET请求调用微信提供的接口获取全局的access_token,同时将取到的值写入缓存。

 

获取、缓存全局的jsapi_ticket

技术分享
  /**
     * jsapi_ticket是公众号用于调用微信JS接口的临时票据
     * @return
     * @throws IOException 
     * @throws ClientProtocolException 
     */
    public String getJsapiTicket() throws ClientProtocolException, IOException{
        try {
            String value = redisService.get("WEIXIN_JS_API_TICKET");
            if (!StringUtils.isEmpty(value)) {
                return value;
            }else{
                synchronized (this) {
                    //缓存中没有、或已经失效
                    //获取全局的access_token,唯一票据
                    String accessToken = getBaseAccessToken();
                    
                    String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ accessToken +"&type=jsapi";
                    
                    String rs = apiService.doGet(url);
                    
                    JSONObject obj_content = JSONObject.parseObject(rs);
                    String jsapi_ticket = obj_content.getString("ticket");
                    Integer time = Integer.parseInt(obj_content.getString("expires_in").toString());
                    
                    //写缓存
                    redisService.set("WEIXIN_JS_API_TICKET", jsapi_ticket, time - 3600);
                    
                    return jsapi_ticket;
                }
            }
        } catch (Exception e) {
            LOGGER.error("Get js_api_ticket from redis is error:{}",e);
        }
        
        return null;
    }
技术分享

由于获取jsapi_ticket微信有100000次限制,所以必须用上缓存。同理获取access_token,我这里为了保险起见缓存失效时间设置为官方提供的时间再减去一个小时。

 

jssdk加密串获取restful

1.Controller

技术分享
  /**
     * 微信分享证书获取
     * @param 
     * @return signature
     * @throws IOException 
     */
    @RequestMapping(value = "/signature", method = RequestMethod.GET)
    public @ResponseBody String createSignature(
                                @RequestParam String url) throws IOException{

        LOGGER.info("RestFul of createSignature parameters url:{}",url);
        
        try {
            String rs = wechatService.createSignature(url);
            LOGGER.info("RestFul of signature is successful.",rs);
            
            return rs;
        } catch (Exception e) {
            LOGGER.error("RestFul of signature is error.",e);
        }
        
        return null;
    }
技术分享

2.Service

技术分享
  /**
     * 根据jsapi_ticket等参数进行SHA1加密
     * @param nonceStr 随机字符串
     * @param timestamp 当前时间戳
     * @param url 当前页面url
     */
    public String createSignature(String url) throws ClientProtocolException, IOException{
        String nonceStr = create_nonce_str();
        String timestamp = create_timestamp();
        
        String signature = "jsapi_ticket="+getJsapiTicket();
               signature += "&noncestr="+nonceStr;
               signature += "&timestamp="+timestamp;
               signature += "&url="+url;
        
       try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(signature.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (Exception e) {
            LOGGER.error("Signature for SHA-1 is error:{}",e);
        }
       
        Map<String, String> map = new HashMap<String, String>();
        map.put("timestamp", timestamp);
        map.put("nonceStr", nonceStr);
        map.put("signature", signature);
        map.put("appid", WX_APPID);
        return JSON.toJSONString(map, true);
    }
技术分享
技术分享
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;
    }
技术分享
WX_APPID为公众号appid,通过[email protected]注解从配置文件获取,这里不细说。

3.生成随机字符串

private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

4.时间格式化

private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

到此为止后台全部完成,其实没有太多的解释,仔细读一遍代码,可读性应该还行!

 

封装获取授权组件,实现分享方法

技术分享
require.config({
    urlArgs: "v=20161116" ,
    baseUrl : "/static",
    paths: {
        jweixin: ‘component/jweixin/jweixin-1.0.0‘,
        share: ‘component/wechat/share‘//微信分享组件
    }
})
技术分享

首先通过调用后台接口获取加密字符串,调用微信提供的wx.config()方法

技术分享
  //jsSDK授权
    $.signature = function(wx,opts,currentUrl,callback){

        $.ajax({
            data: {url: currentUrl},
            type: "GET",
            url: WX_ROOT + "wechat/signature",
            success: function (json) {
                if (json) {
                    var data = JSON.parse(json);
                    
                    wx.config({
                        debug: false,
                        appId: data.appid,
                        timestamp: data.timestamp,
                        nonceStr: data.nonceStr,
                        signature: data.signature,
                        jsApiList: [
                            ‘onMenuShareTimeline‘,
                            ‘onMenuShareAppMessage‘,
                            ‘onMenuShareQQ‘,
                            ‘onMenuShareWeibo‘,
                            ‘onMenuShareQZone‘
                        ]
                    });
                    
                    wechatShare.options.isSignature = true;
                    
                    callback && callback(opts,wx);
                }
            }
        });
    }
技术分享

建议:开发环境建议开启调式模式,方便打印日志定位问题debug: true   

所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,我这里用一个全局变量isSignature缓存了是否已经配置授权,然后执行回调。如实现分享接口:

技术分享
  //分享
    $.share = function(opts,wx) {
        var options = {
                currentUrl: window.location.href.split(‘#‘)[0],
                imgUrl: null,
                title: ‘达农保险‘,
                desc: null,
                shareUrl: null
            }
        
        $.extend(true, options, opts || {});
        
        //判断是否已经授权
        if(!wechatShare.options.isSignature){
            $.signature(wx,opts,options.currentUrl,$.share)
        }else{
            wx.ready(function(){
                //分享到朋友圈
                wx.onMenuShareTimeline({
                    title: options.title,
                    link: options.shareUrl,
                    imgUrl: options.imgUrl,
                    success: function () {
                        //分享统计,分享来源 1 朋友圈 2分享给朋友  3分享到QQ  4分享到QQ空间
                        
                    }
                });

                //分享给朋友
                wx.onMenuShareAppMessage({
                    title: options.title,
                    desc: options.desc,
                    link: options.shareUrl,
                    imgUrl: options.imgUrl
                });
            });
        }
        
    }
技术分享

我先确认是否已经配置授权,如果没有授权则调用$.signature()回调函数里传入$.share,有点类似递归调用,当再次回到share方法的时候isSignature已经是true了,则执行wx.ready()方法,再调需要调用的接口,微信开放提供了很多接口给我们,分享只是其中一个。只有想不到的,没有实现不了的.... 

注意:currentUrl 必须是动态获取的,通过window.location.href方法,因为页面分享,微信客户端会在你的链接末尾加入其它参数,所以需要再将url用‘#’割一下,取第一个,如果有中文最好是用encodeURIComponent转义一下,保证签名获取成功。如果报invalid signature,大部分原因是传入的url,和加密算法的问题,仔细检查!

调用:

技术分享
var ua = navigator.userAgent.toLowerCase(),
    isWechat = ua.indexOf(‘micromessenger‘) != -1;//判断是否为微信浏览器
var shareData = {
    title: ‘测试分享’,
    desc: ‘这里是描述,分享到朋友圈不会显示’,
    link: APP_ROOT + ‘/base/downloadApp,//分享后打开的链接,必须在配置的安全域名下
    imgUrl: PIC_PATH + (self.data.shareListData[0].imgSmall || ‘/static/img/coupon/getTicPic.png‘),//分享后显示的图片
    success: function(){
                      setTimeout(function(){
              //运营数据统计
             },0)//伪异步方式调用 }
        }
//微信浏览器分享加载
if(isWechat){
 require([‘jweixin‘],function(wx){
    require([‘share‘],function(){
$.share(shareData,wx);
    })
  })
}   
技术分享
















以上是关于js处理微信分享配置的主要内容,如果未能解决你的问题,请参考以下文章

微信JS SDK配置授权,实现分享接口

微信分享配置(js-sdk)

Vue项目配置微信分享

微信公众号开发--微信JS-SDK分享到朋友圈和分享给朋友

微信公众号开发--微信JS-SDK分享到朋友圈和分享给朋友

实战模拟│微信 JSSDK 实现自定义分享手机选图拍照图片音频处理地理位置摇一摇等功能