微信小程序订阅

Posted 泽能

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序订阅相关的知识,希望对你有一定的参考价值。

微信小程序订阅

摘要

1.基于promise封装微信小程序订阅

2.解决由于微信基础库版本低下的兼容

3.解决“总是保持以上选择,不再询问”的取消状态

主要运用API:

requestSubscribeMessage
getSetting
openSetting

 主要功能:

用户强制订阅,无论怎么取消都能订阅,总代码在下方,具体流程思路有耐心可以往下看...,可以拷贝直接用。引入即可,当然我比较菜,大家可以再改改。

总代码

/**
 * @desc 小程序订阅功能
 * @param {Array} tmplIds 订阅列表
 * @returns {Promise} 返回promise
 */

// 永久关闭订阅则代表点击了我不在接受此消息,再次订阅是无法弹起授权窗口的。普通关闭时可以再次弹起授权窗口。


export const Subscribe = (tmplIds = []) => {
    return new Promise((resolve, reject) => {
        // 判断是否为微信小程序,不是的不做订阅进行跳过
        let isWx = false;
        // #ifdef MP-WEIXIN
        isWx = true;
        // #endif
        if (!isWx) resolve(1);
        console.log(‘进来了哟‘)
        // 判断基本库是否在2.8.3,低于的暂时不做订阅进行跳过
        const versionCan = compareVersion("2.8.3");
        if (versionCan === -1) resolve(1);
        // 主流程
        requestSubscribe(tmplIds, resolve, reject)
    })

}
// 申请订阅功能
function requestSubscribe(tmplIds, resolve, reject) {
    uni.requestSubscribeMessage({
        tmplIds,
        success: async res => {
            // 检查订阅数量
            let checkSubscribeBool = await checkSubscribeAll(tmplIds, res);
            if (checkSubscribeBool) {
                // 用户完成订阅
                console.log("[用户完成订阅]")
                resolve(1);
            } else {
                // 跳去检查永久关闭订阅还是普通关闭订阅
                guidSubscribeMessageAuthAfter(tmplIds, resolve, reject);
            }
        },
        fail: res => {
            console.log(res, "订阅,失败");
            if (res.errCode == 20004) {
                // console.log(res, ‘fail:用户关闭了主开关,无法进行订阅,引导开启---‘);
                guideOpenSubscribeMessage(tmplIds, resolve, reject);
            }
            return
        }
    })
}



// 计算用户订阅消息的数量
function checkSubscribeAll(tmplIds, res) {
    // 将accept的生成一个数组,判断申请的订阅消息是不是已经订阅消息的子集
    let arr = [];
    for (const key of Object.keys(res)) {
        if (res[key] === ‘accept‘) {
            arr.push(key);
        }
    }
    if (arr.length == tmplIds.length) {
        console.log(‘订阅完毕‘)
        return true
    } else {
        console.log(‘没订阅或者少订阅‘)
        return false
    }

}

// 检查用户是否授权完毕(检查时永久关闭还是普通关闭)
function guidSubscribeMessageAuthAfter(tmplIds, resolve, reject) {
    uni.getSetting({
        withSubscriptions: true,
        success: async res => {
            let {
                authSetting = {},
                subscriptionsSetting: { mainSwitch = false, itemSettings = {} } = {}
            } = res;
            if (Object.keys(itemSettings).length == 0) {   // 这种情况是普通关闭
                uni.showModal({
                    title: "温馨提示",
                    content: "同意订阅才能及时获知完成进度领取优惠",
                    confirmText: "重新订阅",
                    cancelText: "我再看看",
                    success: res => {
                        if (res.confirm) {
                            // 重新调起授权订阅
                            requestSubscribe(tmplIds, resolve, reject);
                        } else if (res.cancel) {
                            //没成功订阅,返回reject
                            reject(2);
                        }
                    }
                });
            } else {   // 这种是订阅成功或永久关闭
                let checkSubscribeBool = await checkSubscribeAll(tmplIds, itemSettings);
                if (
                    authSetting["scope.subscribeMessage"] ||
                    (mainSwitch && checkSubscribeBool)
                ) {
                    //成功
                    console.log("用户手动开启同意了,订阅消息");
                    resolve(1);
                } else {
                    //失败,永久关闭
                    guideOpenSubscribeMessage(tmplIds, resolve, reject);
                }
            }
        }
    });
}



//引导用户重新授权(永久关闭的方法)
function guideOpenSubscribeMessage(tmplIds, resolve, reject) {
    // console.log(resolve, reject, ‘rescovavasr1‘)
    uni.showModal({
        title: "温馨提示",
        content: "检测到您没有开启全部订阅消息的权限,是否去设置?",
        success: res => {

            if (res.confirm) {
                uni.openSetting({
                    success: res => {
                        // 在检查是否全部订阅完毕
                        guidSubscribeMessageAuthAfter(tmplIds, resolve, reject);
                    }
                });
            } else if (res.cancel) {
                // console.log(resolve, reject, ‘rescovavasr2‘)
                uni.showModal({
                    title: "温馨提示",
                    content: "同意订阅才能及时获知完成进度领取优惠",
                    showCancel: false,
                    confirmText: "我知道了"
                });
                reject(2);
            }
        }
    });
}

// 比较版本号
function compareVersion(v2) {
    let { SDKVersion: v1 } = uni.getSystemInfoSync();
    v1 = v1.split(".");
    v2 = v2.split(".");
    const len = Math.max(v1.length, v2.length);

    while (v1.length < len) {
        v1.push("0");
    }
    while (v2.length < len) {
        v2.push("0");
    }

    for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i]);
        const num2 = parseInt(v2[i]);

        if (num1 > num2) {
            return 1;
        } else if (num1 < num2) {
            return -1;
        }
    }

    return 0;
}

 思路流程解析

这是第一步,封装promise,返回订阅成功和订阅失败的回调。以及判断版本号是否低于2.8.3,低于2.8.3是只能使用一个模板id的,可以考虑做兼容。这边内部原因就跳过不做订阅。然后走入主流程requestSubscribe(tmplIds, resolve, reject),带入模板id和俩个回调

   return new Promise((resolve, reject) => {
        // 判断是否为微信小程序,不是的不做订阅进行跳过
        let isWx = false;
        // #ifdef MP-WEIXIN
        isWx = true;
        // #endif
        if (!isWx) resolve(1);
        console.log(‘进来了哟‘)
        // 判断基本库是否在2.8.3,低于的暂时不做订阅进行跳过
        const versionCan = compareVersion("2.8.3");
        if (versionCan === -1) resolve(1);
        // 主流程
        requestSubscribe(tmplIds, resolve, reject)
    })

 这是第二步,订阅api。api走通就success,报错走fail。 主要看success,返回一个res,大家可以打印看看,里面就一个对象,键是id,订阅成功的值是accept,执行一波判断数量函数,符合长度说明用户全部订阅,就放行。

当然点击了“总是保持以上选择,不再询问”也是走到这里面,然后值都是订阅失败的。这里走去检查看看是否点击了“总是保持以上选择,不再询问”。

// 申请订阅功能
function requestSubscribe(tmplIds, resolve, reject) {
    uni.requestSubscribeMessage({
        tmplIds,
        success: async res => {
            // 检查订阅数量
            let checkSubscribeBool = await checkSubscribeAll(tmplIds, res);
            if (checkSubscribeBool) {
                // 用户完成订阅
                console.log("[用户完成订阅]")
                resolve(1);
            } else {
                // 跳去检查永久关闭订阅还是普通关闭订阅
                guidSubscribeMessageAuthAfter(tmplIds, resolve, reject);
            }
        },
        fail: res => {
            console.log(res, "订阅,失败");
            if (res.errCode == 20004) {
                // console.log(res, ‘fail:用户关闭了主开关,无法进行订阅,引导开启---‘);
                guideOpenSubscribeMessage(tmplIds, resolve, reject);
            }
            return
        }
    })
}

 第三步 getsettingApi,检查用户是否点击了“总是保持以上选择,不再询问”,判断的条件就是返回的res有没有itemSettings,当然大家可以找俩种情况比对一下就知道了,永久关闭的是有的那个对象的,普通关闭是没有的。

判断这个目的,是可以直接在调起订阅界面。可以引导用户重新点击。当然如果调不起就走guideOpenSubscribeMessage函数。

// 检查用户是否授权完毕(检查时永久关闭还是普通关闭)
function guidSubscribeMessageAuthAfter(tmplIds, resolve, reject) {
    uni.getSetting({
        withSubscriptions: true,
        success: async res => {
            let {
                authSetting = {},
                subscriptionsSetting: { mainSwitch = false, itemSettings = {} } = {}
            } = res;
            if (Object.keys(itemSettings).length == 0) {   // 这种情况是普通关闭
                uni.showModal({
                    title: "温馨提示",
                    content: "同意订阅才能及时获知完成进度领取优惠",
                    confirmText: "重新订阅",
                    cancelText: "我再看看",
                    success: res => {
                        if (res.confirm) {
                            // 重新调起授权订阅
                            requestSubscribe(tmplIds, resolve, reject);
                        } else if (res.cancel) {
                            //没成功订阅,返回reject
                            reject(2);
                        }
                    }
                });
            } else {   // 这种是订阅成功或永久关闭
                let checkSubscribeBool = await checkSubscribeAll(tmplIds, itemSettings);
                if (
                    authSetting["scope.subscribeMessage"] ||
                    (mainSwitch && checkSubscribeBool)
                ) {
                    //成功
                    console.log("用户手动开启同意了,订阅消息");
                    resolve(1);
                } else {
                    //失败,永久关闭
                    guideOpenSubscribeMessage(tmplIds, resolve, reject);
                }
            }
        }
    });
}

 第四步,用户永久关闭了订阅,我们可以用openSetting打开。这时候订阅消息是会出来没订阅的模板的。重新引导...这样就结束了这个封装啦!

//引导用户重新授权(永久关闭的方法)
function guideOpenSubscribeMessage(tmplIds, resolve, reject) {
    // console.log(resolve, reject, ‘rescovavasr1‘)
    uni.showModal({
        title: "温馨提示",
        content: "检测到您没有开启全部订阅消息的权限,是否去设置?",
        success: res => {

            if (res.confirm) {
                uni.openSetting({
                    success: res => {
                        // 在检查是否全部订阅完毕
                        guidSubscribeMessageAuthAfter(tmplIds, resolve, reject);
                    }
                });
            } else if (res.cancel) {
                // console.log(resolve, reject, ‘rescovavasr2‘)
                uni.showModal({
                    title: "温馨提示",
                    content: "同意订阅才能及时获知完成进度领取优惠",
                    showCancel: false,
                    confirmText: "我知道了"
                });
                reject(2);
            }
        }
    });
}

 

 
 
 

大家觉得有什么奇怪的,欢迎和我讨论

 

以上是关于微信小程序订阅的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序-订阅消息定时发送

微信小程序视图层WXML_模板

微信小程序订阅消息调研

微信小程序做出这种效果需要用到代码吗

微信小程序之再说“一次性订阅消息”

微信小程序 一次性订阅消息