单页应用微信公众号分享解决方案

场景及问题

  • 场景:就是很简单的商城下单付款流程,付款时可以分享给微信好友,好友打开链接可以进行代付;

  • 问题:这个功能已经上线正常运行了很久,但是这几天,突然从客服部门反馈回来很多异常案例,很多用户分享出去想让好友代付,好友打开代付链接时,显示的不是代付的页面,而变成了分享人要分享的页面,多见于安卓系统;
    详见下图,打开代付链接,看到的应该是图2,而不是图1中的发起代付页面;

图1
图2

解决方案及思路

  • 参考:一开始的时候,网上搜索了很多,其实都是抄来抄去没有任何卵用的方法,治标不治本,以下的方法非常简单,100%原创,直接解决这个棘手的问题。

  • 错误分析:之前已经在生产环境运行了很久没有出问题,那么肯定是近期微信版本更新后,改变了单页应用分享出去的地址,导致了在A页面想分享出去B页面的链接,让用户打开显示的也是B页面,但链接出了问题,所以基于微信的分享错误兼容,用户打开仍然是A页面;

  • 具体解决过程:
    因为具体的页面地址和路由太长,我就以下面的链接示例详细说明,同样的道理;
    实际业务代码

现在我们在A页面时,A页面的链接为:https://xxx.xxx.com/h5/index.html#/pageA?order_id=xxx

此时分享的话,实际上要给出去B页面的链接:https://xxx.xxx.com/h5/index.html#/pageB?order_id=xxx,这样别人打开才能看到代付付款的页面;

这次微信更新,肯定在转义过程中把链接中的#给砍掉了,所以分享链接就会出问题;这种情况只要做过单页应用的前端开发,应该都能遇到,微信恶心的分享机制,碰到#这种奇怪的符号,安卓系统里面极大概率都要出问题;

如果是非哈希路由呢,分享肯定不会出问题,例如链接是这样的:https://xxx.xxx.com/h5/index.html/pageB?order_id=xxx,里面完全没有#,我们的具体解决思路,就是把奇奇怪怪的#/换成看起来正常点的东西;

直接放出封装的代码,代码之后讲其中的思路

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
import handle from '@/Global/utils/handle';

export const isAndroid = /(Android)/i.test(window.navigator.userAgent)

export const transformShareLink = (url, isBack = false) => {
if (isBack) {
// 刚进来自动'#/'的成分直接去除
return url.replace('#/', '').replaceAll('?a_route=', '#/').replace('&', '?')
}
// 无哈希路由
if (!url.includes('#/')) {
return url
}
return isAndroid ? url.replaceAll('?', '&').replaceAll('#/', '?a_route=') : url
}

/**
* 来自安卓的分享特殊处理
* @returns
*/
export const shareInit = () => {
// 是否是安卓手机打开公众号的分享出来的
const a_route = handle.getQueryByName(window.location.href, 'a_route')
// 非安卓
if (!a_route) {
return true
}
// 安卓
location.href = transformShareLink(location.href, true)
return false
}

可以看到其实就是2个函数,一个transformShareLink,一个shareInit,重点在于transformShareLink方法处理的URL处理,就是简单暴力的字符串替换;

transformShareLink方法中,核心其实就是这一句

1
return isAndroid ? url.replaceAll('?', '&').replaceAll('#/', '?a_route=') : url

#/替换为?a_route=,就这么简单,将奇怪的符号,换为正常的字母,分享出去,另一个人打开链接再进入时,检测到有?a_route=这个字符,则又把?a_route=换回#/,这样就保证了分享链接经过微信时,保持正常不会被砍掉或者转义的状态,接收者打开时,本地函数又处理回单页应用哈希路由的模式,不经过微信,从而保证不会出错;

具体使用的话,在A页面,分享时将link先转换一次,如下图:
转换

好友打开代付页面时,全局app初始化,运行shareInit函数,如果检测到链接中有?a_route=,本地将URL重定向至含有#的哈希路由地址,如下图:
恢复

总结

总体来说就是微信分享时把URL处理为正常的形式,不经过微信,打开时又恢复为哈希路由模式,所有的转换和恢复,都在本地操作,不经过微信,曲线救国直接解决问题。

网上乱七八糟的解决方案,实际没有任何卵用,全部抄袭搬运,一点质量都没有,方法其实很简单,重要的是思路,搞懂微信分享的机制与原理是什么,结合对应的思路,就能找到完美的解决方案。

说点题外话,我做博客去分享一些东西,最初也是在实际业务过程中遇到很多问题,第一时间也会去网上参考别的开发者如何思考如何解决,结果发现大多数就是抄袭搬运毫无质量,要么会解决的人自己悄悄解决了,也不会分享,那既然这样,还不如从我做起,能分享一些是一些,坚持原创,坚持思路大于方法,希望能帮助遇到和我当时一样懵逼抓狂却又无助的开发者。


单页应用微信公众号分享解决方案
https://liujiaweb.cn/posts/27415.html
作者
Liu Jia
发布于
2021年12月7日
许可协议