欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

小程序登陸設(shè)計-耐心看,講的很明白 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

小程序登陸設(shè)計-耐心看,講的很明白

發(fā)表時間:2021-4-13

發(fā)布人:葵宇科技

瀏覽次數(shù):156

 

小程序可以通過微信官方提供的登錄能力方便地獲取微信提供的用戶身份標識,快速建立小程序內(nèi)的用戶體系。

即「靜默登錄」,通過調(diào)用 wx.login 獲取到 code ,將其發(fā)送到開發(fā)者后端,開發(fā)者后端通過接口去微信后端換取到 openid 和 sessionKey(現(xiàn)在會將 unionid 也一并返回)后,然后把自定義登錄態(tài) 3rd_session(本業(yè)務(wù)命名為auth-token) 返回給前端,就已經(jīng)完成登錄行為了。

理論上,開發(fā)者后端可以通過 openid識別用戶,也能通過unionid關(guān)聯(lián)同主體的多個小程序、公眾號、app,實現(xiàn)數(shù)據(jù)互通,從而為每一個用戶創(chuàng)建獨一無二的uid(本業(yè)務(wù)自定義的用戶 id),在「微信生態(tài)」中建立成熟用戶體系。

然而,對于復(fù)雜的電商跨端應(yīng)用,比如pc、h5小程序,不同渠道注冊的uid是不同的,用戶登錄后難以對各個渠道的交易、促銷、收藏等數(shù)據(jù)進行整合。因此,要實現(xiàn)跨端的用戶體系數(shù)據(jù)互通,就需要提供一個唯一的用戶標識——手機號。這便是本文重點講述的「用戶登錄」,即「游客態(tài)」轉(zhuǎn)變成「會員態(tài)」的過程。

2. 「用戶登錄」流程

當新用戶第一次進入小程序時,便會觸發(fā)「靜默登錄」,這個過程對用戶是無感知的。但此時開發(fā)者服務(wù)端已經(jīng)為該用戶定義了uid,并下發(fā)auth-token給小程序端,對于一些需要鑒權(quán)的請求,服務(wù)端可以根據(jù)請求攜帶的auth-token精確識別是哪個用戶發(fā)起的行為。

然而,類似加購、下單領(lǐng)券等用戶行為,涉及到跨端數(shù)據(jù)的整合,在執(zhí)行用戶操作之前,會判斷用戶是否登錄,如若用戶未登錄,則跳轉(zhuǎn)登錄頁面,整個流程如下所示:

比如在「用戶中心」頁面點擊「我的訂單」,由于此時用戶未登錄,跳轉(zhuǎn)到登錄頁面,可以選擇以下兩種登錄方式:

  1. 選擇 「微信授權(quán)登錄」,彈出授權(quán)手機號信息彈窗,點擊「允許」,此時用戶登錄成功。
  2. 選擇 「手機快捷登錄」,輸入手機號,使用 「驗證碼」 或者 「密碼」 進行登錄,登錄成功跳轉(zhuǎn)回到「用戶中心」頁面。

上述步驟已經(jīng)完成了「用戶登錄」,用戶可以正常的執(zhí)行加購、領(lǐng)券、下單等操作。 為了提升用戶體驗,需要對 「會員信息」 進行維護 ,比如昵稱、頭像、性別、生日等信息,最簡單的方法是 獲取「微信授權(quán)用戶信息」。觸發(fā)時機分為以下兩種:

  1. 用戶第一次選擇 「微信授權(quán)登錄」 成功后跳轉(zhuǎn)授權(quán)用戶信息頁面,點擊 「授權(quán)用戶信息」,彈出授權(quán)用戶信息彈窗。點擊「允許」,跳轉(zhuǎn)回「用戶中心」頁面。
  2. 在「用戶中心」頁面點擊頭像昵稱區(qū)域,彈出授權(quán)用戶信息彈窗,點擊「允許」,更新「會員信息」并跳轉(zhuǎn)用戶信息編輯頁面。

3. 「用戶登錄」方案設(shè)計

3.1 架構(gòu)

「用戶登錄」方案架構(gòu)如上圖所示,將所有登錄相關(guān)功能抽象到 「service 層」(本項目將其命名為session),供 「業(yè)務(wù)層」 調(diào)用。該 「service 層」 主要分為以下兩個模塊:

3.1.1 libs - 提供登錄相關(guān)的類方法供「業(yè)務(wù)層」調(diào)用

  1. 封裝session類,提供類方法供「業(yè)務(wù)層」調(diào)用。主要有以下幾種方法:
方法名功能使用場景
silentLogin發(fā)起靜默登錄-
login登錄,silentLogin方法的一層封裝用于小程序啟動時發(fā)起靜默登錄
refreshLogin刷新登錄態(tài),silentLogin方法的一層封裝用于登錄態(tài)過期時發(fā)起靜默登錄
ensureSessionKey驗證sessionKey是否過期,過期則刷新登錄態(tài)綁定微信授權(quán)手機號時驗證是否過期,過期則得重新彈窗授權(quán)
bindPhone綁定微信授權(quán)手機號微信授權(quán)手機號彈窗點擊「允許」觸發(fā)
updateUser綁定微信授權(quán)用戶信息微信授權(quán)用戶信息點擊「允許」觸發(fā)
getCurrentAuthStep獲取當前用戶登錄所屬階段詳見下文
mustAuth各種觸發(fā)場景攔截判斷是否需要登錄詳見下文

當然,session類中還封裝了一些方法用于與storage交互,比如獲取storage中的auth-token用于各種鑒權(quán)請求攜帶等等。session類也提供的一些拓展方法,比如注銷賬號、解綁手機號等等用于后續(xù)需求迭代。

  1. 裝飾器:

    • must-auth: mustAuth類方法的裝飾器,便于業(yè)務(wù)層各種場景觸發(fā)登錄。
    • fuse-line: 熔斷機制,如果短時間內(nèi)多次調(diào)用,則停止響應(yīng)一段時間,類似于 TCP 慢啟動。用于解決refreshLogin、login等方法的并發(fā)處理問題。
    • single-queue: 單隊列模式,同一時間,只允許一個正在過程中的網(wǎng)絡(luò)請求。請求被鎖定之后,同樣的請求都會被推入隊列,等待進行中的請求返回后,消費同一個結(jié)果。用于解決refreshLoginlogin等方法的并發(fā)處理問題。

3.1.2 ui - 提供通用組件供業(yè)務(wù)層調(diào)用

  1. 基礎(chǔ)組件: user-containerphone-container分別是獲取「微信授權(quán)用戶信息」和獲取「微信授權(quán)手機號」的純 UI 單元組件,給通用組件使用。
  2. behavior 類:拿到授權(quán)數(shù)據(jù)后需要發(fā)送給服務(wù)端進行存儲,也需要執(zhí)行一些跳轉(zhuǎn)邏輯判斷,這些都抽象成行為類封裝在auth-flow中,供通用組件使用。
  3. 通用組件: 共用一個行為類,區(qū)別在于auth-flow-container用于頁面,auth-flow-popup用于彈窗。如下所示,小程序只有微信授權(quán)功能,則可以通過彈窗完成授權(quán)。如小程序同時提供手機號驗證碼和密碼登錄等功能,則需跳轉(zhuǎn)特定登錄頁面。

3.2 libs

3.2.1 用戶身份定義

綜上所示,用戶登錄的階段可以分為以下三步:

// 用戶登錄的階段 export enum AuthStepType {   // 階段一:游客態(tài):靜默登錄成功,未綁定手機號,無用戶信息   ONE = 1,   // 階段二:會員態(tài):用戶登錄成功,已綁定手機號,無用戶信息   TWO = 2,   // 階段三:會員信息態(tài):用戶登錄成功,已綁定手機號,有用戶信息   THREE = 3, } 復(fù)制代碼

那么如何判斷用戶此時處于哪個步驟,基于「靜默登錄」的啟發(fā),原本「靜默登錄」成功開發(fā)者后端會將自定義登錄態(tài) auth-token返回給前端,此處請求可以攜帶返回「用戶信息」,同auth-token一起命名為session存儲在本地storage。當「用戶登錄」或者「更新用戶信息」時,會同步更新storagekeysession的數(shù)據(jù),從而通過這些用戶數(shù)據(jù)判斷當前用戶處于哪一個登錄階段。

以下表格列出了session存儲的部分重要的屬性以及在三個階段屬性對應(yīng)的值。

屬性定義游客態(tài)會員態(tài)會員信息態(tài)
authToken自定義登錄態(tài)'0d5bad172...''0d5bad172...''0d5bad172...'
uid用戶 id'001''001''001'
busiIdentity用戶身份定義'VISIT''MEMBER''MEMBER'
nickName用戶昵稱'''u_a1bk45''rileycai'
headUrl頭像鏈接'''''www.xx.com/image/...'
phone手機號碼'''17600888888''17600888888'
...其它用戶信息.........

注意: 會員態(tài)和會員信息態(tài)的busiIdentity值均為MEMBER,區(qū)分會員態(tài)和會員信息態(tài)可以通過用戶昵稱和頭像等字段,比如用戶登錄成功會為用戶生成以'u_'開頭的默認昵稱和默認為空的用戶頭像鏈接。

判斷用戶此時處于哪個步驟的代碼如下:

  // 獲取當前授權(quán)階段   public getCurrentAuthStep(): AuthStepType {     // 切換賬號登錄的時候,始終返回AuthStepType.ONE     const loginMode = this.getLoginMode();     if (loginMode === LoginMode.SWITCH_ACCOUNT) return AuthStepType.ONE;      // 用戶身份定義非會員返回AuthStepType.ONE     const userInfo = this.getUser();     if (userInfo?.busiIdentity !== 'MEMBER') return AuthStepType.ONE;      // 初次登錄,未授權(quán)用戶信息,返回AuthStepType.TWO     if (userInfo.nickName.substring(0, 2) === 'u_' && !userInfo.headUrl)       return AuthStepType.TWO;      // 都有,返回AuthStepType.THREE     return AuthStepType.THREE;   } 復(fù)制代碼

3.2.2 用戶登錄觸發(fā)場景

前面提到過,「用戶登錄」的 目的是為了整合各個渠道的交易、促銷、收藏等數(shù)據(jù),針對電商小程序,目前總結(jié)的需要用戶登錄的場景如下所示:

即當用戶登錄小程序時,可以正常瀏覽瀏覽商品,只有觸發(fā)某些特定行為,比如領(lǐng)券、加購、收藏、下單等,才會判斷用戶是否處于登錄狀態(tài),如未登錄,跳轉(zhuǎn)登錄頁面。

如下所示,封裝mustAuth方法進行攔截,未登錄則跳轉(zhuǎn)登錄頁面:

export default class Session {   ...   public mustAuth({     mustAuthStep = AuthStepType.TWO, // 傳人參數(shù),需要授權(quán)的LEVEL   } = {}): Promise<void> {     // 當前階段處于會員態(tài)(2)或者會員信息態(tài)(3),執(zhí)行resolve操作     if (this.getCurrentAuthStep() >= mustAuthStep) return Promise.resolve();     // 當前階段處于游客態(tài)(1),跳轉(zhuǎn)登錄頁     Navigator.gotoPage('/login/home');     // 執(zhí)行reject操作     return Promise.reject();   } } 復(fù)制代碼

上述代碼是跳轉(zhuǎn)頁面攔截,對于彈窗而言,需要把彈窗注入base-page(每個頁面都需要引入的通用組件,封裝每個頁面都需要使用的通用方法,比如錯誤處理等)中,通過 id 查找到彈窗組件,并進行調(diào)用。

export default class Session {   ...    public mustAuth({     mustAuthStep = AuthStepType.TWO, // 需要授權(quán)的LEVEL     popupCompName = 'auth-flow-popup',   } = {}): Promise<void> {     // 當前階段處于會員態(tài)(2)或者會員信息態(tài)(3),執(zhí)行resolve操作     if (this.getCurrentAuthStep() >= mustAuthStep) return Promise.resolve();     // 獲取彈窗組件     const pages = getCurrentPages();     const curPage = pages[pages.length - 1];     const context = curPage.$$basePage || curPage;     const popupComp = context.selectComponent(`#${popupCompName}`);     // 容錯處理     if (!popupComp) {       return Promise.reject(         new Error(           "當前頁面未找到 #auth-popup 組件,請參考 'doc/登錄組件的使用方式.md'",         ),       );     }     // 調(diào)用彈窗組件方法     popupComp.setMustAuthStep(mustAuthStep);     popupComp.nextStep();     // 等待授權(quán)成功回調(diào)     return this.waitAuth();   } }  復(fù)制代碼

各個業(yè)務(wù)使用時可以通過session.mustAuth().then(() => {...});進行調(diào)用,為了提高使用體驗,也可以使用裝飾器@mustAuth()來修飾各個業(yè)務(wù)需求 類的方法,裝飾器源碼如下:

/**  * 登錄檢查裝飾器,使用該裝飾器的方法,會先執(zhí)行授權(quán)檢查,如果未授權(quán),將跳轉(zhuǎn)登錄頁面  */ export default function mustAuth(option = {}) {   return function(     _target: Record) {     const method = descriptor.value;     descriptor.value = function(...args: any[]) {       if (!session) return;       // 登錄攔截       return session.mustAuth(option).then(() => {         if (method) return method.apply(this, args);       });     };   }; } 復(fù)制代碼

3.3 UI

3.3.1 基礎(chǔ)組件

1. phone-container 組件

因為需要用戶主動觸發(fā)才能發(fā)起獲取微信授權(quán)手機號接口,需用 button 組件的點擊來觸發(fā)。組件代碼如下所示:

// index.wxml    // index.ts export default class PhoneContainer extends BaseComponent {   getPhoneNumber(     e: WechatMiniprogram.Event,   ) {     this.triggerEvent('getphonenumber', { ...e.detail,  authType: AuthType.PHONE,});   } } 復(fù)制代碼

phone-container是一個純 UI 組件,通過triggerEvent事件將獲取手機號數(shù)據(jù)傳遞給父組件,

2. user-container 組件

user-container組件是獲取微信授權(quán)用戶信息的純 UI 組件,之前通過

 

2012 年 4 月 13 日之前,使用wx.getUserInfo彈出授權(quán)彈窗時,如果用戶點擊允許授權(quán),那么會記錄用戶的行為,下次再點擊時,不會彈窗而是直接將授權(quán)結(jié)果返回。4 月 13 日之后后,使用wx.getUserProfile,開發(fā)者每次通過該接口獲取用戶個人信息均需用戶確認,因此需要妥善保管用戶授權(quán)的頭像昵稱,避免重復(fù)彈窗。

3.3.2 行為類

如下圖所示,auth-flow行為類主要封裝用戶、小程序、服務(wù)端三者之間的交互邏輯。

在「微信授權(quán)登錄」過程中,小程序拿到加密的encryptedDataiv數(shù)據(jù),將其和攜帶的auth-token一起發(fā)送給開發(fā)者服務(wù)器,服務(wù)端通過auth-token鑒權(quán)識別這個用戶,并使用靜默登錄成功獲取的session_key(對稱解密密鑰)對encryptedDataiv數(shù)據(jù)進行對稱解密,獲取該用戶的手機號,將手機號與uid綁定,此時該用戶成功注冊會員,并將會員信息返回給小程序端。

小程序端更新本地storage存儲的session數(shù)據(jù),此時busiIdentity的值已經(jīng)從VISIT更新為MEMBER,用戶身份轉(zhuǎn)變?yōu)?span style="overflow-wrap: break-word; margin: 0px; padding: 0px; font-weight: 700; color: rgb(3, 106, 202);">會員態(tài),登錄成功。

在「授權(quán)用戶信息」的過程中,小程序調(diào)用wx.getUserProfile方法拿到用戶數(shù)據(jù),并將這些數(shù)據(jù)與攜帶的auth-token一起發(fā)送給開發(fā)者服務(wù)器,服務(wù)端通過auth-token鑒權(quán)識別這個用戶,更新該用戶的信息并將新的會員數(shù)據(jù)返回給小程序端。

小程序端更新本地storage存儲的session數(shù)據(jù),此時用戶昵稱和頭像均已更新,用戶身份轉(zhuǎn)變?yōu)?span style="overflow-wrap: break-word; margin: 0px; padding: 0px; font-weight: 700; color: rgb(3, 106, 202);">會員信息態(tài),授權(quán)成功。

眼尖的讀者一定觀察到了,時序圖中還對微信頭像做了轉(zhuǎn)存。這是因為用戶在微信端修改微信頭像后,之前「授權(quán)用戶信息」獲取的微信頭像鏈接就會失效,因此開發(fā)者應(yīng)該在自己獲取用戶信息后,將頭像保存下來,避免微信頭像 URL 失效后的異常情況。

3.3.3 通用組件

通用組件是對基礎(chǔ)組件和行為類的二次封裝,主要是為業(yè)務(wù)層提供彈窗登錄和頁面登錄兩種能力。

4. 總結(jié)

我們將用戶登錄能力從業(yè)務(wù)層中抽象出來,統(tǒng)一封裝在service層,便于復(fù)用。本文主要講述的是service層的架構(gòu),對于業(yè)務(wù)層的邏輯實現(xiàn)并沒有多加累贅。下列表格以小程序端為例,簡述了「靜默登錄」和「用戶登錄」整套方案的前后端邏輯實現(xiàn)。

        業(yè)務(wù)場景用戶感知前端處理邏輯后端處理邏輯補充說明
        掃碼搜索等各種方式進入小程序1、判斷:當前小程序是否緩存了登錄態(tài)auth-token 且使用wx.checkSeesion檢查當前用戶在小程序中登錄態(tài)是否過期,過期執(zhí)行步驟 2;
        2、使用wx.login獲取認證信息,請求后端wxLogin接口獲取微信小程序認證默認綁定的用戶身份以及登錄態(tài)auth-token。
        1、解析微信加密信息獲取認證身份openidunionId;
        2、查找openid是否已經(jīng)綁定了對應(yīng)的用戶,若綁定直接返回并為其生成對應(yīng)的登錄態(tài)auth-token;
        3、新用戶會根據(jù)openid為其自動生成一個用戶身份uid(見右補充說明)。
        a、存在聚合根標識unionId && 有用戶信息:將已有聚合根用戶對應(yīng)的exUid直接映射到當前uid下;
        b、存在聚合根標識unionId && 無用戶信息:根據(jù)unionId生成對應(yīng)的賬號,但和opneid對應(yīng)的uid一致;
        c、不存在聚合根標識:直接為對應(yīng)openid初始化一個uid。
        收藏加購、下單、領(lǐng)券等操作攔截跳轉(zhuǎn)1、判斷: 當前用戶身份處于游客態(tài),跳轉(zhuǎn)登錄頁面。對應(yīng)域服務(wù)后端接口可以根據(jù)請求攜帶的auth-token進行鑒權(quán),判斷用戶是否有操作權(quán)限-
        用戶登錄 或者 切換賬號選擇: