微信小程序登陸(包括獲取不到unionid的狀況)

咱們通常都是先獲取到微信的 unionid,而後再經過 unionid 去登陸本身的網站,就能夠關聯到用戶在本身網站上的 user_id,可是在小程序登陸中,有時候能夠獲取到 unionid,有時候獲取不到,在獲取不到 unionid 的狀況下,用戶沒法正常登陸網站。html

 
UnionID機制說明: 
  若是開發者擁有多個移動應用、網站應用、和公衆賬號(包括小程序),可經過 unionid 來區分用戶的惟一性,由於只要是同一個微信開放平臺賬號下的移動應用、網站應用和公衆賬號(包括小程序),用戶的 unionid 是惟一的。換句話說,同一用戶,對同一個微信開放平臺下的不一樣應用,unionid 是相同的。
  同一個微信開放平臺下的相同主體的 App、公衆號、小程序,若是用戶已經關注公衆號,或者曾經登陸過App或公衆號,則用戶打開小程序時,開發者能夠直接經過  wx.login 獲取到該用戶UnionID,無須用戶再次受權。(解讀:用戶若是沒有登陸過app,也沒有登陸過公衆號,也沒有關注過公衆號的狀況下,小程序中經過 wx.login 是獲取不到 unionid的)
 
  簡而言之,微信針對不一樣的用戶在不一樣的應用下都有惟一的一個 openId, 可是要想肯定用戶是否是同一個用戶,就須要靠 unionid 來區分。
  一般本身的後臺都會有本身的一個用戶表,每一個用戶有不一樣的 userid。也就是說同一個用戶在同一個微信開放平臺下的相同主體的應用對應着相同的 userid, unionid 以及不一樣的 openid。因此在用戶登陸進來的時候,咱們只能靠微信返回給咱們的 unionid 去判斷是否是同一個用戶,再去關聯咱們的用戶表,拿到對應的 user_id。
 
通常狀況下(即在登陸小程序以前,已經關注過公衆號或已經登陸過公衆號或已經使用微信登陸的方式登陸過app),用戶經過如下兩步就正常成功登陸網站。
1. 獲取code(登陸憑證,用來換取openid及session_key等)
    wx.login({
      success: function(res){
         if(res.code){
             that.getNeededUserInfo(res.code);
          }else{
          console.log('獲取用戶登陸態失敗!'+res.errMsg);
      }
    }
  })

2. 獲取用戶信息(利用wx.login返回的code獲取用戶的信息)
  getNeededUserInfo: function(code){
    wx.request({
      url: 'https://my.com/login',
      method: 'POST',
      data: {
        code: code // 後端經過這個code去調用微信的接口(https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code),傳入參數code、appid、appsecret後獲取到微信返回的unionid、openid及session_key等。(而後後端能夠直接利用微信返回的信息去關聯用戶在本身網站的user_id)
      },
      success: function(res){
        // 能夠返回前端須要的用戶信息(包括unionid、openid、user_id等)
      }
    })
  }
二般狀況下(即在登陸小程序以前,既沒有關注過公衆號,也沒有登陸過公衆號,更沒有使用微信登陸的方式登陸過app),經過 wx.login 的到的 code 換不回 unionid 及 openid 等信息。
解決思路:經過帶登陸態的  wx.getUserInfo 獲取到用戶的加密數據 encryptedData 和加密算法的初始向量iv,而後將 encryptdata、iv 以及 code傳給後端,後端再去經過接收到的encryptedData、iv以、code 以及以前的 session_key 解密出用戶的 openid、unionid 等。加密數據解密算法
如下是具體實現步驟:
1. 獲取code(登陸憑證,用來換取openid及session_key等)
  wx.login({
    success:  function(res){
      if(res.code){
        that.getNeededUserInfo(res.code);
      }else{
        console.log('獲取用戶登陸態失敗!'+res.errMsg);
      }
    }
  })

2. 獲取加密數據和加密算法初始向量
舊版本基礎庫調取wx.getUserInfo()能夠直接獲取到微信返回的encryptdata等完整數據,基礎庫更新以後,須要增長withCredentials屬性,並將屬性值設置爲true時才能夠獲取到除用戶基本信息以外的encryptedData以及iv等數據。
須要注意的是:當withCredentials值爲true時,要求此前有調用過wx.login且登陸態還沒有過時。
  getEncData:  function(){
    wx.getUserInfo({
      withCredentials: true,
      success: function(res){
        that.getNeededUserInfo( code,  res.encryptedData,  res.encryptedData );
      }
    })
  }

3. 獲取用戶信息(利用wx.login返回的code獲取用戶的信息)
  getNeededUserInfo:  function(code, enc, iv){
    wx.request({
      url: 'https://my.com/login',
      method: 'POST',
      data: {
        code: code,
        encryptedData: enc,
        iv: iv
      },
      success: function(res){
        // 能夠返回前端須要的用戶信息(包括unionid、openid、user_id等)
      }
    })
  }
實際項目中須要將以上兩種狀況整合之後使用。
 
思路有兩種:
 
  第一種:( 前端判斷是否有 unionid )在向後端上傳 code 而且後端返回數據之後,前端判斷返回值中是否有 unionid 或者 unionid 是否爲 null,null 的狀況下去調用帶有用戶登陸態的wx.getUserInfo(),而後再將微信返回的  encryptedData 和 iv 返回給後端,後端解密出相應的信息後再返回給前端;
 
  第二種:( 後端判斷是否有 unionid )前端在調用 wx.getUserInfo() 時候帶着登陸態,而後無論後臺能不能拿到 unionid,都把 encryptedData 和 iv 返回給後端,後端在拿到前端 code 以後去請求微信的接口拿 unionid,若是返回的 unionid 爲空,再拿前端傳的 encryptedData、iv以及以前的 session_key 解密出 unionid。
 
相關文章
相關標籤/搜索