SpringBoot + UniApp對接微信OAuth2登錄的全過程
本文將手把手帶你打通SpringBoot后端與UniApp前端的微信登錄全流程,并分享那些官方文檔沒寫的實戰(zhàn)經(jīng)驗。
前期準備
在開始編碼前,這些準備工作必須到位:
- 微信開放平臺賬號(個人/企業(yè)均可)
- 已審核通過的移動應(yīng)用(審核通常需要1-3個工作日)
- 獲取AppID和AppSecret(這是微信登錄的“身份證”)
特別注意:微信登錄權(quán)限需要單獨申請,通過審核后才能正常使用!
前端實戰(zhàn):Uniapp一鍵登錄按鈕
關(guān)鍵代碼實現(xiàn)
<template>
<view class="container">
<button class="wechat-btn" open-type="getUserInfo" @click="handleWechatLogin">
<uni-icons type="weixin" color="#fff" size="30"></uni-icons>
微信一鍵登錄
</button>
</view>
</template>
<script>
export default {
methods: {
async handleWechatLogin() {
try {
// 獲取微信授權(quán)碼
const loginRes = await uni.login({
provider: "weixin",
onlyAuthorize: true, // 關(guān)鍵參數(shù):僅授權(quán)不獲取用戶信息
});
// 調(diào)用后端登錄接口
const res = await uni.request({
url: "你的后端地址/weChatLogin", // 記得換成你的實際地址!
method: 'POST',
data: { socialCode: loginRes.code }
});
if (res.data.token) {
// 登錄成功處理
uni.showToast({ title: '登錄成功!', icon: 'success' });
} else {
// 需要綁定手機號
this.goToBindPhone();
}
} catch (error) {
uni.showToast({ title: '登錄失敗,請重試', icon: 'none' });
}
}
}
}
</script>
核心要點:
- onlyAuthorize: true 參數(shù)確保符合微信規(guī)范
- 異常捕獲必不可少,網(wǎng)絡(luò)請求總有意外
- token為空時的處理:跳轉(zhuǎn)手機號綁定頁面
后端開發(fā):Springboot接收與處理
后端的核心使命:安全驗證 + 用戶管理 + 令牌發(fā)放。
- 控制器層
@Tag(name = "微信登錄")
@RestController
public class SysLoginController {
@Autowired
private SysLoginService loginService;
@Operation(summary = "微信授權(quán)登錄")
@PostMapping("/weChatLogin")
public AjaxResult weChatLogin(@RequestBody LoginBodyWeChat loginBody) {
// 三步走:授權(quán) -> 獲取用戶信息 -> 生成令牌
Map<String, String> authResult = weiXinApiService.authorize(loginBody.getSocialCode());
Map<String, String> userInfo = weiXinApiService.getUserInfo(
authResult.get("access_token"),
authResult.get("openid")
);
String token = loginService.weChatLogin(userInfo);
// 返回令牌給前端
return AjaxResult.success()
.put(Constants.TOKEN, token)
.put("unionid", userInfo.get("unionid"));
}
}
- 微信API服務(wù)
@Component
public class WeiXinApiService {
public Map<String, String> authorize(String socialCode) {
String url = String.format(
"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
appid, secret, socialCode
);
String response = HttpUtil.get(url);
JSONObject jsonObject = JSONUtil.parseObj(response);
// 錯誤處理絕不能少!
if (jsonObject.containsKey("errcode")) {
throw new ServiceException("微信登錄失敗:" + jsonObject.get("errmsg"));
}
// 返回access_token和openid
return Map.of(
"access_token", jsonObject.getStr("access_token"),
"openid", jsonObject.getStr("openid")
);
}
public Map<String, String> getUserInfo(String accessToken, String openId) {
String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s",
accessToken, openId);
String response = HttpUtil.get(url);
JSONObject jsonObject = JSONUtil.parseObj(response);
if (jsonObject.containsKey("errcode")) {
throw new ServiceException("獲取微信用戶信息失?。? + jsonObject.get("errmsg"));
}
Map<String, String> result = new HashMap<>();
result.put("nickname", jsonObject.getStr("nickname"));
result.put("sex", jsonObject.getStr("sex"));
result.put("headimgurl", jsonObject.getStr("headimgurl"));
result.put("unionid", jsonObject.getStr("unionid"));
result.put("openid", jsonObject.getStr("openid"));
return result;
}
}
- 業(yè)務(wù)邏輯層:用戶存在就登錄,不存在就創(chuàng)建
public String weChatLogin(Map<String, String> userInfo) {
// 用unionid查詢用戶
SysUser user = userService.selectUserByOpenId(userInfo.get("unionid"));//這里可以根據(jù)自己的業(yè)務(wù)框架來處理
if (user == null) {
// 新用戶:自動注冊
user = createNewUser(userInfo);
userService.insertUser(user);//這里可以根據(jù)自己的業(yè)務(wù)框架來處理
}
// 未綁定手機號?引導綁定
if (StringUtils.isBlank(user.getPhonenumber())) {
return ""; // 前端根據(jù)空token跳轉(zhuǎn)綁定頁面
}
// 執(zhí)行登錄,生成token
return performLogin(user.getPhonenumber());//這里可以根據(jù)自己的業(yè)務(wù)框架來處理
}
核心概念解析:openid vs unionid
很多開發(fā)者在這里踩坑,其實很簡單:
- openid:用戶在單個應(yīng)用內(nèi)的身份證(同一個用戶在不同應(yīng)用openid不同)
- unionid:用戶在微信開放平臺體系的身份證(同一用戶在不同應(yīng)用unionid相同)
簡單理解:openid是部門工號,unionid是公司工號
手機號綁定
重要提醒:微信官方已限制獲取用戶手機號!我們的解決方案:
- 自動檢測:用戶首次微信登錄后,檢測是否已綁定手機
- 友好引導:token為空時,前端跳轉(zhuǎn)到綁定頁面
- 簡化流程:只需驗證碼即可完成綁定
參考代碼:
@PostMapping("/bindPhoneNumber")
public AjaxResult bindPhoneNumber(@RequestBody LoginBodyBindPhone loginBody) {
// 驗證碼校驗 + 綁定手機號
String token = loginService.bindPhoneNumber(loginBody);
return AjaxResult.success().put(Constants.TOKEN, token);
}
@Data
public class LoginBodyBindPhone {
@Schema(description = "手機號")
private String phonenumber;
@Schema(description = "微信用戶統(tǒng)一標識")
private String unionid;
@Schema(description = "驗證碼")
private String code;
}
微信登錄對接就像搭積木——步驟固定,但細節(jié)決定成敗。掌握核心流程(獲取code → 換取token → 獲取用戶信息 → 業(yè)務(wù)處理),你就能應(yīng)對各種場景。
總結(jié)
到此這篇關(guān)于SpringBoot + UniApp對接微信OAuth2登錄的文章就介紹到這了,更多相關(guān)SpringBoot UniApp對接微信OAuth2登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
eclipse/intellij idea 查看java源碼和注釋方法
下面小編就為大家?guī)硪黄猠clipse/intellij idea 查看java源碼和注釋方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
詳解spring cloud hystrix 請求合并collapsing
這篇文章主要介紹了詳解spring cloud hystrix 請求合并collapsing,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
Jackson反序列化@JsonFormat 不生效的解決方案
這篇文章主要介紹了Jackson反序列化@JsonFormat 不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08

