微信分享逻辑与流程详细说明
微信分享逻辑与流程详细说明
适用:开发人员、系统管理员
关联:页面标题、SEO 与微信分享操作说明
代码入口:Banyan/Lib/Action/Wap/CommonAction.class.php、static/default/wap/js/wechat-share.js
一、整体流程(从打开页面到分享卡片)
sequenceDiagram
participant User as 用户微信内打开页面
participant PHP as WAP Action + CommonAction
participant Svc as WechatShareService
participant Tpl as 模板 footer_share
participant JS as wechat-share.js
participant API as /wap/api/sharethumb
participant WX as 微信 JS-SDK
User->>PHP: 请求页面
PHP->>PHP: 设置 mobile_title、setWechatShare()
PHP->>PHP: display() → seo() 强制分享标题=页面标题
PHP->>Svc: WechatShareService::build()
Svc-->>Tpl: $wechatShare JSON
Tpl->>JS: window.__WECHAT_SHARE__ + __WECHAT_SIGN__
JS->>JS: normaliseShareConfig() 合并标题/图
JS->>API: imgUrl 经 sharethumb 裁成 300×300
JS->>WX: wx.config + updateAppMessageShareData
User->>WX: 点击右上角「分享给朋友」
WX-->>User: 分享卡片(标题/描述/缩略图/链接)
要点:分享内容在 服务端先配好,前端 再规范化 + 裁图,最后交给 微信 JS-SDK。页面 <title> 与分享标题保持一致(商家/详情页已强制)。
二、服务端:谁决定标题、描述、链接、图片?
2.1 调用链
- 各
*Action在display()前调用:
- setWechatShare($options),或
- applySiteSectionShare() / applyContentDetailShare() / applyShopSectionShare() / initShopWechatShare()(内部仍调 setWechatShare)。
CommonAction::display()→seo():
- 输出 $mobile_title 到模板 <title>;
- 强制 wechatShare.title = mobile_title(与分享标题一致)。
WechatShareService::build()合并后台默认配置与页面传入项,得到$wechatShare。- 模板
themes/default/Wap/public/footer_share.html输出:
- window.__WECHAT_SHARE__(JSON)
- window.__WECHAT_SIGN__(JS-SDK 签名)
2.2 分享标题优先级
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1 | Action 传入 title + forcePageShare=true | 商家页、详情页必须走此路径 |
| 2 | $this->mobile_title | 与页面 <title> 相同 |
| 3 | 后台「微信分享默认标题」 | 仅当开启默认设置且未 forcePageShare |
| 4 | document.title(前端) | 仅当 usePageContent=true 且服务端 title 为空 |
| 5 | 固定文案「分享」 | 极端兜底 |
描述 desc:优先 Action 传入 → 否则与 title 相同 → 否则站点描述。
链接 link:优先 Action 传入(常带 fuid 分销参数)→ 否则当前页完整 URL。
2.3 后台「启用微信分享默认设置」
路径:系统后台 → 微信相关配置。
| 开关状态 | 行为 |
|---|---|
开启 且页面未传 forcePageShare | 标题/描述/图片以后台默认为准,Action 传的 title/desc/imgUrl 可能被忽略 |
开启 但页面传了 forcePageShare=true | 以页面为准(商家、资讯详情等均已使用) |
| 关闭 | 以 Action 传入为准;未传 title 时可能 usePageContent=true 从前端取 |
三、服务端:分享图片如何指定?
3.1 PHP 层 imgUrl 规则(WechatShareService)
Action 构造分享时常见写法:
// 有商家图/文章配图
'imgUrl' => config_weixin_img($detail['photo']),
// 故意不传图,交给前端按页面 DOM 或 wx.jpg 处理
'imgUrl' => '', // 或 initShopWechatShare 中无 photo 时 $shareImg = ''
WechatShareService 在 imgUrl 为空时的兜底(未开强制页面分享时):
- 页面传入的
imgUrl(经config_weixin_img转绝对 URL) - 站点 Logo(
site.logo) {host}/static/default/wap/image/logo.png
商家页 initShopWechatShare:
- 有
shop.photo→ 用作分享图; - 否则
shop.logo; - 都没有 →
imgUrl传空字符串,交给前端继续处理(见下文)。
3.2 为何还要前端再处理一次?
微信要求分享缩略图:
- 建议 300×300 左右、小于 32KB;
- 必须是 公网可访问的绝对 URL。
因此前端 wechat-share.js 会把最终选用的图片 URL 再包一层:
/wap/api/sharethumb?size=300&src={原始图片URL}
由服务端 居中裁剪为正方形 JPEG 并 缓存 7 天(attachs/sharethumb/)。
四、前端:无图、一图、多图分别怎么处理?
文件:static/default/wap/js/wechat-share.js
函数:findFirstPageImage()、normaliseShareConfig()、buildShareThumbUrl()
4.1 最终用哪张图?(决策顺序)
1. serverImg = window.__WECHAT_SHARE__.imgUrl(PHP 输出,已非空)
↓ 若为空
2. pageImg = 页面上第一张「有效」<img> 的 src
↓ 若仍为空
3. 默认图 = /attachs/wx.jpg
↓
4. 全部经 sharethumb 裁成 300×300 后作为 wx 的 imgUrl
对应代码逻辑:
var serverImg = share.imgUrl; // 服务端
var pageImg = findFirstPageImage(); // DOM 扫描
if (!pageImg) pageImg = '/attachs/wx.jpg';
var imgSrc = serverImg || pageImg;
imgUrl = buildShareThumbUrl(imgSrc, 300);
4.2 场景 A:页面没有任何图片
| 步骤 | 行为 |
|---|---|
| PHP | imgUrl 为空或未设置 |
| JS | findFirstPageImage() 找不到有效 src |
| JS | 使用 /attachs/wx.jpg 作为默认分享图 |
| API | sharethumb 将 wx.jpg 裁成 300×300 输出 |
这就是「页面没有图标/配图」时本站采用的方法:统一落到了 attachs/wx.jpg(请确保该文件存在于服务器 attachs 目录)。
4.3 场景 B:页面只有一张内容图
| 步骤 | 行为 |
|---|---|
| PHP | 可不传 imgUrl,或传 config_weixin_img($photo) |
| JS | 若 PHP 未传,则 findFirstPageImage() 取到该 <img> |
| API | 对该图居中裁剪为正方形 |
推荐:详情页(资讯、活动、招标)在 PHP 显式传入文章/活动配图,避免 DOM 顺序干扰。
4.4 场景 C:页面有多张图片(重点)
规则:只取一张,且是 DOM 中出现的第一张有效 <img>。
document.images 按 HTML 文档顺序 遍历,不会:
- 比较图片尺寸大小;
- 跳过「小图标」;
- 让用户选择哪一张。
会被跳过的 <img>:
src为空;src以data:或blob:开头(内联图、本地预览)。
实际影响:
| 情况 | 可能结果 |
|---|---|
| 页头/导航里先出现 logo、箭头图标 | 可能误用图标 作为分享图 |
| 正文大图在列表后面 | 若前面有小图,不会用正文大图 |
| 轮播图多张 | 通常用 轮播 DOM 里排第一 的那张 |
最佳实践(开发):
- 重要页面(商家详情、文章详情、活动详情)必须在 PHP 传
imgUrl,不要依赖 DOM 自动抓取。 - 仅列表页、简单页可依赖「首图」或 wx.jpg。
4.5 场景 D:PHP 已指定 imgUrl,页面上还有其他图
以 PHP 为准。serverImg 非空时 不会 再扫描页面其他 <img>。
示例:商家详情传 shop.photo,即使页面还有轮播、评价头像,分享图仍是 商家封面。
4.6 场景 E:图片 URL 无效或下载失败
sharethumb 接口(ApiAction::sharethumb):
- 尝试读本地
attachs或远程下载; - 失败 → 回退
attachs/wx.jpg; - GD 无法解析 → 再次回退 wx.jpg;
- 裁剪:居中裁切为正方形,输出 JPEG 质量 85。
五、sharethumb 接口说明
URL:/wap/api/sharethumb?size=300&src=/path/to/image.jpg
| 参数 | 说明 |
|---|---|
size | 输出边长,默认 300,最大 800 |
src | 原图路径或完整 http(s) URL |
处理:
- 居中裁剪(cover)→ 正方形 → 缩放到
size×size; - 缓存文件:
attachs/sharethumb/{md5(url+size)}.jpg,7 天有效。
前端最终传给微信的 imgUrl 形如:
https://你的域名/wap/api/sharethumb?size=300&src=https%3A%2F%2F...%2Fattachs%2Fxxx.jpg
六、分享标题在前端的合并规则
title = serverTitle
|| (usePage ? pageTitle : '')
|| pageTitle
|| '分享';
| 字段 | 规则 |
|---|---|
| title | 服务端 title 优先;否则看 usePageContent 是否用 document.title |
| desc | 服务端 desc → 否则 title |
| link | 服务端 link → 否则 location.href(转绝对 URL) |
当前商家/详情页均 usePageContent=false 且服务端必传 title,故分享标题 = mobile_title = <title>。
七、微信 JS-SDK 注册与分享接口
CommonAction::_initialize()生成signPackage(appId、timestamp、nonceStr、signature)。wechat-share.js在 DOM 就绪后:
- wx.config({ jsApiList: [...] })
- wx.ready() 后调用:
- 新接口:updateAppMessageShareData(朋友)、updateTimelineShareData(朋友圈)
- 旧接口兜底:onMenuShareAppMessage、onMenuShareTimeline
前提:公众号后台 JS 安全域名已配置;appid/appsecret 正确。
八、按页面类型的推荐配置
| 页面类型 | title | imgUrl 建议 |
|---|---|---|
| 商家主页 | 商家名称 | shop.photo 或 logo |
| 商家子版块 | 商家名(版块名) | 同上 |
| 资讯/活动/招标详情 | 内容标题 | 文章/活动/招标配图 |
| 全站列表 | 网站名+版块名 | 站点 logo 或留空走 wx.jpg |
| 无图纯文字页 | 页面标题 | 留空 → wx.jpg |
九、调试方法
- 看页面源码:搜索
__WECHAT_SHARE__,确认 title/link/imgUrl。 - 看
<title>:应与分享标题一致。 - 微信开发者工具 / 真机:打开页面 → 分享 → 看卡片缩略图。
- 直接访问 sharethumb URL:浏览器打开最终
imgUrl,应返回 300×300 JPEG。 - 确认 wx.jpg 存在:
/attachs/wx.jpg可访问。
控制台可查看(脚本写入):
window.__WECHAT_SHARE__ // 最终配置
window.__WECHAT_SHARE_PAGE__ // { title, firstImage } 页面扫描结果
十、常见问题
Q:为什么分享图是网站小 logo 而不是文章大图?
A:PHP 未传 imgUrl,且 DOM 里 第一个 <img> 是小图标。解决:详情 Action 传 config_weixin_img($photo)。
Q:为什么分享标题还是站点名?
A:检查 header 是否读 $mobile_title;Action 是否 forcePageShare;是否被后台默认分享覆盖。
Q:多图能否自动选最大的一张?
A:当前不会。只能 PHP 指定,或调整 HTML 让目标图成为第一个有效 <img>(不推荐,应用 PHP 指定)。
Q:wx.jpg 放在哪?
A:站点 attachs/wx.jpg(与上传目录同级)。sharethumb 失败时也会回退此文件。
十一、相关文件索引
| 文件 | 作用 |
|---|---|
Banyan/Lib/Action/Wap/CommonAction.class.php | setWechatShare、seo、辅助方法 |
Banyan/Lib/Service/WechatShareService.class.php | 合并后台默认与页面参数 |
Banyan/Lib/Action/Wap/ShopAction.class.php | initShopWechatShare 商家分享 |
Banyan/Lib/Action/Wap/ApiAction.class.php | sharethumb 裁图 |
static/default/wap/js/wechat-share.js | 前端规范化 + JS-SDK |
themes/default/Wap/public/footer_share.html | 注入 __WECHAT_SHARE__ |
attachs/wx.jpg | 无图默认分享图 |
十二、更新帮助页
修改本文档后执行:
php tools/build_help_pages.php
访问:/home/help/article/slug/wechat-share-flow-detail.html
