1. 程式人生 > >微信開放平臺開發第三方授權登陸(五):第三方登陸授權開發(微信小程式)

微信開放平臺開發第三方授權登陸(五):第三方登陸授權開發(微信小程式)

 開發小程式需要在公眾平臺註冊一個小程式賬號,然後獲取到小程式的AppID和AppSecret。就可以進行第三方登陸授權開發。

一、需求

擁有第三方微信登入功能,並獲取到使用者資訊。

二、開發流程

小程式:

1. 微信小程式通過wx.login API進行登入獲取code。由於AppID和AppSecret不能洩露給使用者,根據code獲取openid需要在服務端完成,所以需要將code傳送給服務端

(服務端),並且帶上授權臨時票據code引數;

2. 服務端通過code和appid、APPSecret獲取到openid和SessionKey。服務端需要返回自定義登入態給前端,不能返回SessionKey

3. 前端儲存自定義登入態,獲取使用者資訊時攜帶自定義登入態給後端。

獲取Token的流程

三、開發使用的技術及工具

1、.後端採用IDEA2017 進行開發

2、前端使用微信開發者工具V1.02進行開發

3、使用fastJson對json資料進行處理

1.前端(小程式)

目錄結構如下:

1)自定義的全域性變數

globalData: {

    userInfo: null,

    sessionkey:null

  }

自定義userInfo用於儲存使用者資訊

sessionKey用於儲存服務端發回給客戶端的sessionkey

2)index載入時進行登入

使用者登入後,服務端會返回一個sessionkey給客戶端儲存,如果為空,說明沒有登入過,需要呼叫wx.login進行登入。

呼叫wx.login後,微信會返回一個code給小程式,小程式需要通過這個code傳送給自身的服務端來獲取sessionkey和openid資訊。

onLoad: function() {

    var serverUrl = app.serverUrl;

    // 載入時,檢查當前使用者資訊是否登入

    if (app.globalData.sessionkey != null) { // 已經登入了

      // 是否授權

      wx.getSetting({

        success: function(res) {

          if (res.authSetting['scope.userInfo']) {

            // 已經授權,可以直接呼叫 getUserInfo 獲取頭像暱稱

            wx.getUserInfo({

              success: function(res) {

                app.globalData.userInfo = JSON.parse(res.rawData);

              }

            })

          } else {

            // 還沒有授權,則需要授權

            wx.redirectTo({

              url: '../authorization/authorization'

            })

          }

        }

      })

    } else { // 還沒有登入

      // 提示使用者登入授權

      wx.login({

        success: res => {

          // 傳送 res.code 到後臺換取 openId, sessionKey, unionId

          if (res.code) {

            // 傳送請求,服務端能獲取到openid和unionid,之前登入過則可以獲取到之前的使用者資訊。

            wx.request({

              url: serverUrl + '/miniprogram/login/' + res.code, //請求路徑

              method: "GET",

              success: function(res) {

                app.globalData.sessionkey = res.data;

                // 進入授權

                wx.redirectTo({

                  url: '../authorization/authorization'

                })

              }

            })

          }

        }

      })

    }

},

登入成功後,重定向到授權頁面

3)授權頁面authorization.wxml

<view class='tag-title'>

  <image mode="widthFix" style=' width: 200rpx;height: 200rpx;margin-top:150rpx' src="/images/logo.jpg"></image>

</view>

<view wx:if="{{canIUse}}">

  <view style='text-align:center;margin-top:50rpx'>

    允許微信授權後,可體驗更多功能</view>

  <view>

    <button open-type='getUserInfo' bindgetuserinfo="bindGetUserInfo" >授權登入</button>

    <button bindtap='navigateBack'>返回首頁</button>

  </view>

</view>

<view wx:else style='text-align:center;margin-top:50rpx'>

  您的微信版本過低,請升級後再次體驗</view>

Button的open-type為getUserInfo時,點選後會呼叫bindgetuserinfo屬性配置的函式,同時帶上使用者基本資訊(不包括Openid等)

4)使用者資訊傳送給後端

// 授權登入按鈕

  bindGetUserInfo: function(e) {

    let that = this;

    var serverUrl = app.serverUrl;

    console.log(e.detail.userInfo)

    if (e.detail.userInfo) {  // 成功獲取到資訊

      app.globalData.userInfo = e.detail.userInfo

      // 這裡可以將使用者資訊傳送給後臺

      // 獲取到sessionkey

      if (app.globalData.sessionkey!=null){

        wx.request({

          url: serverUrl + '/miniprogram/userinfo', //請求路徑,

          method: "GET",

          data: {

            // openid: this.openid,

            // unionid: this.unionid,

            key: app.globalData.sessionkey,

            nickname: app.globalData.userInfo.nickName, //獲取暱稱

            gender: app.globalData.userInfo.gender, //獲取性別

            province: app.globalData.userInfo.province, //獲取省份

            city: app.globalData.userInfo.city, //獲取城市

            country: app.globalData.userInfo.country, //獲取國家

            avatarUrl: app.globalData.userInfo.avatarUrl, //這些是使用者的基本資訊

            language: app.globalData.userInfo.language

          },

          success: function (res) {

            if (res.data.code == 0) {  // 請求成功

              debugger

              app.globalData.userInfo = res.data.data; // 以資料庫中返回的資料為準

              // 獲取使用者資訊成功

              wx.switchTab({

                url: '../mine/mine'

              })

            }

          }

        })

      }else{

        this.showZanTopTips('錯誤:SessionKey為null');

      }



    } else {

      this.showZanTopTips('您拒絕了微信授權');

    }

  },



}));

獲取使用者資訊成功後,頁面跳轉到mine中顯示使用者詳情資訊

5)使用者詳情頁mine.wxml

<view class="container more">

  <view class="userinfo">

    <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>

    <text class="userinfo-nickname">{{userInfo.nickName}}</text>

          <text class="userinfo-nickname">性別:{{userInfo.gender === 1 ? '男':'女'}}</text>

          <text class="userinfo-nickname">城市:{{userInfo.city}}</text>

          <text class="userinfo-nickname">省份:{{userInfo.province}}</text>

          <text class="userinfo-nickname">國家:{{userInfo.country}}</text>

          <text class="userinfo-nickname">使用語言:{{userInfo.language}}</text>

  </view>

</view>

2.服務端(Java)

服務端需要做的是:接受小程式前端傳送的請求,根據傳送過來的code,以及服務端儲存的AppId和APPSecret等向微信服務端傳送請求,獲取到sessionkey和openid,然後將二者關聯起來儲存到session儲存器中(Redis),返回給前端key值。

接受小程式傳送過來的key和使用者基本資訊,根據key從redis中獲取openid,然後對資料庫進行查詢,若存在資料則封裝後返回給前端,若無資訊則向資料庫中插入資料並返回給前端。

1).配置檔案新增小程式相關配置

wechar.miniprogram.appid =

wechar.miniprogram.appsecret =

2)獲取openid以及Sessionkey

@ResponseBody

    @RequestMapping("/login/{code}")

    public String login(@PathVariable("code") String code) {

        String url = "https://api.weixin.qq.com/sns/jscode2session?" +

                "appid=" +

                env.getProperty("wechar.miniprogram.appid") +

                "&secret=" +

                env.getProperty("wechar.miniprogram.appsecret") +

                "&js_code=" +

                code +

                "&grant_type=authorization_code";

        JSONObject object = HttpClientUtils.httpGet(url);

        // 請求,獲取openid或unionid

        // 從資料庫中查詢是否儲存

        // 成功獲取

        String unionid = (String) object.get("unionid");

        String openid = (String) object.get("openid");//使用者唯一標識

        // 會話金鑰session_key 是對使用者資料進行加密簽名的金鑰。為了應用自身的資料安全,開發者伺服器不應該把會話金鑰下發到小程式,也不應該對外提供這個金鑰。

        String session_key = (String) object.get("session_key");

        String key = "wecharminiprogramkey-" + UUID.randomUUID().toString().replaceAll("-", "");

        RedisPoolUtil.setEx(key, openid + "---" + session_key, 9600);

        return key;

}

3).獲取使用者資訊:

小程式能夠獲取使用者基本資訊,但是不包括openid等資訊,僅有基本的暱稱等資訊,需要通過後端傳輸的key作為標識傳送到前端,然後找到對應的openid來獲取。

@ResponseBody

@RequestMapping(value = "/userinfo", method = RequestMethod.GET) // 獲取使用者資訊

public Result getOpenId(String key, MiniProgramBaseUserInfo miniProgramBaseUserInfo) {

        MiniProgramBaseUserInfo result = null;

        String value = RedisPoolUtil.get(key);

        if (value != null) {

            String values[] = value.split("---");

            String openid = values[0];

            // 從資料庫中查詢是否儲存(根據openid查詢)

            result = null; // TODO: 這裡是查資料庫操作

            if (result == null){ // 資料庫中沒有資料

                // TODO: 向資料庫中執行插入操作

                // insert  weCharUserInfo

                result = miniProgramBaseUserInfo;

            }

            return Result.success(result);

        return Result.error(SESSION_KEY_OVER_TIME); // SessionKey失效

    }