本文轉載自:https://blog.csdn.net/qq_34190023/article/details/82351505
開發小程序需要在公眾平台注冊一個小程序賬號,然后獲取到小程序的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).配置文件新增小程序相關配置
wechat.miniprogram.appid =
wechat.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("wechat.miniprogram.appid") + "&secret=" + env.getProperty("wechat.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 = "wechatminiprogramkey-" + 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 weChatUserInfo result = miniProgramBaseUserInfo; } return Result.success(result); return Result.error(SESSION_KEY_OVER_TIME); // SessionKey失效 }