微信小程序登錄授權及手機號獲取


實現效果:

 

 

1.開發工具uniapp

2.功能模塊

  ① 登錄模塊(微信登錄,授權獲取昵稱,頭像,地區等,授權獲取手機號,解密手機號)

  ② UI模塊 (uview,vant)

  ③ 請求模塊 (axios封裝) 

  ④ 問題匯總

3.功能拆解(附代碼)

  ① 微信登錄:文檔(https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html)

   步驟:

      <1> 通過微信官方提供的登錄api(wx.login)獲取code,用code當參數請求后台接口獲取openid,以此作為登錄憑證

      <2> 分段代碼:

        

wx.login({
    success(res) {
        if (res.code) {
            //向后台發起網絡請求
            wx.request({
                url: '后台提供的接口地址',
                data: {
                    code: res.code
                },
                success(res) {
                    console.log("獲取到的openid是:", res)
                }
            })
        } else {
            console.log('登錄失敗!' + res.errMsg)
        }
    }
})

  ② 授權獲取昵稱,頭像,地區:文檔(https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html)

   步驟:

      <1> 頁面產生點擊事件(例如 button 上 bindtap 的回調中)后才可調用

      <2> 分段代碼:

        

wx.getUserProfile({
    lang: 'zh_CN',
    desc: '用戶登錄',
    success: (res) => {
        console.log("用戶允許授權后獲得的信息為:", res)
    },
    fail: (err) => {
        console.log("用戶拒絕授權")
    }
})

  ③ 授權獲取手機號及解密,文檔(https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html)

    步驟:

      <1> 將 button 組件 open-type 的值設置為 getPhoneNumber

      <2> 用戶同意后,通過 bindgetphonenumber 事件回調獲取到微信服務器返回的加密數據

      <3> 獲取session_key

      <4> 向后台發送參數解密手機號

      <5> 分段代碼:

// html代碼:

// 原生微信小程序寫法:
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>

// uniapp寫法:
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">獲取手機號碼</button>

// js代碼:

// 獲取手機號:

getPhoneNumber(e) {
  if (e.detail.errMsg !== "getPhoneNumber:ok") return; // 如果用戶不同意授權則返回並結束
  console.log(e.detail.errMsg)
  console.log(e.detail.iv)
  console.log(e.detail.encryptedData)
}

// 檢驗登錄是否過期:

uni.checkSession({
    success(res) {
        console.log("登錄未過期,進行下一步操作")
    },
    fail() {
        console.log("登錄已過期,請重新登錄")
    }
})

// 獲取session_key,以此作為參數進行解密手機號

wx.request({
    url: "https://api.weixin.qq.com/sns/jscode2session",
    data: {
        'appid': "小程序的appid",
        'secret': "小程序密鑰",
        'js_code': "登錄時獲取到的code",
        'grant_type': "authorization_code" // 默認填寫authorization_code
    },
    method: 'GET',
    header: {
        'content-type': 'application/json'
    },
    success: function(res) {
        console.log("成功獲取到session_key", res)
    },
    fail(err) {
        console.log("獲取session_key失敗", err)
    }
})

// 解密手機號

wx.request({
    url: '后台提供的接口地址',
    data: {
        'encryptedData': e.detail.encryptedData,
        'iv': e.detail.iv,
        'session_key': "上一步獲取到的session_key"
    },
    method: 'GET',
    header: {
        'content-type': 'application/json'
    },
    success: function(data) {
        console.log("獲取到的手機號是", data)
    },
    fail: function(err) {
        console.log(err)
    }
})


    

  ④ 微信登錄流程的完整代碼:

    

<template>
  <!-- #ifdef MP-WEIXIN -->
  <view v-if="!isCanUse">
    <view>
      <view class='header'>
        <image src='你的網站logo等等'></image>
      </view>
      <view class='content'>
        <view>申請獲取以下權限</view>
        <text>獲得你的公開信息(昵稱,頭像、地區等)</text>
      </view>
      <button v-if="!flag" type="primary" class='btn' withCredentials="true" lang="zh_CN" open-type="getUserInfo" @tap="wxLogin">
        授權登錄
      </button>
      <button v-else type="primary" class='btn' open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">獲取手機號碼</button>
    </view>
  </view>
  <!-- #endif -->
</template>
<script>
export default {
  data() {
    return {
      SessionKey: '',
      OpenId: '',
      code: '',
      isCanUse: uni.getStorageSync('isCanUse'), //默認為true
      token: '',
      userInfo: {
        nickName: null,
        avatarUrl: null,
      },
      flag: false,
      toWeb: false,
      webSrc: 'http://localhost:8080/#/?token=' + uni.getStorageSync('token'),
    }
  },
  onLoad() {
    if (uni.getStorageSync('isCanUse') == '1') {
      console.log('已經授權登錄過了,請直接跳轉')
    } else {
      console.log('未授權登錄,請點擊登錄')
    }
  },
  methods: {
    wxLogin(e) {
      let p1 = this.wxSilentLogin() // 獲取code
      let p2 = this.wxGetUserProfile() // 獲取用戶信息
      p1.then((code) => {
        return code
      })
        .then((code) => {
          this.code = code
          return new Promise((resolve, reject) => {
            p2.then((res) => {
              resolve({
                code,
                iv: res.iv,
                encryptedData: res.encryptedData,
              })
            }).catch((err) => {
              reject(err)
            })
          })
        })
        .then((res) => {
          let _this = this
          // 請求服務器
          wx.request({
            url: '后台提供的接口',
            method: 'get',
            data: {
              code: res.code,
              encrypted_data: res.encryptedData,
              iv: res.iv,
            },
            header: {
              'content-type': 'application/json', // 默認值
            },
            success(res) {
              uni.setStorageSync('token', res.data.data)
              _this.token = res.data.data
              console.log('獲取token', _this.token)
            },
          })
        })
        .catch((err) => {
          console.log(err)
        })
    },
    wxGetUserProfile: function () {
      // 獲取頭像昵稱等
      let _this = this
      return new Promise((resolve, reject) => {
        wx.getUserProfile({
          lang: 'zh_CN',
          desc: '用戶登錄',
          success: (res) => {
            resolve(res)
            console.log('獲取到的用戶信息', res.userInfo)
            _this.userInfo.nickName = res.userInfo.nickName
            _this.userInfo.avatarUrl = res.userInfo.avatarUrl
            uni.setStorageSync('isCanUse', '1')
            _this.flag = true
            // _this.updateUserInfo();
          },
          // 失敗回調
          fail: (err) => {
            reject(err)
            console.log('選擇了拒絕')
          },
        })
      })
    },
    wxSilentLogin: function () {
      // 獲取code
      return new Promise((resolve, reject) => {
        wx.login({
          success(res) {
            resolve(res.code)
            console.log('獲取得到的loginres', res)
          },
          fail(err) {
            reject(err)
          },
        })
      })
    },
    getPhoneNumber: function (e) {
      var self = this
      if (e.detail.errMsg !== 'getPhoneNumber:ok') return
      wx.showLoading()
      uni.checkSession({
        success(res) {
          if (self.code) {
            //    2.訪問登錄憑證校驗接口獲取session_key
            wx.request({
              url: 'https://api.weixin.qq.com/sns/jscode2session',
              data: {
                appid: '小程序appid',
                secret: '小程序密鑰',
                js_code: self.code,
                grant_type: 'authorization_code',
              },
              method: 'GET',
              header: {
                'content-type': 'application/json',
              },
              success: function (data) {
                console.log('獲取到session_key啦', data)
                if (data.statusCode == 200) {
                  //3. 解密
                  wx.request({
                    url: '后台提供的接口',
                    data: {
                      encryptedData: e.detail.encryptedData,
                      iv: e.detail.iv,
                      sessionKey: data.data.session_key,
                    },
                    method: 'GET',
                    header: {
                      'content-type': 'application/json',
                    },
                    success: function (data) {
                      wx.hideLoading()
                      console.log('獲取到的手機號是', data.data.phoneNumber)
                    },
                    fail: function (err) {
                      console.log(err)
                    },
                  })
                }
              },
              fail: function (err) {
                console.log(err)
              },
            })
          } else {
            wx.showToast({
              icon: 'none',
              title: '授權失敗,請重新授權',
            })
            self.flag = false
          }
        },
        fail() {
          wx.showToast({
            icon: 'none',
            title: '登錄過期,請重新登錄',
          })
        },
      })
    },
    updateUserInfo: function () {
      return new Promise((resolve, reject) => {
        console.log('發送給后台的用戶信息', this.userInfo)
        wx.request({
          url: '后台提供的接口',
          method: 'POST',
          data: {
            openId: '',
            password: '',
            telePhone: '',
            tenantId: 0,
            username: '',
          },
          header: {
            'content-type': 'application/json', // 默認值
          },
          success(res) {
            console.log(333, res.data)
          },
        })
        wx.login({
          success(res) {
            resolve(res.code)
          },
          fail(err) {
            reject(err)
          },
        })
      })
    },
  },
}
</script>

<style>
.header {
  margin: 90rpx 0 90rpx 50rpx;
  border-bottom: 1px solid #ccc;
  text-align: center;
  width: 650rpx;
  height: 300rpx;
  line-height: 450rpx;
}

.header image {
  width: 240rpx;
  height: 240rpx;
  border-radius: 50%;
}

.content {
  margin-left: 50rpx;
  margin-bottom: 90rpx;
}

.content text {
  display: block;
  color: #9d9d9d;
  margin-top: 40rpx;
}

.btn {
  background: #1890FF !important;
  line-height: 80rpx !important;
  border-radius: 80rpx !important;
  margin: 70rpx 50rpx !important;
  font-size: 35rpx !important;
}
</style>

 

  

注:1. background: url 無法使用靜態資源,可以使用線上資源或者數據流(base64等),在線圖片庫(https://www.superbed.cn/)

  2.分包:文件資源過大時,可使用分包加載 (https://www.cnblogs.com/cisum/p/10190245.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM