微信小程序微信登錄的實現方法詳解(JAVA後臺)
官方文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
本文主要記錄小程序實現微信登陸功能,後端為Java開發。
在開發之前我們先看一下官方提供的時序圖,瞭解一下我們的大致開發流程:
大致瞭解流程之後,我們便可以著手開發瞭。
1. 前提
一個可以測試的微信小程序
此微信小程序的APPID和APPscret(至開發者後臺獲取)
2. 開發流程
從時序圖我們可以瞭解到流程大致分為兩步:
- 小程序端獲取code後傳給Java後臺
- Java後臺獲取code後向微信後臺接口獲取open_id
2.1 小程序端
在微信小程序的前端調用wx.login()獲取一個code,這個code就像是我們去微信後臺服務器獲取用戶信息的一個鑰匙,微信通過獲取這個code的過程給用戶一個選擇是否授權的選擇,如果用戶選擇瞭授權就會返回一個code。這個code是一次性的,也是有時限的。由於我在Java後臺進行瞭一次數據校驗,所以我也會從getUserInfo接口中獲取相關數據。代碼如下:
2.2 Java後端接口
後端的流程我將其大致分為如下幾點:
- 接收小程序發送的code
- 開發者服務器 登錄憑證校驗接口 appi + appsecret + code
- 接收微信接口服務 獲取返回的參數
- 校驗簽名 小程序發送的簽名signature與服務器端生成的簽名signature2 = sha1(rawData + sessionKey)
- 根據返回的User實體類,判斷用戶是否是新用戶,是的話,將用戶信息存到數據庫;
獲取openId
後臺接受瞭code以後通過建立一個http請求去訪問微信後臺服務器拉取這個用戶的openid,如果一切正常就會得到這個用戶對應這個小程序的openid。
請求的地址:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
通過GET方式訪問,其中的參數分別是:
- appid:小程序的appid
- secret:小程序的appsecret
- js:小程序前端傳來的code
- grant_type:這個不用修改,表示授權的類型
請求工具類代碼如下:(APPID自行替換)
public class WechatUtil { public static JSONObject getSessionKeyOrOpenId(String code) { String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; Map<String, String> requestUrlParam = new HashMap<>(); // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN //小程序appId requestUrlParam.put("appid", WXConstant.APPID); //小程序secret requestUrlParam.put("secret", WXConstant.SECRET); //小程序端返回的code requestUrlParam.put("js_code", code); //默認參數 requestUrlParam.put("grant_type", "authorization_code"); //發送post請求讀取調用微信接口獲取openid用戶唯一標識 JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam)); return jsonObject; } }
HTTP工具類如下:
需要添加相關依賴。
<!-- http請求工具包依賴 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>
public class HttpClientUtil { public static String doGet(String url, Map<String, String> param) { // 創建Httpclient對象 CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response = null; try { // 創建uri URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); // 創建http GET請求 HttpGet httpGet = new HttpGet(uri); // 執行請求 response = httpclient.execute(httpGet); // 判斷返回狀態是否為200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doGet(String url) { return doGet(url, null); } public static String doPost(String url, Map<String, String> param) { // 創建Httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創建Http Post請求 HttpPost httpPost = new HttpPost(url); // 創建參數列表 if (param != null) { List<NameValuePair> paramList = new ArrayList<>(); for (String key : param.keySet()) { paramList.add(new BasicNameValuePair(key, param.get(key))); } // 模擬表單 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); httpPost.setEntity(entity); } // 執行http請求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doPost(String url) { return doPost(url, null); } public static String doPostJson(String url, String json) { // 創建Httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創建Http Post請求 HttpPost httpPost = new HttpPost(url); // 創建請求內容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 執行http請求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } }
接口代碼
具體代碼如下所示:
判斷用戶是否存在後的代碼根據自己的業務邏輯進行修改即可。
@PostMapping("/wx/login") public R user_login(@RequestParam(value = "code", required = false) String code, @RequestParam(value = "rawData", required = false) String rawData, @RequestParam(value = "signature", required = false) String signature) { // 用戶非敏感信息:rawData // 簽名:signature JSONObject rawDataJson = JSON.parseObject(rawData); // 1.接收小程序發送的code // 2.開發者服務器 登錄憑證校驗接口 appi + appsecret + code JSONObject SessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(code); // 3.接收微信接口服務 獲取返回的參數 String openid = SessionKeyOpenId.getString("openid"); String sessionKey = SessionKeyOpenId.getString("session_key"); // 4.校驗簽名 小程序發送的簽名signature與服務器端生成的簽名signature2 = sha1(rawData + sessionKey) String signature2 = DigestUtils.sha1Hex(rawData + sessionKey); if (!signature.equals(signature2)) { return R.error().message("簽名校驗失敗"); } // 5.根據返回的User實體類,判斷用戶是否是新用戶,是的話,將用戶信息存到數據庫; LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery(); lqw.eq(User::getOpenId, openid); User user = userService.getOne(lqw); if (user == null) { // 用戶信息入庫 String nickName = rawDataJson.getString("nickName"); String avatarUrl = rawDataJson.getString("avatarUrl"); user = new User(); user.setOpenId(openid); user.setAvatar(avatarUrl); user.setNickName(nickName); userService.save(user); } return R.ok().data(user); }
總結
到此這篇關於微信小程序微信登錄實現的文章就介紹到這瞭,更多相關微信小程序微信登錄內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 解決HttpPost+json請求—服務器中文亂碼及其他問題
- Java中生成微信小程序太陽碼的實現方案
- Java HttpClient用法的示例詳解
- HttpClient詳細使用示例代碼
- 使用HTTPclient保持長連接