这是微信公众号专属权利, 如果没有微信开发接口的话正常的分享只能使用默认的分型信息
需求描述
在开发移动端的页面时,有分享到微信朋友圈的需求。比如:
但是如果没有额外设置的话,微信默认分享的样式只是默认获取网页的标题,而且不会自动获取图片,像这样:
首先,这就过不了产品这一关, 其次呢, 没有其次。所以我们下一个需求就是,让分享到朋友圈或者微信朋友的页面可以自定义标题, 图片和描述信息。
食材准备
查了一下微信的文档, 我们找到这么一条自定义“分享给朋友”及“分享到QQ”按钮的分享内容(1.4.0), 是目前版本的微信所支持的, 所以按照这个思路做下去应该就可以实现了。
按照文档的说明, 这个接口是微信的JS-SDK
实现的, 而要接入这个 SDK 呢需要做如下工作:
文档: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#0
- 绑定域名
- 引入js文件
- 通过
config
接口注入权限验证设置 - 在
reeady
接口中调用需要自动调用的 SDK 接口(因为 config 验证通过后会执行 ready,自动的借口只有在这里才能保证顺序正确) - 在
error
借口中处理失败情况
大概是以上几个流程,其中第三步验证是异步的, 所以自动的方法需要用第四步来执行以保证顺序,当让如果是用户触发的操作的话就不需要(因为这个时候cofing接口已经验证完成)。有一丢丢类似于 ajax 。
其中第三步是最关关键的一环。 需要配置信息如下:
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
然后微信扔下一句话:
跑掉了。
稍微查了一遍文档,发现其中这个签名,是需要access_token
来生成的, access_token
又是通过 appid
和 secret
来获取的。 那既如此, 只能通过后台来完成了, 不然把这个全部暴露在前端, 可就想前阵子闹的挺欢的某考试信息网了。
这样子事情明朗了:
- 绑定好域名
- 后端写一个接口, 返回计算好的接口,部署在第一步的域名下面
- 前端按照上面步骤接入, 从后端请求签名信息
- 位置自定义分享页面的内容。
监听分享事件,自动跳到朋友圈页面(划掉)让用户自己点击右上角分享, 此时发现分享的链接会按照定要好的内容走起来 (这一点需要留意, 微信为了“不要有诱导分享等违规行为”,现在这样子, 不能在网页内弄一个分享按钮直接跳转)
上菜
这个问题难道我是第一个遇到的么? 不可能!
本着绝不重复造轮子的原则,我在某hub上疯狂搜索,发现果不其然已经有人做了相当不错的东西,只需要拿过来用就是了:
- imokya/wechat-share : 基本包括了上面步骤中前端的工作, 这样一来只需要在后端写好借口就可以了, 而且接口设计特别简洁, 只需要提供接口地址就可以了, 美中不足的是后台借口的返回内容和实现方法没有给介绍, 所以一开始看的时候有点懵。
- backToNature/m-share: (非必选), 页面渲染部分, 可以省去许多画UI的工作,同时适配了几个浏览器的native分享。 事实上这个项目可以包含上面项目的内容, 不过对微信的借口设计没有那么简洁,两个配合使用更佳。
然后就是后端的问题,需要实现一个计算好签名的接口。 实现的算法在微信文档中国有介绍,基本上就是拿个时间戳,随机数怎么的组一组,然后加个密返回。 我们依旧首先不造轮子, 找一找其他人的实现:
- Python: https://github.com/penpenps/wechat-python-jssdk/blob/master/wechat_sign.py
- Go: https://github.com/henson/wxtoken
- PHP: https://github.com/lin1061/php-wechat
- Java: https://github.com/sooglejay/wx_signature
- (弃用)
合辑: https://github.com/arronf2e/jssdk_simple
这样一来, 我们只需把轮子组装起来,用简单几行代码就可以实现微信的自定义分享内容了, 前端代码大概长这样子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>分享测试</title>
</head>
<body>
<div id="share-wrapper"></div>
</body>
<script src="m-share.min.js"></script>
<script src="wechat.share.js"></script>
<script>
const sharedata = {
link: location.href, //分享链接
title: '这是自定义分享的标题', //分享title
desc: '这是分享的内容balababalabalaaaaaaaaaaaaaaaaa', //分享文案
imgUrl: 'https://oldzengblog.oss-cn-beijing.aliyuncs.com/16274628_1568551424059.jpg',
}
const config = {
apiURL: 'https://example.com/myapi', // 分享接口服务器地址, 返回jssdk签名, 与微信公众号配置中的域名一致
wxURL: '//res2.wx.qq.com/open/js/jweixin-1.4.0.js', //JSAPI地址
debug: false, //调试模式
type: 'post', //请求类型
jsonp: true, //jsonp跨域
data: sharedata
}
new WechatShare(config)
if(isWeixinBrowser) // 如果是微信浏览器只显示分享到微信的按钮(可忽略这一段)
sharedata.types = ['wx', 'wxline']
Mshare.render('#share-wrapper', sharedata);
function isWeixinBrowser() {
navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == "micromessenger"
}
</script>
</html>
端实现-泪的教训
关于后端的的实现, 重新部署过一次, 然而又踩了一次坑, 有些事情必须要说清楚:
-
apiURL
所域名, 必须与公众号后台微信公众平台-开发-基本配置-JS安全域名一致
,比如api写https://www.x.com/xxx
, 而安全域名填x.com
就是不行的, 应该填www.x.com
-
必须将后端借口所部署的服务器的IP地址加入到
微信公众平台-开发-基本配置-IP白名单中
, 否则无法调用成功, 拿不到 access_token -
后端实现的接口应该是返回类似下面这样的结构.
{ "appId": "wxxxxxxxxxxx", "timestamp": 1586626880, "nonceStr": "xxxxxxxxx", "signature": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "url": "https:\/\/example.com\/xxx.htm" }
-
(接3) 但是!!! PHP 有可能会很鬼畜!!! 它可能需要返回这样的格式:
CallbackFunction({....})
里面才是真正的json , 而如果直接返回JSON的话会报语法错误: Uncaught SyntaxError: Unexpected token ':'. 这个CallbackFunction应该是请求Url中的callback
参数的值, 如果没有这个参数, 它可能要直接返回json吧. 参考链接
最终实现效果:
👇