微信小程序 unionid 登陸解決方案

第三方登陸模塊使開發者能快捷靈活的擁有本身的用戶系統,是 LeanCloud 最受歡迎的功能之一。隨着第三方平臺的演化,特別是微信小程序的流行,LeanCloud 第三方登陸模塊也一直在改進:html

  • v2.0*:增長微信小程序一鍵登陸功能。支持開發者不寫任何後端代碼實現微信小程序用戶系統與 LeanCloud 用戶系統的關聯。
  • v3.6:增長 unionid 登陸接口。支持開發者使用 unionid 關聯一個微信開發者賬號下的多個應用從而共享一套 LeanCloud 用戶系統。 這兩個功能各自都很是簡單可靠,可是其中重疊的部分需求倒是一個難題:「如何在小程序中支持 unionid 登陸,既能獲得 unionid 登陸機制的靈活性,又保留一鍵登陸功能的便利性」。

在最近發佈的 JavaScript SDK v3.13 中包含了微信小程序 unionid 登陸支持。咱們根據不一樣的需求設計了不一樣的解決方案。小程序

* 這裏的版本指開始支持該功能的 JavaScript SDK 版本。後端

一鍵登陸

LeanCloud 的用戶系統支持一鍵使用微信用戶身份登陸。要使用一鍵登陸功能,須要先設置小程序的 AppID 與 AppSecret:微信小程序

1.登陸 微信公衆平臺,在 設置 > 開發設置 中得到 AppID 與 AppSecret。 前往 LeanCloud 控制檯 > 組件 > 社交,保存「微信小程序」的 AppID 與 AppSecret。 這樣你就能夠在應用中使用AV.User.loginWithWeapp()方法來使用當前用戶身份登陸了。api

AV.User.loginWithWeapp().then(user => {
  this.globalData.user = user;
}).catch(console.error);
複製代碼

使用一鍵登陸方式登陸時,LeanCloud 會將該用戶的小程序 openidsession_key 等信息保存在對應的 user.authData.lc_weapp 屬性中,你能夠在控制檯的 _User 表中看到:bash

{
  "authData": {
    "lc_weapp": {
      "session_key": "2zIDoEEUhkb0B5pUTzsLVg==",
      "expires_in": 7200,
      "openid": "obznq0GuHPxdRYaaDkPOHk785DuA"
    }
  }
}
複製代碼

若是用戶是第一次使用此應用,調用登陸 API 會建立一個新的用戶,你能夠在 控制檯 > 存儲 中的 _User 表中看到該用戶的信息,若是用戶曾經使用該方式登陸過此應用(存在對應 openid 的用戶),再次調用登陸 API 會返回同一個用戶。微信

用戶的登陸狀態會保存在客戶端中,可使用 AV.User.current() 方法來獲取當前登陸的用戶,下面的例子展現瞭如何爲登陸用戶保存額外的信息:session

// 假設已經經過 AV.User.loginWithWeapp() 登陸
// 得到當前登陸用戶
const user = AV.User.current();
// 調用小程序 API,獲得用戶信息
wx.getUserInfo({
  success: ({userInfo}) => {
    // 更新當前用戶的信息
    user.set(userInfo).save().then(user => {
      // 成功,此時可在控制檯中看到更新後的用戶信息
      this.globalData.user = user;
    }).catch(console.error);
  }
});
複製代碼

authData 默認只有對應用戶可見,開發者可使用 masterKey 在雲引擎中獲取該用戶的 openidsession_key 進行支付、推送等操做。詳情的示例請參考 支付微信開發

小程序的登陸態(session_key)存在有效期,能夠經過 wx.checkSession() 方法檢測當前用戶登陸態是否有效,失效後能夠經過調用 AV.User.loginWithWeapp() 從新登陸。app

使用 unionid

微信開放平臺使用 unionid 來區分用戶的惟一性,也就是說同一個微信開放平臺賬號下的移動應用、網站應用和公衆賬號(包括小程序),用戶的 unionid 都是同一個,而 openid 會是多個。若是你想要實現多個小程序之間,或者小程序與使用微信開放平臺登陸的應用之間共享用戶系統的話,則須要使用 unionid 登陸。

要在小程序中使用 unionid 登陸,請先確認已經在 微信開放平臺 綁定了該小程序

在小程序中有不少途徑能夠 獲取到 unionid。不一樣的 unionid 獲取方式,接入 LeanCloud 用戶系統的方式也有所不一樣。

一鍵登陸時靜默獲取 unionid

當知足如下條件時,一鍵登陸 API AV.User.loginWithWeapp() 能靜默地獲取到用戶的 unionid 並用 unionid + openid 進行匹配登陸。

  • 微信開放平臺賬號下存在同主體的公衆號,而且該用戶已經關注了該公衆號。
  • 微信開放平臺賬號下存在同主體的公衆號或移動應用,而且該用戶已經受權登陸過該公衆號或移動應用。 要啓用這種方式,須要在一鍵登陸時指定參數 preferUnionId 爲 true:
AV.User.loginWithWeapp({
  preferUnionId: true,
});
複製代碼

使用 unionid 登陸後,用戶的 authData 中會增長 _weixin_unionid 一項(與 lc_weapp 平級):

{
  "authData": {
    "lc_weapp": {
      "session_key": "2zIDoEEUhkb0B5pUTzsLVg==",
      "expires_in": 7200,
      "openid": "obznq0GuHPxdRYaaDkPOHk785DuA",
      "unionid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo"
    },
    "_weixin_unionid": {
      "uid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo"
    }
  }
}
複製代碼

用 unionid + openid 登陸時,會按照下面的步驟進行用戶匹配:

  1. 若是已經存在對應 unionid(authData._weixin_unionid.uid)的用戶,則會直接做爲這個用戶登陸,並將全部信息(openidsession_keyunionid 等)更新到該用戶的 authData.lc_ewapp 中。
  2. 若是不存在匹配 unionid 的用戶,但存在匹配 openid(authData.lc_weapp.openid)的用戶,則會直接做爲這個用戶登陸,並將全部信息(session_keyunionid 等)更新到該用戶的 authData.lc_ewapp 中,同時將 unionid 保存到 authData._weixin_unionid.uid 中。
  3. 若是不存在匹配 unionid 的用戶,也不存在匹配 openid 的用戶,則建立一個新用戶,將全部信息(session_keyunionid 等)更新到該用戶的 authData.lc_ewapp 中,同時將 unionid 保存到 authData._weixin_unionid.uid 中。

無論匹配的過程是如何的,最終登陸用戶的 authData 都會是上面這種結構。

LeanTodo Demo 即是使用這種方式登陸的,若是你已經關注了其關聯的公衆號(搜索 AVOSCloud,或經過小程序關於頁面的相關公衆號連接訪問),那麼你在登陸後會在 LeanTodo Demo 的 設置 - 用戶 頁面看到當前用戶的 authData 中已經綁定了 unionid。

微信掃描二維碼進入 Demo

須要注意的是:

  • 若是用戶不符合上述靜默獲取 unionid 的條件,那麼就算指定了 preferUnionId 也不會使用 unionid 登陸。
  • 若是用戶符合上述靜默獲取 unionid 的條件,但沒有指定 preferUnionId,那麼該次登陸不會使用 unionid 登陸,但仍然會將獲取到的 unionid 做爲通常字段寫入該用戶的 authData.lc_weapp 中。此時用戶的 authData 會是這樣的:
{
  "authData": {
    "lc_weapp": {
      "session_key": "2zIDoEEUhkb0B5pUTzsLVg==",
      "expires_in": 7200,
      "openid": "obznq0GuHPxdRYaaDkPOHk785DuA",
      "unionid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo"
    }
  }
}
複製代碼
經過其餘方式獲取 unionid 後登陸

若是開發者自行得到了用戶的 unionid(例如經過解密 wx.getUserInfo 獲取到的用戶信息),能夠在小程序中調用 AV.User.loginWithWeappWithUnionId() 投入 unionid 完成登陸受權:

AV.User.loginWithWeappWithUnionId(unionid, {
  asMainAccount: true
}).then(console.log, console.error);
複製代碼
經過其餘方式獲取 unionid 與 openid 後登陸

若是開發者但願更靈活的控制小程序的登陸流程,也能夠自行在服務端實現 unionid 與 openid 的獲取,而後調用通用的第三方 unionid 登陸接口指定平臺爲 lc_weapp 來登陸:

const unionid = '';
const authData = {
  openid: '',
  session_key: ''
};
const platform = 'lc_weapp';
AV.User.loginWithAuthDataAndUnionId(authData, platform, unionid, {
  asMainAccount: true
}).then(console.log, console.error);
複製代碼

相對上面提到的一些 Weapp 相關的登陸 API,loginWithAuthDataAndUnionId 是更加底層的第三方登陸接口,不依賴小程序運行環境,所以這種方式也提供了更高的靈活度:

  • 能夠在服務端獲取到 unionid 與 openid 等信息後返回給小程序客戶端,在客戶端調用 AV.User.loginWithAuthDataAndUnionId 來登陸。
  • 也能夠在服務端獲取到 unionid 與 openid 等信息後直接調用 AV.User.loginWithAuthDataAndUnionId 登陸,成功後獲得登陸用戶的 sessionToken 後返回給客戶端,客戶端再使用該 sessionToken 直接登陸。
關聯第二個小程序

這種用法的另外一種常見場景是關聯同一個開發者賬號下的第二個小程序。

由於一個 LeanCloud 應用默認關聯一個微信小程序(對應的平臺名稱是 lc_weapp),使用小程序系列 API 的時候也都是默認關聯到 authData.lc_weapp 字段上。若是想要接入第二個小程序,則須要自行獲取到 unionid 與 openid,而後將其做爲一個新的第三方平臺登陸。這裏一樣須要用到 AV.User.loginWithAuthDataAndUnionId 方法,但與關聯內置的小程序平臺(lc_weapp)有一些不一樣:

  • 須要指定一個新的 platform
  • 須要將 openid 保存爲 uid(內置的微信平臺作了特殊處理能夠直接用 openid 而這裏是做爲通用第三方 OAuth 平臺保存所以須要使用標準的 uid 字段)。

這裏咱們以新的平臺 weapp2 爲例:

const unionid = '';
const openid = '';
const authData = {
  uid: openid,
  session_key: ''
};
const platform = 'weapp2';
AV.User.loginWithAuthDataAndUnionId(authData, platform, unionid, {
  asMainAccount: true
}).then(console.log, console.error);
複製代碼
獲取 unionid 後與現有用戶關聯

若是一個用戶已經登陸,如今經過某種方式獲取到了其 unionid(一個常見的使用場景是用戶完成了支付操做後在服務端經過 getPaidUnionId 獲得了 unionid)但願與之關聯,能夠在小程序中使用 AV.User#associateWithWeappWithUnionId()

const user = AV.User.current(); // 獲取當前登陸用戶
user.associateWithWeappWithUnionId(unionid, {
  asMainAccount: true
}).then(console.log, console.error);
複製代碼
啓用其餘登陸方式

上述的登陸 API 對接的是小程序的用戶系統,因此使用這些 API 建立的用戶沒法直接在小程序以外的平臺上登陸。若是須要使用 LeanCloud 用戶系統提供的其餘登陸方式,如用手機號驗證碼登陸、郵箱密碼登陸等,在小程序登陸後設置對應的用戶屬性便可:

// 小程序登陸
AV.User.loginWithWeapp().then(user => {
  // 設置並保存手機號
  user.setMobilePhoneNumber('13000000000');
  return user.save();
}).then(user => {
  // 發送驗證短信
  return AV.User.requestMobilePhoneVerify(user.getMobilePhoneNumber());
}).then({
  // 用戶填寫收到短信驗證碼後再調用 AV.User.verifyMobilePhone(code) 完成手機號的綁定
  // 成功後用戶的 mobilePhoneVerified 字段會被置爲 true
  // 此後用戶即可以使用手機號加動態驗證碼登陸了
}).catch(console.error);
複製代碼

驗證手機號碼功能要求在 控制檯 > 存儲 > 設置 > 用戶帳號 啓用「用戶註冊時,向註冊手機號碼發送驗證短信」。

綁定現有用戶

若是你的應用已經在使用 LeanCloud 的用戶系統,或者用戶已經經過其餘方式註冊了你的應用(好比在 Web 端經過用戶名密碼註冊),能夠經過在小程序中調用 AV.User#associateWithWeapp() 來關聯已有的帳戶:

// 首先,使用用戶名與密碼登陸一個已經存在的用戶
AV.User.logIn('username', 'password').then(user => {
  // 將當前的微信用戶與當前登陸用戶關聯
  return user.associateWithWeapp();
}).catch(console.error);
複製代碼

更多內容歡迎查看《在微信小程序與小遊戲中使用 LeanCloud》

相關文章
相關標籤/搜索