1. 程式人生 > >微信開放平臺PC端掃碼登入功能個人總結

微信開放平臺PC端掃碼登入功能個人總結

最近公司給我安排一個微信登入的功能,需求是這樣的:

  1.登入授權

    點選二維碼圖示後,登入介面切換為如下樣式(二維碼),微信掃描二維碼並授權,即可成功登入;

       若當前賬號未繫結微信賬號,掃描後提示“您的賬號未繫結微訊號,請先登入繫結”;

       點選“返回”按鈕,介面切換為賬號密碼登入;

          若微訊號繫結多個賬號在,則展示所繫結全部賬號的使用者名稱和企業名,選擇賬號後點擊登入按鈕成功登入;

   2.掃描繫結

     賬號登入後檢測當前賬號open_id為空,則展示當前彈窗(001管理員賬號除外);

               使用者微信掃描二維碼後,將當前微訊號繫結至對應賬號;

          若微訊號之前繫結其他賬號,則對應open_id下增加一個賬號;

   3.個人資料

     新增一個'微訊號'欄位:顯示賬號是否繫結

 

好,現在整理邏輯,理清思路,畫圖:

  宣告一下,PC端的微信掃碼登入是微信開放平臺,移動端關注是跳轉第三方應用的,用的是公眾平臺,兩個的介面地址拿的openId不一樣,開放平臺下面如果建立多個應用或者繫結多個公眾號,各公眾號之間用unionId打通。

openId和unionId區別:http://www.25xt.com/html5css3/11968.html

  公司或者企業在開發前  登入微信開放平臺,註冊認證,建立一個應用(應用就是你的專案,產品,不知道就直接讓產品幫你註冊認證,一般需要一個禮拜時間審批+300人民幣,完了拿到AppId和AppSecret)

 

  自己的本地環境要對映到外網,那樣微信才能訪問到自己介面來。推薦使用ngrok,不會的網上有教程,我的是直接讓人幫我配的。

  準備工作做好,開始開發:

     第一步:根據文件生成二維碼(開放平臺 --> 資源中心 --> 網站應用 --> 微信登入功能 --> 網站應用微信登入開發指南)

   我這裡不需要生成整個頁面,而是在一個div裡生成,所以用js生成:

    1.在頁面中先引入如下JS檔案(支援https):

      <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

    2.在需要使用微信登入的地方例項以下JS物件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

var obj = new WxLogin({

 

                              id:"login_container",    //div的id

 

                              appid: "",

 

                              scope: "",

 

                              redirect_uri: "",        //回撥地址

 

                              state: "",         //引數,可帶可不帶

 

                              style: "",         //樣式  提供"black"、"white"可選,預設為黑色文字描述

 

                              href: ""                 //自定義樣式連結,第三方可根據實際需求覆蓋預設樣式。

 

                            });

 

這裡生成的二維碼供使用者掃描,掃描成功,移動端出現授權頁面,需使用者確認。

回撥地址裡面的域名要在開放平臺去配:

二維碼就生成好了,可以看看效果,還沒調樣式:

再來看授權步驟:

第一步,獲取code。

  呼叫介面:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect;

  介面中引數如下:

自己程式碼:

複製程式碼

 1 @Override
 2     public Map<String, String> weixinLoginUrl() {
 3         String url = "https://open.weixin.qq.com/connect/qrconnect?appid=" + openPlatformAppId + "&redirect_uri="
 4                 + URL.encode("'"+ openPlatformRedirect_uri +"'/getWxLoginCode") + "&response_type=code" + "&scope=snsapi_login"
 5                 + "&state=STATE#wechat_redirect";
 6         Map<String, String> map = new HashMap<String, String>();
 7         map.put("url", url);
 8         map.put("getRedirect_uri", openPlatformRedirect_uri);    //openPlatformRedirect_uri為配置檔案裡的域名(開放平臺配好的) 
 9      return map; 
10 }

複製程式碼

解釋程式碼:

  openPlatformAppId為自己的AppId,

  openPlatformRedirect_uri為自己配的域名,(請忽略我的方法命名和引數命名...別學我!)

這裡提一下,登入的scope=snsapi_login,公眾平臺裡scope有userInfo(使用者有感知)和baseInfo(使用者無感知,靜默授權)

返回給controller,controller重新請求一遍地址,這時候進入的是微信回撥地址了,裡面就會有code引數,根據code引數就可以拿access_token了,controller程式碼:

複製程式碼

1 @RequestMapping(value = "/wxLoginCheck", method = RequestMethod.GET)
2     @ResponseBody
3     public String wxLoginCheck() {
4         Map<String, String> weixinLoginUrl = alarmWxMessageService.weixinLoginUrl();
5         String url = weixinLoginUrl.get("url");
6         return "<script>location.href='" + url + "'</script>";
7     }

複製程式碼

這時候return的回撥地址變成了第一步回撥地址引數的那個地址("/getWxLoginCode"),域名沒寫了

第二步,通過code獲取access_token

  呼叫介面:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code;

  介面中引數如下:

  

自己程式碼:

controller:

1 @RequestMapping(value = "/getWxLoginCode", method = RequestMethod.GET)
2     public String getWxLoginCode(String code) {
3         WeixinOauth2Token wxot=alarmWxMessageService.wxLogingetCode(code);
4         String openId = wxot.getOpenId();
5         String accessToken = wxot.getAccessToken();
6     }

解釋程式碼:

  code直接能拿到了,WeixinOauth2Token 為實體類,封裝openId和access_token之類欄位

serviceImpl:

複製程式碼

 1 @Override
 2     public WeixinOauth2Token wxLogingetCode(String code) {
 3         WeixinOauth2Token wat = null;
 4         String getTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + openPlatformAppId
 5                 + "&secret=" + openPlatformAppSecret
 6                 + "&code=" + code
 7                 + "&grant_type=authorization_code";
 8         // 獲取網頁授權憑證
 9         JSONObject jsonObject = JSONObject.fromObject(HttpUtil.Get(getTokenUrl));
10         if (jsonObject != null) {
11             try {
12                 wat = new WeixinOauth2Token();
13                 wat.setAccessToken(jsonObject.getString("access_token"));
14                 wat.setOpenId(jsonObject.getString("openid"));15             } catch (Exception e) {
16                 wat = null;
17                 int errorCode = jsonObject.getInt("errorCode");
18                 String errorMsg = jsonObject.getString("errorMsg");
19                 log.error("獲取網頁授權失敗errorCode=" + errorCode + ",errorMsg=" + errorMsg);
20             }
21         }
22         return wat;
23     }

複製程式碼

解釋程式碼:

  openPlatformAppId為自己的AppId,

  openPlatformAppSecret為自己的密碼,

  code為之前獲取到的code,

  json那一段是重新發送一個get請求,方法在HttpUtil裡封裝的,下面貼出。

複製程式碼

 1 /**
 2      * 向指定URL傳送GET方法的請求
 3      *
 4      * @param url   傳送請求的URL
 5      * @param param 請求引數,請求引數應該是 name1=value1&name2=value2 的形式。
 6      * @return URL 所代表遠端資源的響應結果
 7      */
 8     public static String Get(String url) {
 9         int connectionTimeOut=HTTP_CONNECTION_TIMEOUT,  readTimeOut =HTTP_READ_TIMEOUT;
10         String result = "";
11         BufferedReader in = null;
12         String urlNameString = url;
13         try {
14             logger.info("請求url+引數:" + urlNameString);
15             URL realUrl = new URL(urlNameString);
16             // 開啟和URL之間的連線
17             URLConnection connection = realUrl.openConnection();
18             // 設定通用的請求屬性
19             connection.setRequestProperty("accept", "*/*");
20             connection.setRequestProperty("connection", "Keep-Alive");
21             connection.setConnectTimeout(connectionTimeOut);
22             connection.setReadTimeout(readTimeOut);
23             // 建立實際的連線
24             connection.connect();
25             // 獲取所有響應頭欄位
26             // 定義 BufferedReader輸入流來讀取URL的響應
27             in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
28             String line;
29             while ((line = in.readLine()) != null) {
30                 result += line;
31             }
32         } catch (Exception e) {
33             logger.error("傳送GET請求出現異常!url: " + urlNameString + ", " + e);
34         }
35         // 使用finally塊來關閉輸入流
36         finally {
37             try {
38                 if (in != null) {
39                     in.close();
40                 }
41             } catch (Exception e2) {
42                 logger.error("close exception", e2);
43             }
44         }
45         return result;
46     }

複製程式碼

到這裡,已經授權完了,能拿到使用者的openId,用這個去完成公司相關業務。文件上面的重新整理access_token沒有做,自己可以去了解下

後來做完了,推送訊息那邊要拿我這個openId,才發現,登入是開放平臺的,推送訊息是公眾平臺的,平臺都不一樣,openId肯定不一樣,所以又重新開發一遍登入,什麼東西都是自己實現。。。。。。

注意:unionId,統一管理多個公眾號或者多個應用而產生的一個機制,像這次開發的,開放平臺和公眾平臺不能用這個

個人總結一下,開發一個東西之前,思路一定要理清,不然會繞來繞去把自己繞暈,技術都不是問題,重要的是思路;

程式碼部分,命名符合規範,讓人看的懂是什麼意思,註釋也要全,讓人明白寫的什麼;

登入模組要好好研究一下,呼叫登入方法去登入,實現的原理和登入時安全問題要考慮到;

技術上新用ModelMap這個物件,後臺儲存:map.put("名字","值"),前臺直接拿:var corpUsers = '${requestScope.名字}';

List Map json 互相轉換、傳值、接收值;

重發請求的GET、POST方法;

spring重定向、jsp重定向等。

 微信ui地址:https://weui.io/

開發小白,如果有錯誤的地方盡請大佬們指出,謝謝