前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

H5之微信公众号分享 JS-SDK接入与二次分享失效排查

首页2020-05-24 13:21:43Front-End
公众号分享微信JS-SDKH5

活动页做完了,测试提了个 bug:分享到朋友圈之后,标题变成了一串网址,图标是默认的灰色地球。改完签名逻辑,标题图标都正常了,测试又提了个新的:第一个人分享出去是好的,第二个人从群里点进来再转发,标题又变回网址了。

这两个问题背后是同一件事,微信的分享签名和当前页面 URL 是绑死的。这篇把公众号 H5 分享从零接入的完整过程记一遍,JS-SDK 的五个步骤、分享接口的用法、平台对文案和图片的硬性要求,重点是最后那个二次分享失效的坑怎么绕过去。

使用微信的分享功能,需要使用微信 JS-SDK 来完成,而且只能点击微信右上角的 ... 调起分享面板,不能直接由页面行为唤起。本文用的是当时的 js-sdk 最新版。

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。通过使用微信 JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • JS-SDK 接入的五个步骤,以及 config、ready、error 三者的执行关系
  • 所有接口通用的五个回调参数分别在什么时候触发
  • 微信对分享标题、图标、描述、链接的硬性规范和文案红线
  • updateAppMessageShareData 和 updateTimelineShareData 两个接口的用法
  • 分享出去的链接为什么会被微信加上 query,以及它怎么把签名搞坏的
  • hash 路由下二次分享失效的两种解法和各自的代价
  • 一份 React 项目里的完整落地代码

# 一、JSSDK使用步骤

# 1.1 步骤一 绑定域名

登录微信公众平台,进入公众号设置,功能设置,填写「JS接口安全域名」。

这一步是所有后续工作的前提。域名没绑,wx.config 直接就返回 invalid url domain,代码写得再对也没用。填的是域名不带协议和路径,而且需要在域名根目录放一个微信给的校验文件。

# 1.2 步骤二 引入JS文件

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

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问: http://res2.wx.qq.com/open/js/jweixin-1.6.0.js,同样支持 https。

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

实际接入时直接写 https 就行,你的页面本来也必须是 HTTPS,页面里混着引 HTTP 资源会被浏览器直接拦掉。

# 1.3 步骤三 通过config接口注入权限验证配置

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

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: '', // 必填,公众号的唯一标识
  timestamp: 0, // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [] // 必填,需要使用的JS接口列表
});
@前端进阶之旅: 代码已经复制到剪贴板

关于 config 有几条要记住:

  • config 是一个客户端的异步操作
  • 在引入 JS-SDK 后调用,也应该尽可能早地调用
  • 同一个 url 仅需调用一次
  • 对于变化 url 的 SPA 类型的 web app,可在每次 url 变化时进行调用
  • 低于 Android6.2 版本的微信客户端,不支持 pushState 这个 H5 新特性,使用 pushState 来实现 web app 的页面会导致签名失败

appId、timestamp、nonceStr、signature 这四个值全部由后端计算后返回,前端不要自己拼。签名的原始串里包含 jsapi_ticket 和当前页面的完整 URL,jsapi_ticket 有有效期而且有每日调用次数上限,必须在服务端缓存,不能每次请求都去微信那里换一次。

debug: true 在联调期间一定要开着,配置错了它会直接 alert 出具体的错误码,比自己一行行猜快太多。上线前记得关掉,不然用户会被弹窗糊一脸。

# 1.4 步骤四 通过ready接口处理成功验证

wx.ready(function(){
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
@前端进阶之旅: 代码已经复制到剪贴板

由于 config 是一个异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在 ready 函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在 ready 函数中。

注意一个反直觉的点:无论 config 成功或失败,ready 中的内容都会被执行。

所以别把 ready 当成「配置成功」的信号。它只表示配置流程走完了,成功与否得看 error 有没有被触发。想在分享设置失败时降级,判断逻辑要写在 error 里,不能靠 ready 里的接口调用是否报错去推断。

# 1.5 步骤五 通过error接口处理失败验证

wx.error(function(res){
  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
@前端进阶之旅: 代码已经复制到剪贴板

注释里最后半句是重点:对于 SPA 可以在这里更新签名。单页应用路由一变签名就可能失效,error 就是你重新去后端换一次签名再 config 的机会。

# 1.6 通用参数

所有接口通过 wx 对象,也可使用 jWeixin 对象来调用。参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用函数参数:

  • success 接口调用成功时执行的回调函数
  • fail 接口调用失败时执行的回调函数
  • complete 接口调用完成时执行的回调函数,无论成功或失败都会执行
  • cancel 用户点击取消时的回调函数,仅部分有用户取消操作的 api 才会用到
  • trigger 监听 Menu 中的按钮点击时触发的方法,该方法仅支持 Menu 中的相关接口

回调参数的结构是这样:

// 回调参数:

{
    xxx: xxx,
    errMsg: '' // 接口调用成功/失败信息
}
@前端进阶之旅: 代码已经复制到剪贴板

errMsg 是排查问题的第一手信息,格式大致是「接口名:结果」,比如 config:ok、config:invalid signature。埋点或者错误上报的时候把这个字段带上,线上出问题能直接定位。

# 二、微信分享

用户调用微信的分享功能,可以自定义分享的 title 和描述,以及小图标和链接,可以分享到群、好友、朋友圈、QQ、QQ空间等。

# 2.1 分享设计规范

这一组规范不是建议,是硬性要求,不满足会直接导致分享效果异常:

  • 分享标题:14 字以内,建议使用朋友般亲切的口吻
  • 分享图标:尺寸 120*120,大小不超过 10K,不支持 GIF 格式,必须采用 https 协议
  • 分享描述:20 字以内,对标题的简要解读
  • 分享链接:外链页面所在服务器至少能支持每秒 1500 次的访问压力,且每次访问的响应时间在 200ms 以内,必须采用 https 协议
  • 分享行为:页面上无分享按钮,页面上无诱导分享行为,包含但不限于分享后才能看到特定的信息、分享后才能进行下一步流程、分享后可以获得奖励等
  • 分享文案:分享时文案和图片可以正常显示,分享后链接可以访问
  • 分享标题和描述不能出现敏感词汇,否则会导致部分不可预知的问题,比如分享者可以看到分享图标,被分享者看不到图标

敏感词举例:红包、现金、到账等。

图标那条我踩过。设计给的图是 200KB 的 PNG,本地测试一切正常,因为图已经在缓存里了。发到测试群里让别人点,一半人看不到图标。图标是被分享方的客户端现去拉的,超过 10K 或者服务器慢一点,它就直接放弃了。

分享的图标链接和分享链接尽量保持为同一域名下的资源,否则可能会出现分享不成功或分享图标不显示的情况。

由于不能由页面直接唤起微信的分享面板,所以就需要一个弹窗浮层来引导用户去点击 ... 按钮唤起分享面板。注意这个弹窗浮层不能出现诱导分享的内容。

# 2.2 分享或广告文案禁止内容

这一段建议直接转给写文案的同学:

  • 特殊字符:不允许使用特殊字符与符号,例如 :) -。- 这类;不允许使用 emoji 表情
  • 诱导或引导操作:不允许出现诱导或引导用户操作的描述,包含但不限于「请点击查看详情」「赶快戳开看一看」「点一下下面你就知道是什么」「点击下方了解公众号」
  • 微信产品功能词汇:未经微信官方授权,禁止使用以下产品功能词汇及其谐音词汇,包含但不限于「朋友圈」「点赞」「评论」「公众号」「微信」「红包」
  • URL:不允许直接放 URL 链接内容
  • 电话号码:不允许出现电话号码
  • 破折号:不允许出现破折号,它在移动端显示容易产生歧义
  • 空行和空格:不允许使用空行或空格
  • 不规范折行:不允许出现单个词语或文字折行
  • 股票代码:不允许出现公司股票代码
  • 非简体中文文字、方言、小语种:不允许使用非简体中文文字(单字、词语、成语),暂不支持使用方言和小语种作为文案
  • 产品销量数据:不允许使用任何维度的产品销量数据

这份清单是当时整理的,平台的运营规范会更新,正式投放前请以微信当时的官方规范为准。

# 三、分享接口

# 3.1 自定义「分享给朋友」及「分享到QQ」按钮的分享内容

这个接口从 1.4.0 版本开始提供:

wx.ready(function () {   //需在用户可能点击分享按钮前就先调用
  wx.updateAppMessageShareData({
    title: '', // 分享标题
    desc: '', // 分享描述
    link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    imgUrl: '', // 分享图标
    success: function () {
      // 设置成功
    }
  })
});
@前端进阶之旅: 代码已经复制到剪贴板

# 3.2 自定义「分享到朋友圈」及「分享到QQ空间」按钮的分享内容

同样是 1.4.0 版本:

wx.ready(function () {      //需在用户可能点击分享按钮前就先调用
  wx.updateTimelineShareData({
    title: '', // 分享标题
    link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    imgUrl: '', // 分享图标
    success: function () {
      // 设置成功
    }
  })
});
@前端进阶之旅: 代码已经复制到剪贴板

注意 updateTimelineShareData 没有 desc 字段,朋友圈只显示标题和图标。所以标题得能独立成立,不能写成「详情见描述」这种依赖描述的句子。

这两个接口最容易被误解的地方是 success 回调。它表示的是「分享内容设置成功」,不是「用户完成了分享」。老版本 JS-SDK 里那两个带 onMenuShare 前缀的接口曾经能拿到用户确认分享的回调,新接口出于反诱导分享的考虑把这个能力收掉了。所以「分享后送积分」这种玩法,从接口层面就已经做不了了。

fe
  • 一、JSSDK使用步骤
    • 1.1 步骤一 绑定域名
    • 1.2 步骤二 引入JS文件
    • 1.3 步骤三 通过config接口注入权限验证配置
    • 1.4 步骤四 通过ready接口处理成功验证
    • 1.5 步骤五 通过error接口处理失败验证
    • 1.6 通用参数
  • 二、微信分享
    • 2.1 分享设计规范
    • 2.2 分享或广告文案禁止内容
  • 三、分享接口
    • 3.1 自定义「分享给朋友」及「分享到QQ」按钮的分享内容
    • 3.2 自定义「分享到朋友圈」及「分享到QQ空间」按钮的分享内容
  • 四、分享开发调试时注意事项
  • 五、实战
  • 六、这几年变了什么
  • 总结
  • 参考

← 小程序直播总结 live-pusher与live-player接入实践前端调试实战指南 从 Chrome DevTools 到真机与 Node →