微信jssdk报错

安卓机可以正常签名,IOS会遇到invalid signature。类似这样:

签名无效,一般出现这种情况是由于计算签名的URL地址不对。

微信要求:如果我们需要在页面中调用微信的某个方法,则必须用这个页面的URL地址获取签名。听上去似乎很好理解,但是实际上URL地址包含的部分很多,有问号,有#号,你所要做的是取出#前面的部分。比如说你的URL地址是这样:https://www.abc.com/abc.html?abc=def#xyz,那么你用于计算签名的URL地址不可以是https://www.abc.com/abc.html,也不能是https://www.abc.com/abc.html?abc=def#xyz,而必须只能是https://www.abc.com/abc.html?abc=def

如何获取当前页面的URL地址呢?这个很简单:

let wechaturl = window.location.href.split('#')[0];

然而你以为事情就这样结束了?太天真。你的页面还是无法正常使用微信函数的。

因为:微信内嵌浏览器在iOS和安卓下的表现不一样。

在安卓下,你确实用上面的方法是可以调用了。但是在iOS下,签名依然失败!因为在iOS下,微信需要你传递的是入口URL,而不是当前页面的URL!

比如说,你在微信公众号的某个菜单链接进入了A页面,然后从A页面的某个链接跳转到B页面,然后你在B页面获取签名,如果是在安卓下,你应该用B页面的URL地址来获取,但是在iOS下,你还必须用A页面的URL地址来获取,否则就还是签名失败!

知道了原因,就有很多种解决办法。

首先,我们可以在入口的A页面里增加这样的判断:

if (navigator.userAgent.indexOf('iPhone') !== -1) {
  window.wechaturl = window.location + '';
}

然后,在B页面需要调用签名的地方,再增加这样的判断:

扫描二维码关注公众号,回复: 14982257 查看本文章
let wechaturl = window.location.href.split('#')[0];
if (window.wechaturl !== undefined) {
 wechaturl = window.wechaturl;
}

这样我们就有效地区分开了iOS和安卓。但问题是在iOS下,如果我的另外一个菜单入口是B页面,我从B页面跳转到A页面,这时候我的入口链接被强制变成了A页面,依然会产生签名失败的错误。

所以我们还需要在微信公众号的每一个入口菜单链接里加一个特殊的参数,例如wechat=1,变成这样:https://www.abc.com/abc.html?abc=def&wechat=1

然后我们再增加一层判断,变成这样:

if (navigator.userAgent.indexOf('iPhone') !== -1) {
 if (this.$route.query.wechat !== undefined && this.$route.query.wechat === '1') {
  window.wechaturl = window.location + '';
 }
}

这里我用了vue的写法,但原理是一样的。只有我检测到了wechat这个参数,我才认为当前页面是入口页面,如果没有检测到,则不必强行设置为入口页面。

这样似乎就解决了微信签名失败的问题。

但是,我们又遇到了另外一种情况:在微信小程序里用web-view内嵌的网页,在安卓下也报permission denied和invalid signature错误。不过有了上面的经验,我们诊断错误根源还是URL入口地址的问题。果然,在安卓下用入口地址获取签名成功,而用当前地址获取签名失败,为此,我们在入口页面里再加一个判断:

if (navigator.userAgent.indexOf('miniProgram') !== -1) {
 window.wechaturl = window.location + '';
}

签名错误的问题解决。

下面给大家提供一个封装的demo:

在util建立wxJsSdk.js文件

import request from "./request.js";
import Vue from 'vue'
let appConfig = uni.getStorageSync('appConfig')
var wxjssdk = (_wx,api) => {
    return new Promise(rr => {
        getApp().globalData.initAppPro.then(() => {
            let wechaturl = window.location.href.split('#')[0];
            if (window.wechaturl !== undefined) {
             wechaturl = window.wechaturl;
            }
           request.request(api.user.getWxJsapiSignature, {
                url: encodeURIComponent(wechaturl)
            }, 'get').then(res => {
                let configData = res.data;
                let configObj = {
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    // debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: configData.appId, // 必填,公众号的唯一标识
                    timestamp: configData.timestamp, // 必填,生成签名的时间戳
                    nonceStr: configData.nonceStr, // 必填,生成签名的随机串
                    signature: configData.signature, // 必填,签名
                    jsApiList: ['updateAppMessageShareData', 'getNetworkType',
                        'updateTimelineShareData', 'getLocation'
                    ],
                    openTagList: ['wx-open-launch-weapp']
                }
                _wx.config(configObj);
                _wx.ready(function(res) {
                    console.log('wx-jssdk-ready',res)
                    rr(true)
                    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
                });
                _wx.error(function(err) {
                    console.log('wx-jssdk-error', err)
                    rr(false)
                    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
                });
            })
        })
    })
}
export default wxjssdk;

使用示例:

import wxjssdk from "@/util/wxJsSdk.js";

wxjssdk(this.$wx,this.$api).then(() => {
    console.log('签名成功');
 })

this.$wx,this.$api 根据你的项目,可传可不传。

猜你喜欢

转载自blog.csdn.net/qq_35713752/article/details/129368067