整合微信登入功能
功能介紹:
使用微信掃碼登入;
首先要了解一個技術棧:OAuth2技術
問題:我們用戶的賬號信息例如:用戶名,地址,頭像,等信息都是保存在騰訊的數據庫,我們應該如何訪問呢?
1.使用用戶的用戶名和密碼直接訪問去訪問騰訊的數據庫(但是風險極大,密碼可能會泄露,而且用戶也不愿意給我們)
2.通用開發者key(和騰訊一起開發一個可以共同訪問的公共鑰匙,但是不可能,騰訊不理你)
3.頒發令牌(OAuth2方式)
騰訊通過用戶授權,頒發一個token給你,你可以只用這個token訪問用戶在騰訊的賬號信息;
如何整合OAuth2:(微信有官方文檔)
首先你要去微信進行申請,但是需要商家才可以申請;
微信會給你提供兩個東西
訪問wx.open.app_id(id)、wx.open.redirect_ur(重定向地址):根據兩個信息可以在前端生成微信登入用的二維碼;
@GetMapping("getLoginParam")@ResponseBodypublic Result genQrConnect() {try {//返回給前端的map集合Map<String, Object> map = new HashMap<>();//二維碼的idmap.put("appid", wxed9954c01bb89b47);//固定參數(作用域)map.put("scope","snsapi_login");//重定向地址String wxOpenRedirectUrl = http://localhost:8160/api/ucenter/wx/callback;//修改編碼方法wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");map.put("redirect_uri",wxOpenRedirectUrl);//狀態就是當前時間map.put("state",System.currentTimeMillis()+"");return Result.ok(map);} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}} wx.open.app_id=wxed9954c01bb89b47 wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback#用戶掃碼成功后微信會根據重定向地址給你發送
code(臨時票據需要通過這個臨時票據訪問微信服務器得到用戶的openId和token令牌)
state? (狀態碼)
#接下來需要使用自己的HttpClientUtils工具對微信的服務進行訪問;
通過HttpClientUtils工具訪問微信的服務器訪問路徑
#https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code#微信服務器的固定地址+appid+secret+code+固定寫法;
#得到兩個值? 用戶的openId和token令牌
@GetMapping("callback")public String callback(String code,String state) {//第一步 獲取臨時票據 codeSystem.out.println("code:"+code);System.out.println("state"+state);//第二步 拿著code和微信id和秘鑰,請求微信固定地址 ,得到兩個值//使用code和appid以及appscrect換取access_token// %s 占位符StringBuffer baseAccessTokenUrl = new StringBuffer().append("https://api.weixin.qq.com/sns/oauth2/access_token").append("?appid=%s").append("&secret=%s").append("&code=%s").append("&grant_type=authorization_code");//調用String.format()完成占位符的字符串的拼接String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),ConstantWxPropertiesUtils.WX_OPEN_APP_ID,ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET,code);//使用httpclient請求這個地址try {//訪問微信服務器得到用戶的微信openId、token(令牌)String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);System.out.println("accesstokenInfo:"+accesstokenInfo);String access_token = jsonObject.getString("access_token");String openid = jsonObject.getString("openid");##
一般把openId存放進入數據庫,作為用戶的唯一標識,可以節省一次訪問;
#如果數據庫中沒有openId
再使用httpClientUtils訪問微信服務器得到用戶具體的數據
把用戶數據轉換成JSONObject對象
if(userInfo == null) {//第三步 拿著openid 和 access_token請求微信地址,得到掃描人信息String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=%s" +"&openid=%s";String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);//訪問微信的服務器String resultInfo = HttpClientUtils.get(userInfoUrl);System.out.println("resultInfo:"+resultInfo);//將用戶的信息轉換成為json對象JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);//解析用戶信息//用戶昵稱String nickname = resultUserInfoJson.getString("nickname");//用戶頭像String headimgurl = resultUserInfoJson.getString("headimgurl");#把數據存放到數據庫,重定向放回給前端顯示;
##這樣子就可以結束了,但是一般還可以添加綁定手機操作
前端已經得到用戶信息了再返回到這個頁面進行手機號綁定;
Map<String,String> map = new HashMap<>();String name = userInfo.getName();if(StringUtils.isEmpty(name)) {name = userInfo.getNickName();}if(StringUtils.isEmpty(name)) {name = userInfo.getPhone();}map.put("name", name);//判斷userInfo是否有手機號,如果手機號為空,返回openid//如果手機號不為空,返回openid值是空字符串//前端判斷:如果openid不為空,綁定手機號,如果openid為空,不需要綁定手機號if(StringUtils.isEmpty(userInfo.getPhone())) {map.put("openid", userInfo.getOpenid());} else {map.put("openid", "");}//使用jwt生成token字符串String token = JwtHelper.createToken(userInfo.getId(), name);map.put("token", token);//跳轉到前端頁面return "redirect:" + ConstantWxPropertiesUtils.YYGH_BASE_URL + "/weixin/callback?token="+map.get("token")+ "&openid="+map.get("openid")+"&name="+URLEncoder.encode(map.get("name"),"utf-8");} catch (Exception e) {e.printStackTrace();return null;}}####完整代碼:
package com.yygh.user.api;import com.alibaba.fastjson.JSONObject; import com.yygh.Result; import com.yygh.helper.JwtHelper; import com.yygh.model.user.UserInfo; import com.yygh.user.service.UserInfoService; import com.yygh.user.utils.ConstantWxPropertiesUtils; import com.yygh.user.utils.HttpClientUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map;/*** 對微信的操作* @author 便利店狗砸ha* 使用@Controller注解是為了完成醫院頁面跳轉*/ @Controller @RequestMapping("/api/ucenter/wx") public class WeixinApiController {@Autowiredprivate UserInfoService userInfoService;//生成微信掃描的二維碼//1 生成微信掃描二維碼//返回生成二維碼需要參數@GetMapping("getLoginParam")@ResponseBodypublic Result genQrConnect() {try {//返回給前端的map集合Map<String, Object> map = new HashMap<>();//二維碼的idmap.put("appid", ConstantWxPropertiesUtils.WX_OPEN_APP_ID);//固定參數(作用域)map.put("scope","snsapi_login");//重定向地址String wxOpenRedirectUrl = ConstantWxPropertiesUtils.WX_OPEN_REDIRECT_URL;//修改編碼方法wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");map.put("redirect_uri",wxOpenRedirectUrl);//狀態就是當前時間map.put("state",System.currentTimeMillis()+"");return Result.ok(map);} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}}@GetMapping("callback")public String callback(String code,String state) {//第一步 獲取臨時票據 codeSystem.out.println("code:"+code);System.out.println("state"+state);//第二步 拿著code和微信id和秘鑰,請求微信固定地址 ,得到兩個值//使用code和appid以及appscrect換取access_token// %s 占位符StringBuffer baseAccessTokenUrl = new StringBuffer().append("https://api.weixin.qq.com/sns/oauth2/access_token").append("?appid=%s").append("&secret=%s").append("&code=%s").append("&grant_type=authorization_code");//調用String.format()完成占位符的字符串的拼接String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),ConstantWxPropertiesUtils.WX_OPEN_APP_ID,ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET,code);//使用httpclient請求這個地址try {//訪問微信服務器得到用戶的微信openId、token(令牌)String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);System.out.println("accesstokenInfo:"+accesstokenInfo);//從返回字符串獲取兩個值 openid 和 access_tokenJSONObject jsonObject = JSONObject.parseObject(accesstokenInfo);String access_token = jsonObject.getString("access_token");String openid = jsonObject.getString("openid");//判斷數據庫是否存在微信的掃描人信息//根據openid判斷UserInfo userInfo = userInfoService.selectWxInfoOpenId(openid);//數據庫不存在微信信息if(userInfo == null) {//第三步 拿著openid 和 access_token請求微信地址,得到掃描人信息String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=%s" +"&openid=%s";String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);//訪問微信的服務器String resultInfo = HttpClientUtils.get(userInfoUrl);System.out.println("resultInfo:"+resultInfo);//將用戶的信息轉換成為json對象JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);//解析用戶信息//用戶昵稱String nickname = resultUserInfoJson.getString("nickname");//用戶頭像String headimgurl = resultUserInfoJson.getString("headimgurl");//獲取掃描人信息添加數據庫userInfo = new UserInfo();userInfo.setNickName(nickname);userInfo.setOpenid(openid);userInfo.setStatus(1);userInfo.setPhone("123");userInfoService.save(userInfo);}//返回name和token字符串Map<String,String> map = new HashMap<>();String name = userInfo.getName();if(StringUtils.isEmpty(name)) {name = userInfo.getNickName();}if(StringUtils.isEmpty(name)) {name = userInfo.getPhone();}map.put("name", name);//判斷userInfo是否有手機號,如果手機號為空,返回openid//如果手機號不為空,返回openid值是空字符串//前端判斷:如果openid不為空,綁定手機號,如果openid為空,不需要綁定手機號if(StringUtils.isEmpty(userInfo.getPhone())) {map.put("openid", userInfo.getOpenid());} else {map.put("openid", "");}//使用jwt生成token字符串String token = JwtHelper.createToken(userInfo.getId(), name);map.put("token", token);//跳轉到前端頁面return "redirect:" + ConstantWxPropertiesUtils.YYGH_BASE_URL + "/weixin/callback?token="+map.get("token")+ "&openid="+map.get("openid")+"&name="+URLEncoder.encode(map.get("name"),"utf-8");} catch (Exception e) {e.printStackTrace();return null;}} }總結
- 上一篇: iTab新标签页,一款个性化的浏览器起始
- 下一篇: MATLAB/simulink学习笔记(