小程序訂閱消息用戶拒絕/關閉后,如何引導用戶再開啟?并獲得用戶的操作呢
發布時間:2020-08-09
前言
有些時間沒折騰小程序了,話說年前小程序就發布了消息,于1月10日會下線模板消息下發功能,所有的訂閱消息都要用戶手動觸發確認同意,這可就太難了,之前的 wx.openSetting 、 wx.getPhoneNumber 、 wx.getUserInfo 等等API的調整,可把我折騰慘了,這次又來……
難道直接js調用,不爽嗎?非要整手動確認,爽是肯定的,但如果從一個用戶的角度出發,自己啥都沒干,你就把我信息獲取了、天天給我推一堆垃圾信息,那肯定不爽了,所以從這角度看,微信的調整也是為了尊重用戶的隱私,畢竟用戶第一嘛
今天主要是想分享一下,今天在處理這個訂閱消息邏輯時,遇到當 用戶拒絕 后,如何重新引導開啟 「訂閱消息」通知的問題,并在 開啟后獲取到它的狀態
如果你處理過小程序的訂閱消息,應該是知道的,在用戶拒絕或關閉消息總開關之后,我們引導用戶手動開啟「訂閱消息」功能(也就是 openSetting API的調用回調里,是拿不到 scope.subscribeMessage 狀態的),開始我也糾結了很久,百度、google都用上了,同樣發現很多的同學也有遇到這樣的問題,而都沒有找到解決方案,最后在我快要放棄的時候卻突然靈光一閃,想到了個辦法,所以抖膽BB幾句,分析一下:
溫馨提示:書讀的少,卻又喜歡瞎BB幾句,內容僅為個人解決方案的思路,僅供參考,不足之處請見諒,勿噴,謝謝~
授權API示例
首先來看下調用的示例:
wx.requestSubscribeMessage({
tmplIds: ['模版id'],
success (res) {
}
})
同時官方也說了, success 回調的模版對應有三種狀態:
accept = 同意
reject = 拒絕
ban = 后臺封禁
fail 也有對應的狀態碼,如下:
本次要講的是 errorCode 20004 與 reject 狀態時,
根據以往經驗,如果拒絕了,我們肯定是使用直接使用 openSetting ,引導用戶進行手動開啟授權(),比如:
//以微信運動為例
export default class Sign extends wepy.page {
config = {
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: '贏積分',
};
components = {
Toast: Toast,
Modals: Modals
};
methods = {
};
data = {
signHistory: []
};
getRunData() {
wx.getWeRunData({
success: res => {
……處理運動步數邏輯
}
});
}
setAuth() {
wx.getSetting({
success: res => {
//第一步,檢測是否有授權 - 沒有授權
if (!res.authSetting['scope.werun']) {
//第二步,開始授權,但這里有一個坑點(騰訊的bug),之前授權過但是是拒絕,所以會進入失敗
wx.authorize({
scope: 'scope.werun',
success: () => {
this.getRunData();
},
fail: () => {
//第三步,引導用戶,手動引導用戶點擊按鈕,去設置頁開啟,## Modals是自定義組件
this.$invoke('Modals', '__modalConfirm__', [
'檢測到您沒有打微信運動的權限,是否去設置?',
'openSetting',
//第四步,進入設置頁的回調 - 成功
res => {
let { authSetting } = res.detail;
if (authSetting['scope.werun']) {
this.getRunData();
} else {
this.$invoke('Toast', '__warning__', [
`您沒有同意授權微信運動,獲取步數失敗`
]);
}
},
//第五步,點擊取消按鈕的回調
() => {
this.$invoke('Toast', '__warning__', [
`您已拒絕微信運動授權,無法獲取步數`
]);
}
]);
}
});
} else {
//第六步,已經授權直接進入保存邏輯
// console.log("授權了")
this.getRunData();
}
}
});
}
}
上面代碼執行截圖如下:
上述代碼, this.$invoke('Modals'……) 部分為自定義彈窗,即引用用戶確定,去設置頁,
requestSubscribeMessage 問題點
但是 在 openSetting 的回調里,是沒有 scope.subscribeMessage 這一項的,下面是列出的 scope 列表 官方清單( 文檔地址 ):
//提交訂閱消息示例
export default class Sign extends wepy.page {
config = {
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: '贏積分',
};
setClock(e) {
let that = this;
if (wx.requestSubscribeMessage) {
wx.requestSubscribeMessage({
tmplIds: [pushReservationTmplIds],
success(res) {
if (res[pushReservationTmplIds] === 'accept') {
//發起請求……
} else if (res[pushReservationTmplIds] === 'reject') {
// 用戶歷史操作有設置了拒絕 or 關閉了訂閱消息的主(總)開關,導致無法推送
that.guideOpenSubscribeMessage();
} else {
wx.showToast({
title: '授權訂閱消息有誤',
icon: 'none'
});
}
},
fail(res) {
// 20004:用戶關閉了主開關 或在 消息通知 里 “拒絕接收”操作,無法進行訂閱,引導開啟
if (res.errCode == 20004) {
console.log(res, 'fail:用戶關閉了主開關,無法進行訂閱,引導開啟---');
}
}
});
} else {
wx.showToast({
title: '請更新您微信版本,來獲取訂閱消息功能',
icon: 'none'
});
}
}
guideOpenSubscribeMessage() {
//引導用戶,手動引導用戶去設置頁開啟,
this.$invoke('Modals', '__modalConfirm__', [
'檢測到您沒有開啟訂閱消息的權限,是否去設置?',
'openSetting',
res => {
console.log('openSetting的回調數據:', res);
//但是這個回調數據里,并沒有 「訂閱消息」 相關 open/close 的狀態返回
},
//用戶點擊了取消按鈕
() => {
// console.log("取消了")
this.$invoke('Toast', '__warning__', [
`您已拒絕訂閱消息授權,無法預約`
]);
}
]);
}
上圖為 openSetting 的回調數據,而網上說回調里不做任何處理,用戶是否有手動開啟,則讓提示讓他再手動點擊一次業務按鈕,如果有開啟,則回到最初的邏輯,訂閱消息成功,否則則又循環進入 openSetting 設置頁,俗稱“死纏爛打授權法”,這當然不失為一種方法,但體驗不是最好,
對于追求完美的我來說,不能接受,繼續尋找更好的方案,把官方文檔來回看,終于發現了新大陸,—— wx.getSetting
文檔有有這么一個屬性: subscriptionsSetting ,感謝蒼天,終于讓我看到了 訂閱消息 相關的東西,
//官方示例
wx.getSetting({
withSubscriptions: true,
success (res) {
console.log(res.authSetting)
// res.authSetting = {
// "scope.userInfo": true,
// "scope.userLocation": true
// }
console.log(res.subscriptionsSetting)
// res.subscriptionsSetting = {
// mainSwitch: true, // 訂閱消息總開關
// itemSettings: { // 每一項開關
// SYS_MSG_TYPE_INTERACTIVE: 'accept', // 小游戲系統訂閱消息
// SYS_MSG_TYPE_RANK: 'accept'
// zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: 'reject', // 普通一次性訂閱消息
// ke_OZC_66gZxALLcsuI7ilCJSP2OJ2vWo2ooUPpkWrw: 'ban',
// }
// }
}
})
在 wx.getSetting 的回調里,有一項 mainSwitch ,還有一項 withSubscriptions: true ,最后回調里還能一項 zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: 'reject' ,到這里,但它也只是在 getSetting 方法里啊,跟 openSetting 沒有扯上任何關系,怎么辦?
其實道理很簡單,但人有時候就是這樣,思維如果沒有轉換過來,你可以就會一直杠在那個死胡同里出不來,
openSetting 回調里取不到狀態, 那么我們是否可以在它的回調里,再做一次 getSetting 的調用里呢? ,取 getSetting 回調里的狀態來判斷,剛才用戶在設置頁的行為操作,直接看示例吧:
//提交訂閱消息示例
const pushReservationTmplIds = 'PVC_DBcvvdtffd1fO0vdS8YpSe0c7Br3QW54';
export default class Sign extends wepy.page {
config = {
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: '贏積分',
};
submitClock() {
fetchJson({
type: 'POST',
url: '/api/steps/clock',
data: {
},
success: res => {
wx.showToast({
title: '預定成功',
icon: 'success',
duration: 2000
});
}
});
}
setClock(e) {
let that = this;
if (wx.requestSubscribeMessage) {
wx.requestSubscribeMessage({
tmplIds: [pushReservationTmplIds],
success(res) {
if (res[pushReservationTmplIds] === 'accept') {
that.submitClock();
} else if (res[pushReservationTmplIds] === 'reject') {
// 用戶歷史操作有設置了拒絕 or 關閉了訂閱消息的主(總)開關,導致無法推送
// console.log(res, '0 拒絕 or 關閉了訂閱消息的主(總)開關---');
that.guideOpenSubscribeMessage();
} else {
wx.showToast({
title: '授權訂閱消息有誤',
icon: 'none'
});
}
},
fail(res) {
// 20004:用戶關閉了主開關,無法進行訂閱,引導開啟
if (res.errCode == 20004) {
// console.log(res, 'fail:用戶關閉了主開關,無法進行訂閱,引導開啟---');
that.guideOpenSubscribeMessage();
}
}
});
} else {
wx.showToast({
title: '請更新您微信版本,來獲取訂閱消息功能',
icon: 'none'
});
}
}
guidSubscribeMessageAuthAfter() {
//引導用戶 開啟訂閱消息 之后,「openSetting」 接口暫時不會返回,用戶手動設置后的狀態,所以采用「getSetting」接口重新進行查詢
wx.getSetting({
withSubscriptions: true,
success: res => {
let {
authSetting = {},
subscriptionsSetting: { mainSwitch = false, itemSettings = {} } = {}
} = res;
if (
(authSetting['scope.subscribeMessage'] || mainSwitch) &&
itemSettings[pushReservationTmplIds] === 'accept'
) {
this.submitClock();
// console.log('用戶手動開啟同意了,訂閱消息');
} else {
this.$invoke('Toast', '__warning__', [
`您沒有同意授權訂閱消息,預約領取失敗`
]);
}
}
});
}
guideOpenSubscribeMessage() {
//引導用戶,手動引導用戶去設置頁開啟,
this.$invoke('Modals', '__modalConfirm__', [
'檢測到您沒有開啟訂閱消息的權限,是否去設置?',
'openSetting',
//用戶點擊了確定按鈕,進入設置頁的回調
res => {
console.log('openSetting的回調數據:', res);
this.guidSubscribeMessageAuthAfter();
},
//用戶點擊了取消按鈕
() => {
// console.log("取消了")
this.$invoke('Toast', '__warning__', [
`您已拒絕訂閱消息授權,無法預約領取`
]);
}
]);
}
}
結尾
到這里, wx.requestSubscribeMessage 的問題,也就得到了解決,看到網上有貼子在噴 requestSubscribeMessage API的設計,比如: wx.requestSubscribeMessage的接口參數結構設計反人性,實習生設計的嗎? ,其實我也想說這么龐大的一個生態體系,更新方案就考慮的這么不全面嗎?還是說就是這么反人類? getSetting 里給 requestSubscribeMessage 的相關狀態, openSetting 里又壓根沒有,然后又把它的引導開啟邏輯UI也放在設置頁里面,我就郁悶了,
今天的分享,為我個人的解決思路方案,如有不足之處,請指出,勿噴~謝謝??!