RadiomM
文章22
标签13
分类1
安卓、ios微信H5分享踩坑指南

安卓、ios微信H5分享踩坑指南

博主最近在开发一个H5的项目,正好遇到了微信分享,不得不说微信的文档不知多久没更新的缘故,里面的操作可以在安卓完美的进行,但是!有一个可恶的苹果挡住了去路!闲话不多说,直接进去正题。附上步骤图

步骤1

一、判断是否需要微信授权

根据微信JSSDK文档,一般来说后端需要配置白名单。进入公众号里面填写JS接口安全域名,这点很重要,因为这样才能获取到正确的config配置。按照我现在的项目,我们前端主要做的就是判断用户有没有openid,没有的话就让他去微信登录授权。那该怎么判断呢?没错只能在地址里判断有没有code码,没有code码的时候,我们就让他去进行微信授权。

1
2
3
4
5
if(window.location.href.includes('code='){
// 有code码的时候进行的操作
} else{
// 没有code码时候要进行微信授权
}

如果你是用vue的hash模式开发的话,当你用微信开发者工具看到微信正确授权回来之后是这样的一个链接。

1
http://192.168.1.165/?code=051JpHFa1U8B6A0sfLIa1m5d422JpHFy&state=#/activity

悲剧不?难受不?这样的code码要自己在链接里获取(开发环境下是不会跳转到你本地的,上面的代码只是展示用,实际上微信只会跳转到你的线上域名地址)。那要怎么获取啊?贴心博主给你下面的代码,不求人!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @description 解析get参数
* @param url
* @returns {Object}
*/
export function getUrlParams (url) {
if (url.includes('?')) {
const str = url.split('?')[1].split('#')[0]
const arr = str.split('&')
const obj = {}
for (let i = 0; i < arr.length; i++) {
obj[arr[i].split('=')[0]] = arr[i].split('=')[1]
}
return obj
} else {
return {}
}
}

只要你把上面的一整个链接直接放到这个方法里面,他就会返回一个Object对象给你。用上面的链接的话返回的就是下面的。

1
2
3
4
const obj = {
code:051JpHFa1U8B6A0sfLIa1m5d422JpHFy,
state:""
}

这时候你只需要将code码发送给你的后端,让他返回给你openid就可以了。当然这个方法不止是这么用的,当你分享需要带参数的时候,这个方法就可以放在跳转到微信授权之前直接调用,然后你就把传过来的参数直接保存到本地储存。为什么要这么做?没错,微信会把你的链接截取的不成人样,所以只能这样保存参数了。

二、获取config配置以及如何携带参数

这里如何引入微信的JSSDK就不再说了,可以通过npm下载包或者是script标签引入。如下:

1
npm i -S weixin-js-sdk

又或者

1
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>    vue项目的话请写在index.html页面

2.1 config配置注入

那么我们就进行第三步!就是config配置注入。原理就是我们通过接口给后端传递url地址(必须与上面公众号配置的安全域名一致!),后端通过微信的接口获取到config配置,具体为什么这么做呢?就是为了安全,不泄露你的公众号的某些信息。然后我们就填到下面的方法。

1
2
3
4
5
6
7
8
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: ['updateTimelineShareData', 'updateAppMessageShareData'] // 必填,需要使用的JS接口列表
});

这里我需要的是微信好友分享以及微信朋友圈分享,更多的接口可以查询微信接口文档这是需要特别提醒的是,配置成功后直接调用wx.ready事件
在这里插入图片描述
一般调试的时候都会打开debug。就是config里面的那个,方便查看config配置成功与否。

2.2 分享链接带参数

如果是简单的分享网页的话,其实不需要做这些步骤。因为微信内置就可以分享网页,只是不会携带任何东西而已,如果是绑定上下级关系的时候,就需要用到自定义分享去配置。前面说到的getUrlParams方法就起了重大作用,用来保存携带过来的参数,那么参数我们需要怎么拼接呢?首先有一点需要明确的是,微信授权回来以后,你的网址链接一般都是长这样的:

1
http://192.168.1.153/?code=051JpHFa1U8B6A0sfLIa1m5d422JpHFy&state=#/invite

没错,会一直携带微信授权回来的东西(博主用的是vue的hash模式,默认将路由地址加在后面),那么我们需要拼接出来的地址是怎么样的?如下:

1
http://192.168.1.153/?spoorerid=100&inviteuserid=1144

没错,微信的官方文档中,特别提醒了我们的链接不能携带#号后面的东西。详情请看这里
在这里插入图片描述
明确标签可以通过?的get方式携带参数,那么我们只要配置成这样就完事了。直接如何配置不做任何示例,我的方法就是,用一个变量拼接参数。如拼接成 ?spoorerid=100&inviteuserid=1144,然后拼成一个完整的链接。如下:

1
2
const link = (window.location.href).replace(window.location.search, addlink).split('#')[0]
// 其中addlink就是上面说的变量。拼出来的结果在上面已经展示了。

三、分享操作

基本上做完上面的工作就可以去分享了,但是!众所周知,ios跟安卓一直有这微妙的关系!没错,如果你是像博主一样,点击了分享以后,才去获取config配置的话,那么恭喜你,安卓是可以的,但是ios的就是不行!不管是在微信开发者工具多少次的成功,你ios这样做就是不行。下面提供两种方法。

3.1 全局配置

实现起来很简单,就是直接在app.vue里把微信JSSDK的东西都写上,包括获取config配置,还有就是ready里面的东西都写上,直接在mounted调用一下就可以了。但是这样的弊端就是,假如需求是指定某个页面才能分享操作,这样写的话就会单页面里的任何一个页面都可以分享,这是我们不想要的。

3.2 独立配置(指定某个页面分享)

上面说到,如果点击触发事件的时候才去获取config配置等等,在ios是不行的。经过不断的尝试以及是查询(其实是问了某个高手),当你跳转到那个需要分享的页面时,你不能使用**this.$router.push()**的方式去跳转,在hash模式下,其实页面是不做任何跳转的,这就导致了在ios中不能获取到配置项。这时候,原生的东西就起了关键作用:

1
window.location.href = window.location.href.split('#')[0] + '#/invite'

通过下面的方式跳转到分享页,页面是相当于刷新了一次,这时候在ios就能获取到相关配置了。可以参考这个文章

完整代码

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
import wx from 'weixin-js-sdk'
import { getWxConfig } from '../api/user'

export function wxShare() {
const params = {
type: 1,
url: window.location.href.split('#')[0]
}
// let link = (window.location.href).replace(window.location.search, '').split('#')[0]
let addlink = ''
const query = JSON.parse(localStorage.getItem('firstQuery'))
const user = JSON.parse(localStorage.getItem('User-Info'))
const counselor = JSON.parse(localStorage.getItem('counselor'))
if (query.spoorerid) {
addlink += `?spoorerid=${query.spoorerid}`
if (user && user.id) {
addlink += `&inviteuserid=${user.id}`
} else if (query.inviteuserid) {
addlink += `&inviteuserid=${query.inviteuserid}`
} else {
addlink += '&inviteuserid=0'
}
} else {
addlink += `?spoorerid=${counselor.id}`
if (user && user.id) {
addlink += `&inviteuserid=${user.id}`
}
}
const link = (window.location.href).replace(window.location.search, addlink).split('#')[0]
// console.log('addlink', addlink)
// console.log('link', link)
getWxConfig(params).then((res) => {
if (res.code === 200) {
wx.config({
debug: false,
appId: res.data.appid,
timestamp: res.data.timestamp,
nonceStr: res.data.nonceStr,
signature: res.data.signature,
jsApiList: ['updateTimelineShareData', 'updateAppMessageShareData']
})
}
})
wx.ready(() => {
const shareObj = {
title: '*******',
link: link,
imgUrl: 'http://hteshb.beegoedu.com/share.png',
desc: '你也一起来跟我携手上进吧',
success() {
console.log('分享成功')
},
fail() {
console.log('分享失败')
}
}
// 分享给朋友
wx.updateAppMessageShareData(shareObj)
// 分享到朋友圈
wx.updateTimelineShareData(shareObj)
})
wx.error(function (res) {
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
console.log('失败返回参数', res)
})
}

总结

好了,花了两三个小时终于是整理完了这文章。如果觉得有用,喜欢收藏或者点个喜欢,毕竟这是博主搜了一个多星期百度的结果,希望能帮到大家永不加班,到点就走!