微信小程式訂閱

澤能發表於2020-05-28

微信小程式訂閱

摘要

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);
            }
        }
    });
}

 

 
 
 

大家覺得有什麼奇怪的,歡迎和我討論

 

相關文章