wx-oauth.js 實(shí)現(xiàn)微信網(wǎng)頁授權(quán)

概述

一款基于 js-cookie介时、axios 等碉京,通過微信網(wǎng)頁授權(quán),以獲取 openid unionid 等用戶信息的 js 插件

配置

屬性 說明 類型 必填 默認(rèn)值
appId 公眾號(hào)的唯一標(biāo)識(shí) String -
scope 應(yīng)用授權(quán)作用域 snsapi_base snsapi_userinfo责掏,詳情請查看微信開發(fā)文檔 String snsapi_base
expires Cookies 過期時(shí)間/天 Number 30
state 重定向后會(huì)帶上 state 參數(shù)砍鸠,開發(fā)者可以填寫 a-zA-Z0-9 的參數(shù)值,最多 128 字節(jié) String -
oauthUrl 服務(wù)器授權(quán)良漱,絕對(duì)地址舞虱,獲取 openid unionid String -
onSuccess 服務(wù)器授權(quán)成功時(shí)的鉤子,返回字段為 response母市,且鉤子需要返回 openId unionId userInfo 等數(shù)據(jù)做邏輯處理 Function -
onFail 服務(wù)器授權(quán)失敗時(shí)的鉤子矾兜,返回字段為 error Function -

方法

方法名 說明 參數(shù)
init 初始化 -
oauth 授權(quán),再調(diào)用可切換賬號(hào) -
getUserInfo 獲取用戶信息 -

示例

import WxOauth from "@/utils/wx/oauth";

const wxOauth = new WxOauth({
    appId: "your appId",
    oauthUrl: "your oauthUrl",
    onSuccess: response => {
        // 處理成功回調(diào)后患久,獲取unionId openId userInfo等信息并返回

        const unionId = "unionId";
        const openId = "openId";
        const userInfo = "userInfo";

        return {
            unionId,
            openId,
            userInfo
        };
    }
});

wxOauth.init();

代碼

import Cookies from "js-cookie";
import axios from "axios";

class WxOauth {
    /**
     * @param appId         公眾號(hào)的唯一標(biāo)識(shí)
     * @param scope         應(yīng)用授權(quán)作用域snsapi_base|snsapi_userinfo椅寺,默認(rèn)snsapi_base
     * @param expires       Cookies過期時(shí)間/天浑槽,默認(rèn)30天
     * @param state         重定向后會(huì)帶上state參數(shù),開發(fā)者可以填寫a-zA-Z0-9的參數(shù)值返帕,最多128字節(jié)
     * @param oauthUrl      服務(wù)器授權(quán)桐玻,絕對(duì)地址,獲取openid unionid
     * @param onSuccess     服務(wù)器授權(quán)成功時(shí)的鉤子荆萤,返回字段為 response
     * @param onFail        服務(wù)器授權(quán)失敗時(shí)的鉤子镊靴,返回字段為 error
     */
    constructor(options) {
        const {
            appId,
            scope,
            expires,
            state,
            oauthUrl,
            onSuccess,
            onFail
        } = options;

        this.appId = appId;
        this.scope = scope || "snsapi_base";
        this.isSnsapiBase = scope === "snsapi_base";
        this.expires = expires || 30;
        this.state = state;
        this.oauthUrl = oauthUrl;

        this.onSuccess = onSuccess;
        this.onFail = onFail || function() {};
    }

    /**
     * @description `判斷數(shù)據(jù)是否為對(duì)象`
     *
     * @param {*} data
     */
    _isObject(data) {
        return Object.prototype.toString.call(data) === "[object Object]";
    }

    /**
     * @description 獲取請求參數(shù),支持解析帶#的url
     *
     * @param {name} name 參數(shù)名
     */
    _getQueryString(name) {
        return (
            decodeURIComponent(
                (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
                    location.href
                ) || ["", ""])[1].replace(/\+/g, "%20")
            ) || null
        );
    }

    /**
     * @description 獲取拼接后的url链韭,過濾undefined|null數(shù)據(jù)
     *
     * @param {String} url
     * @param {Object} data
     */
    _getUrl(url, data) {
        if (!this._isObject(data)) {
            return url;
        }

        const params = Object.keys(data).reduce((pre, key) => {
            const value = data[key];

            value !== undefined &&
                value !== null &&
                (pre += `&${key}=${value}`);
            return pre;
        }, "");

        return `${url}${params.replace("&", "?")}`;
    }

    /**
     * @description 服務(wù)器授權(quán)偏竟,獲取用戶信息
     */
    _oauth(code, state) {
        return new Promise((resolve, reject) => {
            const options = {
                method: "POST",
                data: {
                    code,
                    state
                },
                url: this.oauthUrl
            };

            axios
                .request(options)
                .then(res => {
                    const { openId, unionId, userInfo } = this.onSuccess(
                        res.data
                    );

                    Cookies.set(this._getCookieName("unionId"), unionId, {
                        expires: this.expires
                    });
                    Cookies.set(this._getCookieName("openId"), openId, {
                        expires: this.expires
                    });
                    Cookies.set(this._getCookieName("userInfo"), userInfo, {
                        expires: this.expires
                    });

                    resolve();
                })
                .catch(err => this.onFail(err));
        });
    }

    /**
     * @description 生成特定cookie名
     */
    _getCookieName(name) {
        return `wx_oauth_${this.appId}_${name}`;
    }

    /**
     * @description 是否已登錄
     */
    _isLogged(openId, unionId) {
        return this.isSnsapiBase ? openId : unionId || openId;
    }

    /**
     * @description 登錄,通過code獲取用戶信息
     */
    async _login() {
        const code = this._getQueryString("code");

        if (code) {
            const state = this._getQueryString("state");

            await this._oauth(code, state);
            return;
        }

        this.oauth();
    }

    init() {
        const unionId = Cookies.get(this._getCookieName("unionId"));
        const openId = Cookies.get(this._getCookieName("openId"));

        !this._isLogged(openId, unionId) && this._login();
    }

    /**
     * @description 微信授權(quán)敞峭,支持切換賬號(hào)
     */
    oauth() {
        Cookies.remove(this._getCookieName("unionId"));
        Cookies.remove(this._getCookieName("openId"));

        const url = this._getUrl(
            "https://open.weixin.qq.com/connect/oauth2/authorize",
            {
                appid: this.appId,
                redirect_uri: encodeURIComponent(location.href),
                response_type: "code",
                scope: this.scope,
                state: this.state
            }
        );
        location.href = `${url}#wechat_redirect`;
    }

    /**
     * @description 獲取用戶信息
     */
    getUserInfo() {
        const userInfo = Cookies.get(this._getCookieName("userInfo"));

        return userInfo ? JSON.parse(userInfo) : {};
    }
}

export default WxOauth;

github

https://github.com/SuperIron/wx-oauth

作者

SuperIron

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末踊谋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子旋讹,更是在濱河造成了極大的恐慌殖蚕,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沉迹,死亡現(xiàn)場離奇詭異睦疫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胚股,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門笼痛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裙秋,“玉大人琅拌,你說我怎么就攤上這事≌蹋” “怎么了进宝?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枷恕。 經(jīng)常有香客問我党晋,道長,這世上最難降的妖魔是什么徐块? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任未玻,我火速辦了婚禮,結(jié)果婚禮上胡控,老公的妹妹穿的比我還像新娘扳剿。我一直安慰自己,他們只是感情好昼激,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布庇绽。 她就那樣靜靜地躺著锡搜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞧掺。 梳的紋絲不亂的頭發(fā)上耕餐,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音辟狈,去河邊找鬼肠缔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哼转,可吹牛的內(nèi)容都是我干的桩砰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼释簿,長吁一口氣:“原來是場噩夢啊……” “哼亚隅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起庶溶,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤煮纵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后偏螺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體行疏,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年套像,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酿联。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夺巩,死狀恐怖贞让,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柳譬,我是刑警寧澤喳张,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布希停,位于F島的核電站棠笑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奥帘。R本人自食惡果不足惜制跟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一舅桩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雨膨,春花似錦擂涛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爹土。三九已至,卻和暖如春踩身,著一層夾襖步出監(jiān)牢的瞬間胀茵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工挟阻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼娘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓附鸽,卻偏偏與公主長得像脱拼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坷备,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容