H5卡片分享

一、常规通用分享配置(Open Graph 协议)

适用于大多数社交平台(微信、QQ、微博、Facebook等)的基础分享信息识别,通过 <meta> 标签定义分享标题、链接、图片和描述。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 通用 Open Graph 标签 -->
<meta property="og:type" content="website" />
<meta property="og:title" content="分享标题" />
<meta property="og:url" content="https://www.example.com/" />
<meta property="og:image" content="https://www.example.com/share.jpg" />
<meta property="og:description" content="分享描述内容" />
<meta property="og:site_name" content="网站名称" />

<!-- 补充:Twitter Card(可选) -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="分享标题" />
<meta name="twitter:description" content="分享描述" />
<meta name="twitter:image" content="https://www.example.com/share.jpg" />

注意

  • 图片链接需为有效 HTTPS 地址,避免解析失败(如示例中的 http://example.com/image.jpg 需替换为真实可访问图片);
  • 图片尺寸建议:微信推荐 300x300 像素,QQ 推荐 200x200 像素以上。

二、微信分享转发配置

1. 前置准备

  • 微信公众平台配置:登录 微信公众平台,在“开发 - 开发管理 - 开发设置”中配置 JS接口安全域名(需与分享页面域名一致);
  • 引入微信 JS-SDK:
    1
    2
    <!-- 建议使用最新版 SDK,示例为 1.6.0(兼容旧版 API) -->
    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

2. 服务端鉴权流程(核心)

前端需通过服务端获取鉴权信息(appIdtimestampnonceStrsignature),步骤如下:

步骤1:获取 access_token

服务端调用微信接口:

1
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
  • 返回示例:{"access_token":"ACCESS_TOKEN","expires_in":7200}
  • 注意:access_token 有效期 2 小时,需服务端缓存(避免频繁调用)。

步骤2:获取 jsapi_ticket

access_token 调用微信接口:

1
GET https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
  • 返回示例:{"errcode":0,"errmsg":"ok","ticket":"TICKET","expires_in":7200}
  • 注意:jsapi_ticket 有效期 2 小时,需服务端缓存。

步骤3:生成签名

服务端按以下规则生成签名:

  1. 生成随机字符串 noncestr 和时间戳 timestamp
  2. 获取当前页面 URL(不含 # 及后面部分,需动态获取);
  3. jsapi_ticketnoncestrtimestampurl 按字典序排序,拼接成字符串;
  4. 对拼接后的字符串进行 sha1 加密,得到 signature

Node.js 服务端示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
const crypto = require('crypto');
const request = require('request'); // 需安装 request 库

// 缓存 access_token 和 jsapi_ticket
let cache = {
accessToken: '',
jsapiTicket: '',
expireTime: 0
};

// 获取 access_token
async function getAccessToken() {
if (Date.now() < cache.expireTime) {
return cache.accessToken;
}
return new Promise((resolve, reject) => {
request.get({
url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=YOUR_APPID&secret=YOUR_APPSECRET`
}, (err, res, body) => {
if (err) return reject(err);
const data = JSON.parse(body);
cache.accessToken = data.access_token;
cache.expireTime = Date.now() + (data.expires_in - 60) * 1000; // 提前1分钟刷新
resolve(data.access_token);
});
});
}

// 获取 jsapi_ticket
async function getJsapiTicket() {
const accessToken = await getAccessToken();
return new Promise((resolve, reject) => {
request.get({
url: `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`
}, (err, res, body) => {
if (err) return reject(err);
const data = JSON.parse(body);
cache.jsapiTicket = data.ticket;
resolve(data.ticket);
});
});
}

// 生成签名
async function generateSignature(url) {
const jsapiTicket = await getJsapiTicket();
const noncestr = Math.random().toString(36).substr(2, 15);
const timestamp = Math.floor(Date.now() / 1000);

// 按字典序排序并拼接
const string = `jsapi_ticket=${jsapiTicket}&noncestr=${noncestr}&timestamp=${timestamp}&url=${url}`;
// sha1 加密
const signature = crypto.createHash('sha1').update(string).digest('hex');

return {
appId: 'YOUR_APPID',
timestamp,
nonceStr: noncestr,
signature
};
}

// 服务端接口示例(Express)
app.post('/getWxMpJsConfig', async (req, res) => {
const { url } = req.body;
try {
const config = await generateSignature(url);
res.json({ code: 1, result: config });
} catch (err) {
res.json({ code: 0, message: '获取鉴权信息失败' });
}
});

3. 前端配置与分享设置

(1)新版推荐 API(微信 JS-SDK 1.4.0+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
function initWxShare() {
const shareConfig = {
title: '分享标题',
desc: '分享描述',
link: location.href.split('#')[0], // 分享链接(需与 JS 安全域名一致)
imgUrl: 'https://www.example.com/share.jpg' // 分享图片
};

// 请求服务端鉴权
const xhr = new XMLHttpRequest();
xhr.onload = () => {
const r = JSON.parse(xhr.responseText);
if (r.code !== 1) return;

const { appId, timestamp, nonceStr, signature } = r.result;

wx.config({
appId,
timestamp,
nonceStr,
signature,
debug: false, // 调试时设为 true,会弹出配置结果
jsApiList: [
'checkJsApi',
'updateAppMessageShareData', // 分享给好友
'updateTimelineShareData' // 分享到朋友圈
]
});

wx.ready(() => {
// 分享给好友
wx.updateAppMessageShareData({
...shareConfig,
success: () => console.log('分享好友设置成功')
});

// 分享到朋友圈
wx.updateTimelineShareData({
title: shareConfig.title, // 朋友圈仅显示标题
link: shareConfig.link,
imgUrl: shareConfig.imgUrl,
success: () => console.log('分享朋友圈设置成功')
});
});

wx.error((err) => {
console.error('微信配置失败:', err);
});
};

xhr.open('POST', '/getWxMpJsConfig');
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
xhr.send(JSON.stringify({
url: location.href.split('#')[0]
}));
}

// 页面加载完成后初始化
window.addEventListener('load', initWxShare);

(2)旧版兼容 API(仍可使用,推荐优先用新版)

若需兼容旧版 SDK,可保留以下 API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
wx.ready(() => {
// 分享到朋友圈
wx.onMenuShareTimeline({
title: shareConfig.title,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl,
success: () => alert('分享成功!'),
cancel: () => alert('分享取消')
});

// 分享给好友
wx.onMenuShareAppMessage({
...shareConfig,
type: 'link', // 分享类型:music、video、link
dataUrl: '', // 若 type 为 music/video,需提供数据链接
success: () => alert('分享成功!'),
cancel: () => alert('分享取消')
});

// 分享到 QQ
wx.onMenuShareQQ(shareConfig);
// 分享到 QQ 空间
wx.onMenuShareQZone(shareConfig);
});

三、钉钉分享配置

1. 前置准备

  • 登录 钉钉开放平台,创建应用并配置 JSAPI 安全域名
  • 引入钉钉 JS-SDK:
    1
    <script src="https://g.alicdn.com/dingding/h5-dingtalk-sdk/1.0.0/dd.js"></script>

2. 前端配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function initDingTalkShare() {
const shareConfig = {
title: '分享标题',
content: '分享描述',
url: location.href,
image: 'https://www.example.com/share.jpg'
};

dd.ready(() => {
// 分享到钉钉好友
dd.biz.navigation.share({
type: 0, // 0:分享到好友,1:分享到朋友圈
title: shareConfig.title,
content: shareConfig.content,
url: shareConfig.url,
image: shareConfig.image,
onSuccess: () => console.log('分享成功'),
onFail: (err) => console.error('分享失败:', err)
});
});

dd.error((err) => {
console.error('钉钉配置失败:', err);
});
}

四、QQ 分享配置

1. 方式一:Meta 标签(简单,无需 JS)

1
2
3
4
<!-- QQ 分享专用标签 -->
<meta itemprop="name" content="分享标题" />
<meta itemprop="description" content="分享描述" />
<meta itemprop="image" content="https://www.example.com/share.jpg" />

2. 方式二:QQ JS-SDK(需申请应用)

  • 登录 QQ 互联开放平台,创建应用并获取 appId
  • 引入 QQ JS-SDK 并配置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <script src="https://qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js"></script>
    <script>
    function initQQShare() {
    setShareInfo({
    title: '分享标题',
    summary: '分享描述',
    url: location.href,
    pic: 'https://www.example.com/share.jpg'
    });
    }
    </script>

五、注意事项

  1. 域名配置:所有平台均需在对应开放平台配置 JS 接口安全域名,否则分享功能无法使用;
  2. 图片要求
    • 图片需为 HTTPS 地址,大小不超过 300KB;
    • 尺寸建议:正方形(300x300 像素),避免被平台裁剪;
  3. URL 处理:分享链接需与页面域名一致,单页应用需动态获取当前 URL(不含 # 后内容);
  4. 调试技巧:微信分享可在 wx.config 中设置 debug: true,通过弹窗查看配置结果;
  5. 服务端缓存access_tokenjsapi_ticket 需服务端缓存(有效期 2 小时),避免频繁调用微信接口导致限流。

参考资料


H5卡片分享
https://cszy.top/20220429-H5卡片分享/
作者
csorz
发布于
2022年4月29日
许可协议