微信回撥URL實戰
阿新 • • 發佈:2021-01-03
一準備
1httpclient工具類
package com.atguigu.guli.common.base.util; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.*; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * @className: HttpClientUtils * @description: http請求客戶端 * @date: 2021/1/2 * @author: cakin */ public class HttpClientUtils { private String url; private Map<String, String> param; private int statusCode; private String content; private String xmlParam; private boolean isHttps; public boolean isHttps() { return isHttps; } public void setHttps(boolean isHttps) { this.isHttps = isHttps; } public String getXmlParam() { return xmlParam; } public void setXmlParam(String xmlParam) { this.xmlParam = xmlParam; } public HttpClientUtils(String url, Map<String, String> param) { this.url = url; this.param = param; } public HttpClientUtils(String url) { this.url = url; } public void setParameter(Map<String, String> map) { param = map; } public void addParameter(String key, String value) { if (param == null) param = new HashMap<String, String>(); param.put(key, value); } public void post() throws ClientProtocolException, IOException { HttpPost http = new HttpPost(url); setEntity(http); execute(http); } public void put() throws ClientProtocolException, IOException { HttpPut http = new HttpPut(url); setEntity(http); execute(http); } public void get() throws ClientProtocolException, IOException { if (param != null) { StringBuilder url = new StringBuilder(this.url); boolean isFirst = true; for (String key : param.keySet()) { if (isFirst) { url.append("?"); isFirst = false; }else { url.append("&"); } url.append(key).append("=").append(param.get(key)); } this.url = url.toString(); } HttpGet http = new HttpGet(url); execute(http); } /** * set http post,put param */ private void setEntity(HttpEntityEnclosingRequestBase http) { if (param != null) { List<NameValuePair> nvps = new LinkedList<NameValuePair>(); for (String key : param.keySet()) nvps.add(new BasicNameValuePair(key, param.get(key))); // 引數 http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 設定引數 } if (xmlParam != null) { http.setEntity(new StringEntity(xmlParam, Consts.UTF_8)); } } private void execute(HttpUriRequest http) throws ClientProtocolException, IOException { CloseableHttpClient httpClient = null; try { if (isHttps) { SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, new TrustStrategy() { // 信任所有 public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext); httpClient = HttpClients.custom().setSSLSocketFactory(sslsf) .build(); } else { httpClient = HttpClients.createDefault(); } CloseableHttpResponse response = httpClient.execute(http); try { if (response != null) { if (response.getStatusLine() != null) statusCode = response.getStatusLine().getStatusCode(); HttpEntity entity = response.getEntity(); // 響應內容 content = EntityUtils.toString(entity, Consts.UTF_8); } } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { httpClient.close(); } } public int getStatusCode() { return statusCode; } public String getContent() throws ParseException, IOException { return content; } }
2pom依賴
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
二獲取access_token
/** * 功能描述:阿里雲對本地的回撥 * * @param code 認證code * @param state 認證狀態 * @param session session * @return * @author cakin * @date 2021/1/2 * @description: */ @GetMapping("callback") public String callback(String code, String state, HttpSession session) { System.out.println("callback被呼叫"); System.out.println("code:" + code); System.out.println("state:" + state); if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) { log.error("非法回撥請求"); throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR); } String sessionState = (String) session.getAttribute("wx_open_state"); if (!state.equals(sessionState)) { log.error("非法回撥請求"); throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR); } // 攜帶code臨時票據,和appid以及appsecret請求access_token和openid(微信唯一標識) String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; //組裝引數:?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code Map<String, String> accessTokenParam = new HashMap<>(); accessTokenParam.put("appid", ucenterProperties.getAppId()); accessTokenParam.put("secret", ucenterProperties.getAppSecret()); accessTokenParam.put("code", code); accessTokenParam.put("grant_type", "authorization_code"); HttpClientUtils client = new HttpClientUtils(accessTokenUrl, accessTokenParam); String result; try { // 傳送請求:組裝完整的url字串、傳送請求 client.get(); // 得到響應 result = client.getContent(); System.out.println("result = " + result); } catch (Exception e) { log.error("獲取access_token失敗"); throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD); } Gson gson = new Gson(); HashMap<String, Object> resultMap = gson.fromJson(result, HashMap.class); // 失敗的響應結果 Object errcodeObj = resultMap.get("errcode"); if (errcodeObj != null) { Double errcode = (Double) errcodeObj; String errmsg = (String) resultMap.get("errmsg"); log.error("獲取access_token失敗:" + "code:" + errcode + ", message:" + errmsg); throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD); } // 成功響應:解析出結果中的access_token和openid String accessToken = (String) resultMap.get("access_token"); String openid = (String) resultMap.get("openid"); System.out.println("accessToken:" + accessToken); System.out.println("openid:" + openid); return null; }
三獲取使用者資訊
1根據openid查詢使用者是否已註冊
介面
/**
* 功能描述:根據openid查詢使用者是否已註冊
*
* @author cakin
* @date 2021/1/2
* @param openid openid
* @return Member 使用者資訊
*/
Member getByOpenid(String openid);
實現
/** * 功能描述:根據openid查詢使用者是否已註冊 * * @param openid openid * @return Member 使用者資訊 * @author cakin * @date 2021/1/2 */ @Override public Member getByOpenid(String openid) { QueryWrapper<Member> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("openid", openid); return baseMapper.selectOne(queryWrapper); }
2根據access_token獲取使用者資訊
/**
* 功能描述:阿里雲對本地的回撥
*
* @param code 認證code
* @param state 認證狀態
* @param session session
* @return
* @author cakin
* @date 2021/1/2
* @description:
*/
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
......
// 在本地資料庫中查詢當前微信使用者的資訊
Member member = memberService.getByOpenid(openid);
// 沒有註冊情況
if (member == null) {
// 如果當前使用者不存在,則去微信的資源伺服器獲取使用者個人資訊(攜帶access_token)
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo";
// 組裝引數:?access_token=ACCESS_TOKEN&openid=OPENID
Map<String, String> baseUserInfoParam = new HashMap<>();
baseUserInfoParam.put("access_token", accessToken);
baseUserInfoParam.put("openid", openid);
client = new HttpClientUtils(baseUserInfoUrl, baseUserInfoParam);
String resultUserInfo = "";
try {
client.get();
resultUserInfo = client.getContent();
} catch (Exception e) {
log.error(ExceptionUtils.getMessage(e));
throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
HashMap<String, Object> resultUserInfoMap = gson.fromJson(resultUserInfo, HashMap.class);
// 失敗的響應結果
errcodeObj = resultUserInfoMap.get("errcode");
if (errcodeObj != null) {
Double errcode = (Double) errcodeObj;
String errmsg = (String) resultMap.get("errmsg");
log.error("獲取使用者資訊失敗:" + "code:" + errcode + ", message:" + errmsg);
throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
// 解析出結果中的使用者個人資訊
String nickname = (String) resultUserInfoMap.get("nickname");
String avatar = (String) resultUserInfoMap.get("headimgurl");
Double sex = (Double) resultUserInfoMap.get("sex");
// 在本地資料庫中插入當前微信使用者的資訊(使用微信賬號在本地伺服器註冊新使用者)
member = new Member();
member.setOpenid(openid);
member.setNickname(nickname);
member.setAvatar(avatar);
member.setSex(sex.intValue());
memberService.save(member);
}
// 則直接使用當前使用者的資訊登入(生成jwt)
// member =>Jwt
JwtInfo jwtInfo = new JwtInfo();
jwtInfo.setId(member.getId());
jwtInfo.setNickname(member.getNickname());
jwtInfo.setAvatar(member.getAvatar());
String jwtToken = JwtUtils.getJwtToken(jwtInfo, 1800);
return "redirect:http://localhost:3000?token=" + jwtToken;
}
四前端整合
// 頁面渲染之後執行:可以有window物件
mounted() {
const token = this.$route.query.token
if (token) {
// 將jwt寫入cookie
cookie.set('guli_jwt_token', token, { domain: 'localhost' })
window.location.href = '/'
}
},