微信JS-SDK1.6.0自定义分享的实现

1,545 阅读6分钟

前言

在使用uni-app打包出的H5页面中,通过微信JS-SDK,调用微信的分享功能。

微信JS-SDK使用

一、绑定域名

公众号:登陆微信公众平台 --> 公众号设置 --> 功能设置 --> 填写“JS接口安全域名”;

这里不是必须使用公众号,绑定小程序的也可以,使用小程序中配置的安全域名。

二、优化JS-SDK

从官网下载JS-SDK1.6.0,在源码内修改部分内容:

源码

 !(function(e, n) { 
     typeof define === 'function' && (define.amd || define.cmd) ? define(function() { return n(e) }) : n(e, !0) 
 }

修改为:

!(function (e, n) { 
    module.exports = n(e)
}

三、代码引入JS-SDK

在需要分享的页面引入:

import wx from '../../static/jweixin-module/jweixin-1.6.0';

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

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。

本项目流程是将需要验证的signLink发送给后台,后台进行签名操作,然后将签名信息返回给前端,前端根据返回信息通过config接口注入权限验证配置。

五、通过ready接口处理成功验证

ready函数中执行调用的微信API。

代码如下:

// 将需要验证的signLink发送给后台
uni.request({
    // 后台接口地址
    url: 'https://***.***.com/getSignature/api/creatSignature',	
    method: 'POST',
    data: {
        // 这里进行编码是为了发送途中不被截取,后台会进行解码
        url: encodeURIComponent(signLink)
    },
    success: res => {
        // 通过config接口注入权限验证配置
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来。
            appId: '', // 必填,公众号的唯一标识,也可以使用小程序的唯一标识
            signature: res.data.signature, // 必填,生成签名的时间戳
            timestamp: res.data.timestamp.toString(), // 必填,生成签名的随机串
            nonceStr: res.data.noncestr,	// 必填,签名
            jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] // 必填,需要使用的JS接口列表
        });

        wx.ready(function() {
            // 需在用户可能点击分享按钮前就先调用
            wx.checkJsApi({
                jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'], // 需要检测的JS接口列表
                success: function(res) {
                    // 以键值对的形式返回,可用的api值true,不可用为false
                    // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
                }
            });

            const shareLink = "shareLink";
            const desc = '分享信息简介';
            wx.updateAppMessageShareData({
                title: '分享标题', // 分享标题
                desc: desc, // 分享描述
                link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: 'https://***.***.com/shareLog.png', // 分享图标,分享图标的url,以http或https开头
                success: function() {
                    // 用户点击了分享后执行的回调函数
                },
                cancel: function() {}
            });
        });
        wx.error(function(res) {
            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        });
    }
});

错误总结

一、签名错误

当wx.config的debug设为true的话打开页面会显示签名是否成功,若显示 invalid signature,则是签名报错,这时候你就需要去检查你的签名配置。

校验签名算法:

  1. 确认签名算法是否正确,可用 mp.weixin.qq.com/debug/cgi-b… 页面工具进行校验。
  2. 确认config中noncestr, timestamp与用以签名中的对应noncestr, timestamp一致。
  3. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
  4. 确认url是页面完整的url,包括GET参数部分。

页面url错误导致:

在路由模式为history模式时,iOS需要使用第一次进入页面的URL获取签名,安卓每次路由切换都重新配置签名

iOS端

这里先说本项目实现。在项目入口时,将入口url保存下来,

uni.setStorageSync('entryUrl', location.href.split('#')[0]);

再在分享页面时获取:

iOSLocalUrl: function() {
    const entryUrl = uni.getStorageSync('entryUrl');
    if (entryUrl === '') {
        entryUrl = location.href.split('#')[0];
    }
    return entryUrl;
}

将该返回url做为需要验证的signLink,进行签名校验。

这里也可以借助路由钩子,在每次页面跳转时保存。

router.afterEach(() => {
  Promise.resolve()
    .then(() => {
      getSign({
        url: global.location.href.split('#')[0]
      })
    })
})
Andriod端

直接在分享页面获取location.href.split('#')[0]即可。

signLink = location.href.split('#')[0];
原因分析

下图模拟了一个用户进入你的应用(网页)后的一些行为,包括:

  1. 点击链接或按钮跳转到其他页面

  2. 刷新页面

    其中:

    • currentPage表示你正在看的页面
    • langdingPage表示落地页,也就是浏览器认为的页面

Andriod系统对url的识别机制 iOS系统对url的识别机制

如上,Andriod系统更符合我们对url的认知,而iOS系统中的每个页面的url都是刚进入项目的第一页的url,除非是刷新页面;即:在SPA模式下:

  • iOS中,页面A为整个项目的真实url
  • Andriod中,每次路由跳转都会产生新的url

微信js-sdk配置加密所校验的url是落地页url(即:landingPage),所以以下情况若调用微信API需要在当前页面配置:

  • iOS进入项目的第一页
  • iOS页面刷新后
  • Andriod路由跳转或页面刷新后

二、微信分享非安全域名链接导致分享失败

下面代码中的shareLink即分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致,否则将调用失败。

wx.updateAppMessageShareData({
    title: '会议邀请', // 分享标题
    desc: desc, // 分享描述
    link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    imgUrl: 'https://xlite.kedacom.com/conference/2020/shareLog.png', // 分享图标,分享图标的url,以http或https开头
    success: function() {
        // 用户点击了分享后执行的回调函数
    },
    cancel: function() {}
});

网上有分析,例如,当前页面是 www.abc.com/123,其公众号对应的… www.abc.com 以及 www.xyz.com,则分享自定义链接 www.abc.com/456 可以成功,分享 www.xyz.com/123www.def.com/123 均将失败。

但是我在实际开发中,分享的链接即使与JS安全域名一致也无法分享成功,链接必须与分享页面地址一致。

const localUrl = "https://xlite.kedacom.com/conference/pages/share/share?confname=123";
// 分享不成功
const shareUrl = "https://xlite.kedacom.com/conference?confname=123";
// 分享成功
const shareUrl = "https://xlite.kedacom.com/conference/pages/share/share?confname=123";

如果说你分享跳转页面必须是非安全域名下的链接,那你可以单独做一个转发页面,通过转发链接进入这个转发页面后,再直接跳转到拼接好的授权页面。参考代码:非安全链接分享解决办法

三、分享链接参数带中文或者特殊字符

Andriod会自动encodeURIComponent(),而iOS不会。所以会出现Andriod自定义可以正常分享,但是iOS就不行。处理如下:

const shareUrl = 'https://xlite.kedacom.com/conference/pages/share/share?confname=' + encodeURIComponent(this.confname) + '&confno=' + encodeURIComponent(this.confno);

小记

以上只是我在实现微信JS-SDK1.6.0自定义分享中遇到的问题,网上还有很多分享只得参考。

参考文章:

[微信分享填坑指南]

[微信jssdk自定义分享问题总结]


欢迎关注我的公众号,谢谢大家!