最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot + UniApp對(duì)接微信OAuth2登錄的全過(guò)程

 更新時(shí)間:2025年11月29日 10:07:08   作者:z晨晨  
現(xiàn)在小程序逐漸成為主流,常用的微信授權(quán)登錄很重要很常見(jiàn)的一個(gè)功能,這篇文章主要介紹了使用SpringBoot + UniApp對(duì)接微信OAuth2登錄的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

本文將手把手帶你打通SpringBoot后端與UniApp前端的微信登錄全流程,并分享那些官方文檔沒(méi)寫(xiě)的實(shí)戰(zhàn)經(jīng)驗(yàn)。

前期準(zhǔn)備

在開(kāi)始編碼前,這些準(zhǔn)備工作必須到位

  • 微信開(kāi)放平臺(tái)賬號(hào)(個(gè)人/企業(yè)均可)
  • 已審核通過(guò)的移動(dòng)應(yīng)用(審核通常需要1-3個(gè)工作日)
  • 獲取AppID和AppSecret(這是微信登錄的“身份證”)

特別注意:微信登錄權(quán)限需要單獨(dú)申請(qǐng),通過(guò)審核后才能正常使用!

前端實(shí)戰(zhàn):Uniapp一鍵登錄按鈕

關(guān)鍵代碼實(shí)現(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)不獲取用戶(hù)信息
        });
        
        // 調(diào)用后端登錄接口
        const res = await uni.request({
          url: "你的后端地址/weChatLogin", // 記得換成你的實(shí)際地址!
          method: 'POST',
          data: { socialCode: loginRes.code }
        });
        
        if (res.data.token) {
          // 登錄成功處理
          uni.showToast({ title: '登錄成功!', icon: 'success' });
        } else {
          // 需要綁定手機(jī)號(hào)
          this.goToBindPhone();
        }
      } catch (error) {
        uni.showToast({ title: '登錄失敗,請(qǐng)重試', icon: 'none' });
      }
    }
  }
}
</script>

核心要點(diǎn):

  • onlyAuthorize: true 參數(shù)確保符合微信規(guī)范
  • 異常捕獲必不可少,網(wǎng)絡(luò)請(qǐng)求總有意外
  • token為空時(shí)的處理:跳轉(zhuǎn)手機(jī)號(hào)綁定頁(yè)面

后端開(kāi)發(fā):Springboot接收與處理

后端的核心使命:安全驗(yàn)證 + 用戶(hù)管理 + 令牌發(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) -> 獲取用戶(hù)信息 -> 生成令牌
        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);
        
        // 錯(cuò)誤處理絕不能少!
        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("獲取微信用戶(hù)信息失?。? + 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ù)邏輯層:用戶(hù)存在就登錄,不存在就創(chuàng)建
public String weChatLogin(Map<String, String> userInfo) {
    // 用unionid查詢(xún)用戶(hù)
    SysUser user = userService.selectUserByOpenId(userInfo.get("unionid"));//這里可以根據(jù)自己的業(yè)務(wù)框架來(lái)處理
    
    if (user == null) {
        // 新用戶(hù):自動(dòng)注冊(cè)
        user = createNewUser(userInfo);
        userService.insertUser(user);//這里可以根據(jù)自己的業(yè)務(wù)框架來(lái)處理
    }
    
    // 未綁定手機(jī)號(hào)?引導(dǎo)綁定
    if (StringUtils.isBlank(user.getPhonenumber())) {
        return ""; // 前端根據(jù)空token跳轉(zhuǎn)綁定頁(yè)面
    }
    
    // 執(zhí)行登錄,生成token
    return performLogin(user.getPhonenumber());//這里可以根據(jù)自己的業(yè)務(wù)框架來(lái)處理
}

核心概念解析:openid vs unionid

很多開(kāi)發(fā)者在這里踩坑,其實(shí)很簡(jiǎn)單:

  • openid:用戶(hù)在單個(gè)應(yīng)用內(nèi)的身份證(同一個(gè)用戶(hù)在不同應(yīng)用openid不同)
  • unionid:用戶(hù)在微信開(kāi)放平臺(tái)體系的身份證(同一用戶(hù)在不同應(yīng)用unionid相同)

簡(jiǎn)單理解:openid是部門(mén)工號(hào),unionid是公司工號(hào)

手機(jī)號(hào)綁定

重要提醒:微信官方已限制獲取用戶(hù)手機(jī)號(hào)!我們的解決方案:

  1. 自動(dòng)檢測(cè):用戶(hù)首次微信登錄后,檢測(cè)是否已綁定手機(jī)
  2. 友好引導(dǎo):token為空時(shí),前端跳轉(zhuǎn)到綁定頁(yè)面
  3. 簡(jiǎn)化流程:只需驗(yàn)證碼即可完成綁定

參考代碼:

@PostMapping("/bindPhoneNumber")
public AjaxResult bindPhoneNumber(@RequestBody LoginBodyBindPhone loginBody) {
    // 驗(yàn)證碼校驗(yàn) + 綁定手機(jī)號(hào)
    String token = loginService.bindPhoneNumber(loginBody);
    return AjaxResult.success().put(Constants.TOKEN, token);
}
@Data
public class LoginBodyBindPhone {

    @Schema(description = "手機(jī)號(hào)")
    private String phonenumber;
    @Schema(description = "微信用戶(hù)統(tǒng)一標(biāo)識(shí)")
    private String unionid;
    @Schema(description = "驗(yàn)證碼")
    private String code;
}

微信登錄對(duì)接就像搭積木——步驟固定,但細(xì)節(jié)決定成敗。掌握核心流程(獲取code → 換取token → 獲取用戶(hù)信息 → 業(yè)務(wù)處理),你就能應(yīng)對(duì)各種場(chǎng)景。

總結(jié)

到此這篇關(guān)于SpringBoot + UniApp對(duì)接微信OAuth2登錄的文章就介紹到這了,更多相關(guān)SpringBoot UniApp對(duì)接微信OAuth2登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SprintBoot深入淺出講解場(chǎng)景啟動(dòng)器Starter

    SprintBoot深入淺出講解場(chǎng)景啟動(dòng)器Starter

    本篇文章將和大家分享一下 Spring Boot 框架中的 Starters 場(chǎng)景啟動(dòng)器的內(nèi)容,關(guān)于 Starters 具體是用來(lái)做什么的,以及在開(kāi)發(fā) Spring Boot項(xiàng)目前,要如何自定義一個(gè) Starters 場(chǎng)景啟動(dòng)器
    2022-06-06
  • Mybatis和Mybatis-Plus時(shí)間范圍查詢(xún)方式

    Mybatis和Mybatis-Plus時(shí)間范圍查詢(xún)方式

    這篇文章主要介紹了Mybatis和Mybatis-Plus時(shí)間范圍查詢(xún)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Hive與HBase之間的區(qū)別及使用方式

    Hive與HBase之間的區(qū)別及使用方式

    本文介紹了Hive和HBase的區(qū)別,Hive是基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)工具,不支持實(shí)時(shí)數(shù)據(jù)處理;HBase是一種分布式的、可擴(kuò)展、支持海量數(shù)據(jù)存儲(chǔ)的NoSQL數(shù)據(jù)庫(kù),適用于實(shí)時(shí)數(shù)據(jù)處理,兩者都是基于HDFS的,Hive用于批處理,不支持隨機(jī)寫(xiě)
    2026-04-04
  • springcloud?nacos動(dòng)態(tài)線(xiàn)程池Dynamic?tp配置接入實(shí)戰(zhàn)詳解

    springcloud?nacos動(dòng)態(tài)線(xiàn)程池Dynamic?tp配置接入實(shí)戰(zhàn)詳解

    這篇文章主要為大家介紹了springcloud?nacos動(dòng)態(tài)線(xiàn)程池Dynamic?tp配置接入實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Java并發(fā)編程volatile關(guān)鍵字的作用

    Java并發(fā)編程volatile關(guān)鍵字的作用

    這篇文章主要介紹了Java并發(fā)編程volatile關(guān)鍵字的作用,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java讀取傳輸FTP文件實(shí)現(xiàn)示例

    Java讀取傳輸FTP文件實(shí)現(xiàn)示例

    本文主要介紹了Java讀取傳輸FTP文件方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • MyBatis Mapper代理使用方法詳解

    MyBatis Mapper代理使用方法詳解

    本文是小編日常收集整理的關(guān)于mybatis mapper代理使用方法知識(shí),通過(guò)本文還給大家提供有關(guān)開(kāi)發(fā)規(guī)范方面的知識(shí)點(diǎn),本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看下吧
    2016-08-08
  • Java多線(xiàn)程之多種鎖和阻塞隊(duì)列

    Java多線(xiàn)程之多種鎖和阻塞隊(duì)列

    今天帶大家學(xué)習(xí)的是Java多線(xiàn)程的相關(guān)知識(shí),文章圍繞著java多種鎖和阻塞隊(duì)列展開(kāi),文中有非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-06-06
  • java實(shí)現(xiàn)后臺(tái)圖片跨域上傳功能

    java實(shí)現(xiàn)后臺(tái)圖片跨域上傳功能

    這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)后臺(tái)圖片跨域上傳功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • 關(guān)于SpringGateway調(diào)用服務(wù) 接受不到參數(shù)問(wèn)題

    關(guān)于SpringGateway調(diào)用服務(wù) 接受不到參數(shù)問(wèn)題

    這篇文章主要介紹了關(guān)于SpringGateway調(diào)用服務(wù)接受不到參數(shù)問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論

深水埗区| 邓州市| 江油市| 广宁县| 绥阳县| 甘南县| 历史| 青浦区| 太保市| 栾城县| 天祝| 宁晋县| 镇宁| 漳州市| 同仁县| 清新县| 兴城市| 威信县| 如皋市| 枣庄市| 梁平县| 柳江县| 吉安市| 哈巴河县| 尖扎县| 舟山市| 榕江县| 玉龙| 蒙山县| 勃利县| 闻喜县| 曲松县| 曲靖市| 新闻| 清水县| 孝昌县| 额济纳旗| 鄱阳县| 石城县| 长武县| 东港市|