C# 微信网页分享链接 前后端代码,config:invalid signature错误的解决方法

本文是微信公众号开发-H5网页分享功能的前、后端整个流程,以及遇到的invalid signature问题的解答,希望对该功能开发不是很清楚的朋友有所帮助。

一、准备工作。

百度下“微信 公众平台 开发 文档”进入官方接口文档(这里有朋友要问了,为什么搜索的时候要在词与词之间加空格,这是个小技巧,这样搜索的结果更加准确):文档1.1至3.7的篇幅清晰的介绍了如何设置JS安全域名、网站如何导入开放的js接口文件、如何签名验证和以及分享的多种类型。大家还是要仔细的阅读下。

1、绑定安全域名:因为调用微信H5网页分享功能需要调用微信开放的JS接口,并且网站的域名要绑定到微信公众平台“JS接口安全域名”下,才能正常调用微信开放的JS接口。比如网站是http://my.csdn.com/index.html,那么JS接口安全域名就是my.csdn.com。域名绑定失败或者域名不存在会报错误:invalid url domain。

2、引入微信js文件:在需要调用JS接口的页面引入JS文件,用script标签引入即可,可以直接引用官方提供的JS链接,也可以把JS文件下载到本地引用。

 

3、通过config接口注入权限验证配置:

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用JS-SDK接口。wx.config调用方法如下:

config接口调用完后就可调用ready接口和error接口,这2个接口是代表config是否验证成功的。分享的功能可以封装到一个方法中,然后在ready接口中进行调用。下面直接放代码。

二、前端代码

<script src="js/jquery-3.2.1.js"></script>
<script src="js/jweixin-1.4.0.js"></script>
<script src="js/getRequestParam.js"></script>

<script type="text/javascript">
    var nonceStr = ''; //后台返回-生成签名的随机串
    var timestamp = '';//后台返回-生成签名的时间戳
    var signature = '';//后台返回-签名
    var CurrentPageUrl = '';//前台获取传递给后台(后台签名时用到)-当前页面地址,包括url后面接的参数,如果是微信静默授权进来的,该地址会包含微信Code等信息

    //微信公众平台APPID
    var WX_APPID = "wx8xxxcb598xx5930f";
    //后台接口地址
    var Api_ROOT = "http://localhost:61101/";
    //页面逻辑控制类
    var center = {
        //网页分享方法
        WxShare: function (s_timestamp, s_nonceStr, s_signature, s_title, s_des, s_imgUrl, CurrentPageUrl) {
            wx.config({
                debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: WX_APPID, // 必填,公众号的唯一标识
                timestamp: s_timestamp, // 必填,生成签名的时间戳【后台返回】
                nonceStr: s_nonceStr, // 必填,生成签名的随机串【后台返回】
                signature: s_signature,// 必填,签名【后台返回】
                jsApiList: [
                    'checkJsApi', //判断当前客户端版本是否支持指定JS接口
                    'onMenuShareTimeline', //分享给好友
                    'onMenuShareAppMessage', //分享到朋友圈
                    'onMenuShareQQ', //分享到QQ
                    'onMenuShareWeibo',//分享到微博<br/>
                    'onMenuShareQZone'
                ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
            });

            //通过ready接口处理成功验证
            wx.ready(function () {
                //alert("wx.ready:" + timestamp);
                // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
                wxready();
            });
            //通过error接口处理失败验证
            wx.error(function (res) {
                // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
                alert("res错误信息:" + res.errMsg);
            });
            function wxready() {
                // 判断当前版本是否支持指定 JS 接口,支持批量判断
                wx.checkJsApi({
                    jsApiList: [
                        'checkJsApi', //判断当前客户端版本是否支持指定JS接口
                        'onMenuShareTimeline', //分享给好友
                        'onMenuShareAppMessage', //分享到朋友圈
                        'onMenuShareQQ', //分享到QQ
                        'onMenuShareWeibo',//分享到微博<br/>
                        'onMenuShareQZone'//分享到QQ空间
                    ],
                    success: function (res) {
                        alert("ok");
                    }
                });
                debugger;
                var url = CurrentPageUrl;///分享链接,该链接域名在对应的公众号JS安全域名列表中配置过才行
                var title = s_title;
                var desc = s_des;
                var imgUrl = s_imgUrl;

                //分享到朋友圈
                wx.onMenuShareTimeline({
                    title: title, // 分享标题
                    desc: desc, // 分享描述
                    link: url, // 分享链接
                    imgUrl: imgUrl, // 分享图标
                    success: function () {
                        //分享成功之后执行的回调函数
                        alert("已分享");
                    },
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                        alert("已取消分享");
                    }
                });
                //分享给朋友
                wx.onMenuShareAppMessage({
                    title: title, // 分享标题
                    desc: desc, // 分享描述
                    link: url, // 分享链接
                    imgUrl: imgUrl, // 分享图标
                    type: '', // 分享类型,music、video或link,不填默认为link
                    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                    success: function () {
                        // 用户确认分享后执行的回调函数
                        alert("已分享");
                    },
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                        alert("已取消分享");
                    }
                });
                //分享到QQ
                wx.onMenuShareQQ({
                    title: title, // 分享标题
                    desc: desc, // 分享描述
                    link: url, // 分享链接
                    imgUrl: imgUrl, // 分享图标
                    success: function () {
                        // 用户确认分享后执行的回调函数
                        alert("已分享");
                    },
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                        alert("已取消分享");
                    }
                });
                //分享到腾讯微博
                wx.onMenuShareWeibo({
                    title: title, // 分享标题
                    desc: desc, // 分享描述
                    link: url, // 分享链接
                    imgUrl: imgUrl, // 分享图标
                    success: function () {
                        // 用户确认分享后执行的回调函数
                        alert("已分享");
                    },
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                        alert("已取消分享");
                    }
                });
                //分享到QQ空间
                wx.onMenuShareQZone({
                    title: title, // 分享标题
                    desc: desc, // 分享描述
                    link: url, // 分享链接

                    imgUrl: imgUrl, // 分享图标
                    success: function () {
                        // 用户确认分享后执行的回调函数
                        alert("已分享");
                    },
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                        alert("已取消分享");
                    }
                });
            }
        },
        //调用后台接口返回数据方法
        GetActivityInfo: function (aid, PageUrl) {
            $.ajax({
                url: Api_ROOT + '/Activity/GetActivitysInfo',
                datatype: "JSON",
                data: { "ActivitysId": aid, "h5PageUrl": PageUrl },
                async: false,
                type: 'post',
                success: function (data) {
                    nonceStr = data.Data.ShareModelInfo.nonceStr;//后台返回-生成签名的随机串
                    timestamp = data.Data.ShareModelInfo.timestamp;//后台返回-生成签名的时间戳
                    signature = data.Data.ShareModelInfo.signature;//后台返回-签名
                    center.WxShare(timestamp, nonceStr, signature, data.Data.ActivityInfo.AcTitle, data.Data.ActivityInfo.AcInfo, data.Data.ActivityInfo.AdUrl, PageUrl);
                }
            })
        },
    }

    //页面函数入口
    $(function () {
        //活动ID
        var ActivitysId = request('Aid');

        //当前页面地址,包括url后面接的参数,如果是微信静默授权进来的,该地址会包含微信Code等信息
        CurrentPageUrl = location.href.split('#')[0];

        //通过活动ID调用接口返回活动详情信息
        center.GetActivityInfo(ActivitysId, CurrentPageUrl);
    });
</script>

三、后台代码

 

四、关于“invalid signature”签名验证失败需要注意的点。

一般出现这个错误多半是后台签名获取有问题,主要原因有以下几点:

1、APPID和APPSECRET填错

这个错误可以到官方的调试页面获取access_token看看是否是正确,点击获取获取access_token

根据返回的结果可以判断页面内的APPID和APPSECRET有没有出错,没有出错的话可以点击获取jsapi_ticket

利用前面拿到的access_token 采用http GET方式请求获得jsapi_ticket,如果出错的话会返回对应的说明。

点击进行确认签名算法校验

点击查看全局返回码说明

2、超过了每日的access_token获取上限

官方限定每日2000次请求,所以如果没有缓存access_token的话,还是比较容易过限的。

3、确认config中nonceStr

H5页面中的wx.config方法里nonceStr参数中的S是大写的。

4、确认url是页面完整的url

请在当前页面alert(location.href.split('#')[0])确认,包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

 

大部分的人最主要的问题还是在第4点,后台用url做签名时不要自己定义url,最好是前端每次请求接口时把url通过location.href.split('#')[0] 获取后传进来,注意后台接收这个参数数打印以下跟前端的location.href.split('#')[0] 进行对比,看是否一致,不一致可能需要用encodeURIComponent 进行编码后再传给后台。


版权声明:本文为ananlele_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。