首先說(shuō)一下這個(gè)微信掃碼登錄它的方式有兩種,一種是基于網(wǎng)頁(yè)的redirect實(shí)現(xiàn),一種是基于公眾號(hào)推送消息實(shí)現(xiàn),二者實(shí)現(xiàn)的效果是不一樣的
基于公眾號(hào)推送消息實(shí)現(xiàn)的掃碼登錄
貼一個(gè)官方文檔
前期準(zhǔn)備
- 需要有自己的域名(這里你可以使用內(nèi)網(wǎng)穿透,會(huì)生成一個(gè)自己的域名,網(wǎng)上一大堆,自己奧利給吧)
- 需要申請(qǐng)微信認(rèn)證(如果你是我這種情況,那么同是天涯淪落人,往下走)
- 這一步需要具備以上條件,否則沒(méi)什么用(上面沒(méi)有的就繼續(xù)下)
如上圖,獲取到appid,appsecret(項(xiàng)目中會(huì)用到)之后,再將服務(wù)器配置修改并啟用就可以了,
*服務(wù)器配置中的token到底怎么配置
微信官方文檔公眾號(hào)介入指南說(shuō)明(里面有一個(gè)PHP示例代碼下載,其實(shí)這里不止PHP的)
上面的是微信文檔說(shuō)明,下面一定要注意,很關(guān)鍵
- 首先說(shuō)一下URL,這個(gè)URL是微信服務(wù)器需要使用get方式請(qǐng)求的你的路徑,其次它是白名單的(當(dāng)你配置攔截器或過(guò)濾器或AOP的時(shí)候)。這個(gè)get請(qǐng)求僅僅是驗(yàn)證token的。
- 其次是token,這里的token可以隨意填寫,但是你的程序中的token必須與這個(gè)保持一致(這里就是訪問(wèn)你上面URL的接口中的token)
- 代碼實(shí)現(xiàn)如下:這里的代碼實(shí)現(xiàn)在下面貼
使用測(cè)試號(hào)
配置的話和上面一樣的操作
代碼實(shí)現(xiàn)
maven坐標(biāo)
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-open</artifactId>
<version>3.8.0</version>
</dependency>
配置類實(shí)現(xiàn)
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaobo
* @date 2023/4/10
*/
@Configuration
public class WeChatCodeConfig {
@Value("${wx.appid}")
private String appId;
@Value("${wx.appsecret}")
private String appSecret;
/**
* 定義WxMpService bean
*/
@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
config.setAppId(appId);
config.setSecret(appSecret);
wxMpService.setWxMpConfigStorage(config);
return wxMpService;
}
}
上面的wx.appid,wx.appsecret是定義到配置文件中的,是在前期準(zhǔn)備的第三點(diǎn)中獲取到的
獲取登錄二維碼
@PostMapping("/getLoginQrCode")
@ResponseBody
public RespResult getLoginQrCode() throws WxErrorException, UnsupportedEncodingException {
// 設(shè)置場(chǎng)景id,登錄的時(shí)候需要根據(jù)這個(gè)獲取redis中存在的openid
String sceneStr = IdUtil.getSnowflake().nextIdStr();
WxMpQrCodeTicket wxMpQrCodeTicket = wxService.getQrcodeService().qrCodeCreateTmpTicket(sceneStr, 3600);
// 這里獲取到的是二維碼,前端只需要用<img>標(biāo)簽中的src接收就可以展示
String s = wxService.getQrcodeService().qrCodePictureUrl(wxMpQrCodeTicket.getTicket());
return RespResult.success(s, sceneStr);
}
上面的實(shí)現(xiàn)建議可以再做一步redis存一個(gè)有過(guò)期時(shí)間的key,防止后面一直輪詢調(diào)用
前端輪詢回調(diào)實(shí)現(xiàn)登錄
@PostMapping("wechatOpenIdLogin")
@ResponseBody
public RespResult wechatOpenIdLogin(String sceneStr, HttpServletRequest request) {
// 這里的sceneStr是上面接口返回的,這步操作是微信事件推送之后會(huì)存一個(gè)redis
Boolean exists = JedisUtil.exists(sceneStr);
if (exists) {
// TODO 業(yè)務(wù)操作,其中JedisUtil.getStr(sceneStr)能得到微信掃碼用戶的openid
return weChatCodeService.wechatLogin(JedisUtil.getStr(sceneStr), request);
} else {
return RespResult.fail(sceneStr);
}
}
微信事件推送接口實(shí)現(xiàn)
@RequestMapping("/sign")
public void sign(HttpServletResponse response, HttpServletRequest request) throws Exception {
String method = request.getMethod();
// 微信加密簽名
String signature = request.getParameter("signature");
// 隨機(jī)字符串
String echostr = request.getParameter("echostr");
// 時(shí)間戳
String timestamp = request.getParameter("timestamp");
// 隨機(jī)數(shù)
String nonce = request.getParameter("nonce");
// 簽名驗(yàn)證是get請(qǐng)求
if ("GET".equals(method)) {
String[] str = {"123456token", timestamp, nonce};
// 字典排序
Arrays.sort(str);
String bigStr = str[0] + str[1] + str[2];
// SHA1加密
String digest = sha1(bigStr);
// 確認(rèn)請(qǐng)求來(lái)至微信
if (digest.equals(signature)) {
response.getWriter().print(echostr);
}
} else {
// 獲取WxMpXmlMessage
WxMpXmlMessage wxMpXmlMessage = WxMpXmlMessage.fromXml(request.getInputStream());
// OpenId
String fromUserName = wxMpXmlMessage.getFromUser();
// 消息類型,event
final String msgType = wxMpXmlMessage.getMsgType();
// 事件類型
final String event = wxMpXmlMessage.getEvent();
String sceneStr = "";
log.error("微信返回驗(yàn)簽是:{},{},{}", msgType, event, fromUserName);
if (WxConsts.XmlMsgType.EVENT.equals(msgType)) {
if (event.equals(WxConsts.EventType.SUBSCRIBE)) {
if (ticket != null) {
sceneStr = wxMpXmlMessage.getEventKey().replace("qrscene_", "");
}
}
//注:事件類型為SCAN即已關(guān)注
else if (event.equals(WxConsts.EventType.SCAN)) {
if (ticket != null) {
sceneStr = wxMpXmlMessage.getEventKey();
}
}
// 如果sceneStr不為空代表用戶已經(jīng)掃描并且關(guān)注了公眾號(hào)
if (CharSequenceUtil.isNotEmpty(sceneStr)) {
// 將微信公眾號(hào)用戶ID緩存到redis中,標(biāo)記用戶已經(jīng)掃碼完成,執(zhí)行登錄邏輯。
JedisUtil.setStr(sceneStr, fromUserName, OpenIdRedisExpireTime);
}
}
response.getWriter().write("可以隨便寫");
}
}
微信公眾號(hào)接收事件推送
基于轉(zhuǎn)發(fā)實(shí)現(xiàn)的掃碼登錄
這個(gè)和上面的不一樣,這個(gè)用微信官方來(lái)說(shuō)的話就是==網(wǎng)頁(yè)授權(quán)獲取用戶基本信息==
前期準(zhǔn)備
這里只需要獲取到appid,appsecret,還有一個(gè)就是配置服務(wù)器域名如下圖
代碼實(shí)現(xiàn)
接口實(shí)現(xiàn)
這里需要用到上面公眾號(hào)推送消息實(shí)現(xiàn)的->代碼實(shí)現(xiàn)->(maven坐標(biāo),配置類實(shí)現(xiàn))
/**
* 獲取微信掃碼登錄二維碼
*/
@RequestMapping("/getLoginQrCode")
public RespResult getLoginQrCode() throws WxErrorException {
// 重定向URl,這里必須配置公眾號(hào)對(duì)應(yīng)的域名
String redirectUrl = "http://localhost:8080/login";
// 這里只獲取用戶掃碼地址
String url = wxService.oauth2buildAuthorizationUrl(redirectUrl, WxConsts.OAuth2Scope.SNSAPI_BASE, null);
return RespResult.success(url);
}
/**
* 微信掃碼登錄
*/
@RequestMapping("wechatLogin")
public RespResult wechatLogin(@RequestParam("code") String code, HttpServletRequest request) {
return weChatCodeService.wechatLogin(code, request);
??: 注意,這里的url并不是一個(gè)二維碼,而是一個(gè)地址,如果你在瀏覽器中打開(kāi)的話,它會(huì)提示使用微信客戶端打開(kāi),所以這個(gè)就注定了他并非根本意義上的掃碼登錄,它僅僅是微信掃碼然后直接打開(kāi)你跳轉(zhuǎn)后的頁(yè)面,也就是你上面定義的重定向URI,如果你的網(wǎng)站是手機(jī)端和PC端都兼容,那么可以直接PC出碼,手機(jī)掃碼直接登錄。具體實(shí)現(xiàn)和上面的差不多,這里貼個(gè)圖,針對(duì)上面的接口。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-800795.html
畫的很丑,將就用吧文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-800795.html
到了這里,關(guān)于springboot整合微信(公眾號(hào))實(shí)現(xiàn)掃碼登錄(兩種方式,兩種實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!