微信小程序的订阅消息机制真的是一言难尽:当开发者申请向用户发送消息的时候,用户会收到一个弹窗,选择接收或者拒绝。但是每次申请,每次弹窗,对用户来说是一件很麻烦的事,于是微信官方贴心的加上了一个 “总是保持以上选择,不再询问” 的选项,当用户勾选这个选项之后,微信会保存用户的选择,之后会按照这个标准自动处理开发者的申请,对用户来说,省去了弹窗操作的步骤,是个好事儿;但是对开发者来说,麻烦就麻烦在这里。
当用户使用小程序的频率偏低的时候,一旦用户选择了 “保持以上选择,不再询问”,隔十天半个月再进来,谁还会记得上一次的选择是啥?更要命的是,万一这次用户需要提醒了,他甚至都看不到弹窗,无法更改之前的选择。PS:微信在小程序设置里提供了通知管理入口,但是在我对身边朋友(还是互联网圈内人士)的调研里,100% 的人都不知道,聊胜于无。
我觉得这很不合理,当程序自动处理开发者的申请时,应该告诉用户执行了什么操作;或者在拒绝时,给用户一个再次选择的机会。在参考了网上一些方案之后,我写了一套逻辑来处理这个问题,自觉得在功能和用户体验方面还算平衡得不错。
为了方便描述,用户在没有勾选 “保持以上选择” 的情况下选择接收或取决,我称之为一次性操作;反之,我称为持续性操作。
//订阅按钮绑定事件
subscribe:function(){
let _this = this;
//发起订阅请求
wx.requestSubscribeMessage({
tmplIds: ["Template_Id"],
success:function(res){
//返回操作结果
if(res.Template_Id == "accept"){
//当结果为“允许”时执行订阅消息方法
_this.addUserToDatabase();
}else if(res.Template_Id == "reject"){
//当操作结果为“拒绝”时,有两种可能:一是用户一次性拒绝;二是持续性拒绝,要查看用户设置来分别处理
wx.getSetting({
withSubscriptions: true,
success:function(res){
if(res.subscriptionsSetting.itemSettings){
//返回的subscriptionsSetting对象中如果存在itemSettings,说明用户对某些模版进行过持续性设置
if(res.subscriptionsSetting.itemSettings.Template_Id){
//再看看itemSettings中有没有我们刚才请求的模板ID,如果有,说明用户对这个模板设置了持续性的reject,执行弹窗提醒
_this.openAuthorizeModal();
}else{
//如果itemSettings中没有请求的模板ID,说明用户是一次性拒绝,反馈订阅失败
wx.showToast({
title: '订阅失败',
icon:"error"
});
}
}else{
//返回的subscriptionsSetting对象中不存在itemSettings,说明用户是一次性拒绝,反馈订阅失败
wx.showToast({
title: '订阅失败',
icon:"error"
});
}
}
})
}else{
//当返回的操作结果为其他状态时统一提示订阅失败
wx.showToast({
title: '订阅失败',
icon:"error"
});
}
},
fail:function(res){
//如果用户关闭了消息主开关,将会通过fail返回,错误码20004
if(res.errCode == 20004){
//用户关闭了主开关,执行弹窗提醒
_this.openAuthorizeModal();
}
}
});
}
//订阅消息方法
addUserToDatabase:function (){
//订阅逻辑...
}
//打开提示弹窗
openAuthorizeModal:function(){
let _this = this;
//打开弹窗
wx.showModal({
content:"您尚未开启消息订阅功能,是否去设置?",
cancelText:"算了",
confirmText:"设置",
confirmColor:"#F64D46",
cancelColor:"#9F9F9F",
success:function(res){
//用户点击“设置”,弹出设置面板
if(res.confirm){
wx.openSetting({
withSubscriptions: true,
success:function(res){
//返回用户的设置结果
if(res.subscriptionsSetting.mainSwitch){
//如果消息主开关开启
if(res.subscriptionsSetting.itemSettings){
//看看subscriptionsSetting中是否存在itemSettings,如果存在,说明用户对某些模版进行过持续性设置
if(res.subscriptionsSetting.itemSettings.Template_Id){
//看看itemSettings中是否有我们申请的模板,如果有,说明这个模板被用户进行过某种持续性设置
if(res.subscriptionsSetting.itemSettings.Template_Id == 'accept'){
//如果我们申请的模板的值是“accept”,说明用户持续性允许了接收该模版消息,提示用户去订阅
wx.showToast({
title: '请再次点击订阅按钮',
icon:"none"
})
}else{
//如果我们申请的模板的值不是“accept”,说明用户对模板设置了持续性不接收消息。表示理解,友好提示
wx.showToast({
title: '消息订阅未开启',
icon:"error"
});
}
}else{
//如果itemSettings中没有我们申请的模板,表示用户没有对我们申请的模板进行过任何持续性的设置,可以让用户去订阅
wx.showToast({
title: '请再次点击订阅按钮',
icon:"none"
})
}
}else{
//如果subscriptionsSetting中不存在itemSettings,说明用户没有对任何模板进行过持续性设置,可以让用户去订阅
wx.showToast({
title: '请再次点击订阅按钮',
icon:"none"
})
}
}else{
//如果消息主开关关闭,说明用户铁了心不想接收任何消息,保持风度,尊重用户的选择
wx.showToast({
title: '消息订阅未开启',
icon:"error"
});
}
}
});
}
}
})
}
用户进入设置面板返回之后,可以视操作结果用 modal 引导订阅。但是我不喜欢频繁出弹层,所以没这么做。
另外,订阅结果里动态键的主意是谁想出来的?我想和你聊聊,心平气和的,嗯。
原文发于个人博客:http://mou2xie.site