微信登錄模塊封裝

文章目錄

    • 1.資質申請
    • 2.combinations-wx-login-starter
        • 1.目錄結構
        • 2.pom.xml 引入okhttp依賴
        • 3.WxLoginProperties.java 屬性配置
        • 4.WxLoginUtil.java 后端通過 code 獲取 access_token的工具類
        • 5.WxLoginAutoConfiguration.java 自動配置類
        • 6.spring.factories 激活自動配置類
    • 3.combinations-wx-starter-demo
        • 1.目錄結構
        • 2.pom.xml 引入依賴
        • 3.application.yml 配置AppID和AppSecret
        • 4.application-prod.yml 配置生產環境的日志和.env文件路徑
        • 5.CodeAndState.java 接受code和state的bean
        • 6.WxLoginController.java 微信登錄Controller
        • 7.WxApplication.java 啟動類
    • 4.微信登錄流程梳理
        • 1.用戶點擊微信登錄按鈕
        • 2.前端向開放平臺發送請求主要攜帶appId和redirectUri
        • 3.此時開放平臺會彈出一個掃碼的頁面,用戶掃碼確認
        • 4.用戶確認成功后,開放平臺會將code和state作為參數去請求redirectUri(前端頁面)
        • 5.前端頁面獲取code和state,再向后端發送請求
        • 6.后端使用code進行微信登錄,可以獲取到AccessTokenResponse

1.資質申請

  1. 主體為企業的域名和備案的服務器
  2. 主體為企業的微信開放平臺的開發者資質認證
  3. 微信開放平臺創建應用獲取AppID和AppSecret

2.combinations-wx-login-starter

1.目錄結構

CleanShot 2025-01-23 at 21.17.45@2x

2.pom.xml 引入okhttp依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-combinations</artifactId><version>1.0.0</version></parent><artifactId>combinations-wx-login-starter</artifactId><!-- 項目名 --><name>${project.groupId}:${project.artifactId}</name><!-- 簡單描述 --><description>微信登錄模塊封裝</description><dependencies><!-- okhttp --><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></dependency></dependencies>
</project>
3.WxLoginProperties.java 屬性配置
package cn.sunxiansheng.wx.login.config.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** Description: 微信登錄的屬性配置** @Author sun* @Create 2025/1/23 18:49* @Version 1.0*/
@ConfigurationProperties(prefix = "sun-rays.wx.login")
@Data
public class WxLoginProperties {/*** 微信開放平臺應用的AppID*/private String appId;/*** 微信開放平臺應用的AppSecret*/private String appSecret;/*** 微信開放平臺的access_token_url前綴,有默認值,可以不填,為了防止變化!*/private String accessTokenUrlPrefix = "https://api.weixin.qq.com/sns/oauth2/access_token";
}
4.WxLoginUtil.java 后端通過 code 獲取 access_token的工具類
package cn.sunxiansheng.wx.login.utils;import cn.sunxiansheng.wx.login.config.properties.WxLoginProperties;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;import javax.annotation.Resource;/*** Description: 微信登錄工具類** @Author sun* @Create 2025/1/23 19:01* @Version 1.0*/
@Slf4j
public class WxLoginUtil {/*** 獲取微信登錄的配置*/@Resourceprivate WxLoginProperties wxLoginProperties;/*** 微信登錄的響應類*/@Datapublic static class AccessTokenResponse {@SerializedName("access_token")private String accessToken;@SerializedName("expires_in")private Integer expiresIn;@SerializedName("refresh_token")private String refreshToken;@SerializedName("openid")private String openId;@SerializedName("scope")private String scope;@SerializedName("unionid")private String unionId;}/*** 根據code來完成微信登錄** @param code 微信開放平臺返回的code* @return 返回AccessTokenResponse*/public AccessTokenResponse wxLogin(String code) {return getAccessToken(wxLoginProperties.getAppId(), wxLoginProperties.getAppSecret(), code);}/*** 后端通過 code 獲取 access_token** @param appid  微信應用的 appid* @param secret 微信應用的 secret* @param code   后端已經獲得的 code 參數* @return 返回封裝的 AccessTokenResponse 對象*/private AccessTokenResponse getAccessToken(String appid, String secret, String code) {// 構造請求 URLString url = String.format("%s?appid=%s&secret=%s&code=%s&grant_type=authorization_code",wxLoginProperties.getAccessTokenUrlPrefix(), appid, secret, code);// 創建 OkHttpClient 實例OkHttpClient client = new OkHttpClient();// 創建 Request 對象Request request = new Request.Builder().url(url).build();// 執行請求并處理響應try (Response response = client.newCall(request).execute()) {// 檢查請求是否成功if (!response.isSuccessful()) {String responseBody = response.body() != null ? response.body().string() : "響應體為空";log.error("后端通過 code 獲取 access_token 的請求失敗,響應碼:{}, 響應體:{}", response.code(), responseBody);return null;}// 打印成功的響應String jsonResponse = response.body() != null ? response.body().string() : "響應體為空";log.info("成功獲取 access_token,響應:{}", jsonResponse);// 使用 Gson 解析 JSON 數據并封裝成 AccessTokenResponse 對象Gson gson = new Gson();// 返回封裝的對象return gson.fromJson(jsonResponse, AccessTokenResponse.class);} catch (Exception e) {log.error(e.getMessage(), e);// 返回 null 或者其他錯誤處理return null;}}
}
5.WxLoginAutoConfiguration.java 自動配置類
package cn.sunxiansheng.wx.login.config;import cn.sunxiansheng.wx.login.config.properties.WxLoginProperties;
import cn.sunxiansheng.wx.login.utils.WxLoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;/*** Description: 微信登錄自動配置類** @Author sun* @Create 2025/1/13 16:11* @Version 1.0*/
@Configuration
@EnableConfigurationProperties({WxLoginProperties.class})
@Slf4j
public class WxLoginAutoConfiguration {/*** 自動配置成功日志*/@PostConstructpublic void logConfigSuccess() {log.info("WxLoginAutoConfiguration has been loaded successfully!");}/*** 注入WxLoginUtil** @return*/@Bean@ConditionalOnMissingBeanWxLoginUtil wxLoginUtil() {return new WxLoginUtil();}
}
6.spring.factories 激活自動配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.sunxiansheng.wx.login.config.WxLoginAutoConfiguration

3.combinations-wx-starter-demo

1.目錄結構

CleanShot 2025-01-23 at 21.25.48@2x

2.pom.xml 引入依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-combinations-demo</artifactId><version>1.0.0</version></parent><artifactId>combinations-wx-starter-demo</artifactId><dependencies><!-- combinations-wx-login-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>combinations-wx-login-starter</artifactId><version>1.0.0</version></dependency><!-- common-web-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId><version>1.0.0</version></dependency></dependencies><!-- maven 打包常規配置 --><build><!-- 打包成 jar 包時的名字為項目的artifactId + version --><finalName>${project.artifactId}-${project.version}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!-- 引用父模塊中統一管理的插件版本(與SpringBoot的版本一致! --><executions><execution><goals><!-- 將所有的依賴包都打到這個模塊中 --><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>
3.application.yml 配置AppID和AppSecret
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-combinations-demo/combinations-wx-starter-demo/logs # 日志存儲根目錄env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-combinations-demo/combinations-wx-starter-demo # .env文件的絕對路徑wx:login:app-id: ${WX_LOGIN_APP_ID} # 微信開放平臺應用的AppIDapp-secret: ${WX_LOGIN_APP_SECRET} # 微信開放平臺應用的AppSecret
spring:profiles:active: prod # 激活的環境
4.application-prod.yml 配置生產環境的日志和.env文件路徑
sun-rays:log4j2:home: /www/wwwroot/sunrays-framework/logs # 日志存儲根目錄env:path: /www/wwwroot/sunrays-framework # .env文件的絕對路徑
5.CodeAndState.java 接受code和state的bean
package cn.sunxiansheng.wx.entity;import lombok.Data;/*** Description: 接受code和state的bean** @Author sun* @Create 2025/1/16 19:15* @Version 1.0*/@Data
public class CodeAndState {/*** 微信的code*/private String code;/*** 微信的state*/private String state;
}
6.WxLoginController.java 微信登錄Controller
package cn.sunxiansheng.wx.controller;import cn.sunxiansheng.wx.entity.CodeAndState;
import cn.sunxiansheng.wx.login.utils.WxLoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** Description: 微信登錄Controller** @Author sun* @Create 2025/1/13 16:26* @Version 1.0*/
@Slf4j
@RestController
@RequestMapping("/wx")
public class WxLoginController {@Resourceprivate WxLoginUtil wxLoginUtil;@RequestMapping("/test")public String test() {return "test";}/*** 微信登錄** @param codeAndState 前端傳過來的code和state* @return 返回unionId*/@RequestMapping("/login")public String login(@RequestBody CodeAndState codeAndState) {// 使用code來完成微信登錄WxLoginUtil.AccessTokenResponse accessTokenResponse = wxLoginUtil.wxLogin(codeAndState.getCode());if (accessTokenResponse == null) {log.error("accessToken is null");return "null";}// 獲取unionIdString unionId = accessTokenResponse.getUnionId();if (unionId == null) {log.error("unionId is null");return "null";}// 獲取unionIdreturn accessTokenResponse.getUnionId();}
}
7.WxApplication.java 啟動類
package cn.sunxiansheng.wx;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: 微信啟動類** @Author sun* @Create 2025/1/13 17:54* @Version 1.0*/
@SpringBootApplication
public class WxApplication {public static void main(String[] args) {SpringApplication.run(WxApplication.class, args);}
}

4.微信登錄流程梳理

1.用戶點擊微信登錄按鈕

CleanShot 2025-01-23 at 21.36.20@2x

2.前端向開放平臺發送請求主要攜帶appId和redirectUri
<template><button @click="handleLogin" class="wechat-login-button">微信登錄</button>
</template><script>
export default {methods: {handleLogin() {// 從環境變量中獲取參數const appId = import.meta.env.VITE_APP_ID; // 從環境變量中讀取 appIdconst redirectUri = encodeURIComponent(import.meta.env.VITE_REDIRECT_URI); // 從環境變量中讀取 redirectUriconst responseType = 'code';const scope = 'snsapi_login'; // 網頁應用固定填寫 snsapi_login// 生成一個隨機的 state 參數,用于防止 CSRF 攻擊const state = Math.random().toString(36).substring(2); // 或者使用更安全的方式生成一個隨機字符串// 拼接請求URL,并加入 state 參數const wechatLoginUrl = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirectUri}&response_type=${responseType}&scope=${scope}&state=${state}#wechat_redirect`;// 跳轉到微信登錄頁面window.location.href = wechatLoginUrl;},},
};
</script><style scoped>
.wechat-login-button {background-color: #1aad19;color: white;border: none;border-radius: 5px;padding: 10px 20px;cursor: pointer;transition: background-color 0.3s ease;
}.wechat-login-button:hover {background-color: #128c13;
}
</style>
3.此時開放平臺會彈出一個掃碼的頁面,用戶掃碼確認

CleanShot 2025-01-23 at 21.36.33@2x

4.用戶確認成功后,開放平臺會將code和state作為參數去請求redirectUri(前端頁面)

CleanShot 2025-01-23 at 21.36.47@2x

5.前端頁面獲取code和state,再向后端發送請求
<template><div class="login-container"><div class="loading-spinner"></div><p class="loading-text">微信登錄中,請稍候...</p></div>
</template><script>
export default {async mounted() {const urlParams = new URLSearchParams(window.location.search);const code = urlParams.get("code");const state = urlParams.get("state");if (!code) {console.error("未獲取到微信返回的 code");alert("登錄失敗,請重試");return;}try {const response = await fetch("/wx/login", {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify({ code, state }),});const result = await response.json();if (result.success) {const unionid = result.data;alert(`登錄成功,您的unionid是:${unionid}`);this.$router.push({ path: "/products" });} else {alert("登錄失敗,請重試");}} catch (error) {console.error("請求失敗", error);alert("網絡錯誤,請稍后重試");}},
};
</script><style scoped>
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap");:root {--primary-color: #4facfe;--secondary-color: #00f2fe;--text-color: #333;
}.login-container {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100vh;background: linear-gradient(120deg, #ffffff, #f0f0f0);font-family: "Poppins", sans-serif;
}.loading-spinner {width: 60px;height: 60px;border: 6px solid #e0e0e0;border-top: 6px solid var(--primary-color);border-radius: 50%;animation: spin 1s linear infinite;
}@keyframes spin {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}
}.loading-text {margin-top: 20px;font-size: 18px;font-weight: 500;color: var(--text-color);animation: fadeIn 2s ease-in-out infinite alternate;
}@keyframes fadeIn {0% {opacity: 0.6;}100% {opacity: 1;}
}
</style>
6.后端使用code進行微信登錄,可以獲取到AccessTokenResponse
/*** 微信登錄的響應類*/
@Data
public static class AccessTokenResponse {@SerializedName("access_token")private String accessToken;@SerializedName("expires_in")private Integer expiresIn;@SerializedName("refresh_token")private String refreshToken;@SerializedName("openid")private String openId;@SerializedName("scope")private String scope;@SerializedName("unionid")private String unionId;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67729.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67729.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67729.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DeepSeek 介紹及對外國的影響

DeepSeek 簡介 DeepSeek&#xff08;深度求索&#xff09;是一家專注實現 AGI&#xff08;人工通用智能&#xff09;的中國科技公司&#xff0c;2023 年成立&#xff0c;總部位于杭州&#xff0c;在北京設有研發中心。與多數聚焦具體應用&#xff08;如人臉識別、語音助手&…

MySQL數據庫(二)- SQL

目錄 ?編輯 一 DDL (一 數據庫操作 1 查詢-數據庫&#xff08;所有/當前&#xff09; 2 創建-數據庫 3 刪除-數據庫 4 使用-數據庫 (二 表操作 1 創建-表結構 2 查詢-所有表結構名稱 3 查詢-表結構內容 4 查詢-建表語句 5 添加-字段名數據類型 6 修改-字段數據類…

ARM嵌入式學習--第十天(UART)

--UART介紹 UART(Universal Asynchonous Receiver and Transmitter)通用異步接收器&#xff0c;是一種通用串行數據總線&#xff0c;用于異步通信。該總線雙向通信&#xff0c;可以實現全雙工傳輸和接收。在嵌入式設計中&#xff0c;UART用來與PC進行通信&#xff0c;包括與監控…

面試題-消失的數字-異或

消失的數字 數組nums包含從0到n的所有整數&#xff0c;但其中缺了一個。請編寫代碼找出那個缺失的整數。你有辦法在 O(n) 時間內完成嗎&#xff1f; 示例&#xff1a; 輸入&#xff1a;[3,0,1] 輸出&#xff1a;2 int missingNumber(int* nums, int numsSize) {}分析 本題對…

數據結構與算法之棧: LeetCode 1685. 有序數組中差絕對值之和 (Ts版)

有序數組中差絕對值之和 https://leetcode.cn/problems/sum-of-absolute-differences-in-a-sorted-array/description/ 描述 給你一個 非遞減 有序整數數組 nums 請你建立并返回一個整數數組 result&#xff0c;它跟 nums 長度相同&#xff0c;且result[i] 等于 nums[i] 與數…

筆試-排列組合

應用 一個長度為[1, 50]、元素都是字符串的非空數組&#xff0c;每個字符串的長度為[1, 30]&#xff0c;代表非負整數&#xff0c;元素可以以“0”開頭。例如&#xff1a;[“13”, “045”&#xff0c;“09”&#xff0c;“56”]。 將所有字符串排列組合&#xff0c;拼起來組成…

Python3 OS模塊中的文件/目錄方法說明十七

一. 簡介 前面文章簡單學習了 Python3 中 OS模塊中的文件/目錄的部分函數。 本文繼續來學習 OS 模塊中文件、目錄的操作方法&#xff1a;os.walk() 方法、os.write()方法 二. Python3 OS模塊中的文件/目錄方法 1. os.walk() 方法 os.walk() 方法用于生成目錄樹中的文件名&a…

[Java]抽象類

1. 什么是抽象類&#xff1f; 1.1 定義&#xff1a; 抽象類是一個不能實例化的類&#xff0c;它是用來作為其他類的基類的。抽象類可以包含抽象方法和非抽象方法。抽象方法沒有方法體&#xff0c;子類必須重寫這些方法并提供具體的實現。抽象類可以有構造方法、成員變量、靜態…

css三角圖標

案例三角&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

跨越通信障礙:深入了解ZeroMQ的魅力

在復雜的分布式系統開發中&#xff0c;進程間通信就像一座橋梁&#xff0c;連接著各個獨立運行的進程&#xff0c;讓它們能夠協同工作。然而&#xff0c;傳統的通信方式往往伴隨著復雜的設置、高昂的性能開銷以及有限的靈活性&#xff0c;成為了開發者們前進道路上的 “絆腳石”…

深入解析 COUNT(DISTINCT) OVER(ORDER BY):原理、問題與高效替代方案

目錄 一、累計去重需求場景 二、COUNT(DISTINCT) OVER(ORDER BY) 語法解析 2.1 基礎語法 2.2 執行原理 三、三大核心問題分析

線性數據結構:單向鏈表

放棄眼高手低&#xff0c;你真正投入學習&#xff0c;會因為找到一個新方法產生成就感&#xff0c;學習不僅是片面的記單詞、學高數......只要是提升自己的過程&#xff0c;探索到了未知&#xff0c;就是學習。 目錄 一.鏈表的理解 二.鏈表的分類&#xff08;重點理解&#xf…

基于PyQt5打造的實用工具——PDF文件加圖片水印,可調大小位置,可批量處理!

01 項目簡介 &#xff08;1&#xff09;項目背景 隨著PDF文件在信息交流中的廣泛應用&#xff0c;用戶對圖片水印的添加提出了更高要求&#xff0c;既要美觀&#xff0c;又需高效處理批量文件。現有工具難以實現精確調整和快速批量操作&#xff0c;操作繁瑣且效果不理想。本項…

MCU內部ADC模塊誤差如何校準

本文章是筆者整理的備忘筆記。希望在幫助自己溫習避免遺忘的同時&#xff0c;也能幫助其他需要參考的朋友。如有謬誤&#xff0c;歡迎大家進行指正。 一、ADC誤差校準引言 MCU 片內 ADC 模塊的誤差總包括了 5 個靜態參數 (靜態失調&#xff0c;增益誤差&#xff0c;微分非線性…

嵌入式硬件篇---CPUGPUTPU

文章目錄 第一部分&#xff1a;處理器CPU&#xff08;中央處理器&#xff09;1.通用性2.核心數3.緩存4.指令集5.功耗和發熱 GPU&#xff08;圖形處理器&#xff09;1.并行處理2.核心數量3.內存帶寬4.專門的應用 TPU&#xff08;張量處理單元&#xff09;1.為深度學習定制2.低精…

03-機器學習-數據獲取

一、流行機器學習數據集 主流機器學習數據集匯總 數據集名稱描述來源MNIST手寫數字圖像數據集&#xff0c;由美國人口普查局員工書寫。MNIST官網ImageNet包含數百萬張圖像&#xff0c;用于圖像分類和目標檢測。ImageNet官網AudioSet包含YouTube音頻片段&#xff0c;用于聲音分…

doris:STRUCT

STRUCT<field_name:field_type [COMMENT comment_string], ... > 表示由多個 Field 組成的結構體&#xff0c;也可被理解為多個列的集合。 不能作為 Key 使用&#xff0c;目前 STRUCT 僅支持在 Duplicate 模型的表中使用。一個 Struct 中的 Field 的名字和數量固定&…

一次端口監聽正常,tcpdump無法監聽到指定端口報文問題分析

tcpdump命令&#xff1a; sudo tcpdump -i ens2f0 port 6471 -XXnnvvv 下面是各個部分的詳細解釋&#xff1a; 1.tcpdump: 這是用于捕獲和分析網絡數據包的命令行工具。 2.-i ens2f0: 指定監聽的網絡接口。ens2f0 表示本地網卡&#xff09;&#xff0c;即計算機該指定網絡接口捕…

“新月智能武器系統”CIWS,開啟智能武器的新紀元

新月人物傳記&#xff1a;人物傳記之新月篇-CSDN博客 相關文章鏈接&#xff1a;星際戰爭模擬系統&#xff1a;新月的編程之道-CSDN博客 新月智能護甲系統CMIA--未來戰場的守護者-CSDN博客 “新月之智”智能戰術頭盔系統&#xff08;CITHS&#xff09;-CSDN博客 目錄 智能武…

實驗六 項目二 簡易信號發生器的設計與實現 (HEU)

聲明&#xff1a;代碼部分使用了AI工具 實驗六 綜合考核 Quartus 18.0 FPGA 5CSXFC6D6F31C6N 1. 實驗項目 要求利用硬件描述語言Verilog&#xff08;或VHDL&#xff09;、圖形描述方式、IP核&#xff0c;結合數字系統設計方法&#xff0c;在Quartus開發環境下&#xff…