玩玩微信公衆號Java版之六:微信網頁受權

咱們常常會訪問一些網站,用微信登陸的時候須要用到受權,那麼微信網頁受權是怎麼一回事呢,一塊兒來看看吧!
 
 
官方的文檔有很詳細的說明,這裏就主要分析重要的幾點:
第一,網頁受權分類及說明:
一、以snsapi_base爲scope發起的網頁受權,是用來獲取進入頁面的用戶的openid的,而且是靜默受權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(每每是業務頁面)
二、以snsapi_userinfo爲scope發起的網頁受權,是用來獲取用戶的基本信息的。但這種受權須要用戶手動贊成,而且因爲用戶贊成過,因此無須關注,就可在受權後獲取該用戶的基本信息。
 
第二,網頁受權流程分爲四步:
一、引導用戶進入受權頁面贊成受權,獲取code 
二、經過code換取網頁受權access_token(與基礎支持中的access_token不一樣) 
三、若是須要,開發者能夠刷新網頁受權access_token,避免過時 
四、經過網頁受權access_token和openid獲取用戶基本信息(支持UnionID機制) 
 
瞭解到網頁受權的這些知識,下面就開始去實現吧~
 
開始的準備工做:在接口配置中,設置對應的回調域名,地址:「開發 - 接口權限 - 網頁服務 - 網頁賬號 - 網頁受權獲取用戶基本信息」的配置選項
因爲個人是我的,所以使用測試帳號的配置:

 

配置好了,就能夠進行開發了,首先來看一下具體的流程:html

 

 

其實不少功能點,前面已經實現過,只用改一下調用地址和參數便可。java

 首先,調用的定義連接:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirectjson

連接中須要使用urlEncode對連接進行處理,能夠在工具類中添加一個轉碼方法:api

 1     /**
 2      * 對URL地址進行EnCode處理
 3      * @param url
 4      * @return
 5      */
 6     public static String urlEnCode(String url)
 7     {
 8         String enCodedUrl = "";
 9 
10         try
11         {
12             enCodedUrl = URLEncoder.encode(url, "utf-8");
13         }
14         catch (UnsupportedEncodingException e)
15         {
16             // TODO Auto-generated catch block
17             e.printStackTrace();
18             System.out.println("轉碼失敗!");
19         }
20 
21         return enCodedUrl;
22     }
View Code

另外將其餘參數補充完整,能夠獲得一個訪問連接。 數組

在這裏,能夠結合以前學的菜單的處理,能夠定義一個菜單進行專門的受權驗證,這裏須要改造上一節學到的點,具體以下:微信

 1     /**
 2      * 定義菜單屬性
 3      * @return
 4      */
 5     private Menu getMenu()
 6     {
 7         Menu menu = new Menu();
 8 
 9         // 建3個導航菜單
10         LevelMenu tLevelMenuOne = new LevelMenu();
11         tLevelMenuOne.setName("Damon");
12         LevelMenu tLevelMenuTwo = new LevelMenu();
13         tLevelMenuTwo.setName("Panou");
14         LevelMenu tLevelMenuThree = new LevelMenu();
15         tLevelMenuThree.setName("Papaw");
16 
17         // 第一個導航菜單的子菜單
18         SubMenuButton tSubMenuButton_oneone = new SubMenuButton();
19         tSubMenuButton_oneone.setType(SysCon.WECHAT_MENU_TYPE_VIEW);
20         tSubMenuButton_oneone.setName("網頁受權");
21         tSubMenuButton_oneone.setKey("11");
22         tSubMenuButton_oneone.setUrl(getAuthorUrl());
23 
24         SubMenuButton tSubMenuButton_onetwo = new SubMenuButton();
25         tSubMenuButton_onetwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
26         tSubMenuButton_onetwo.setName("swimming");
27         tSubMenuButton_onetwo.setKey("12");
28 
29         // 加入導航菜單
30         tLevelMenuOne.setSub_button(new SubMenuButton[]
31         { tSubMenuButton_oneone, tSubMenuButton_onetwo });
32 
33         // 第二 個導航菜單的子菜單
34         SubMenuButton tSubMenuButton_twoone = new SubMenuButton();
35         tSubMenuButton_twoone.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
36         tSubMenuButton_twoone.setName("watching TV");
37         tSubMenuButton_twoone.setKey("21");
38 
39         SubMenuButton tSubMenuButton_twotwo = new SubMenuButton();
40         tSubMenuButton_twotwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
41         tSubMenuButton_twotwo.setName("play games");
42         tSubMenuButton_twotwo.setKey("22");
43 
44         SubMenuButton tSubMenuButton_twothree = new SubMenuButton();
45         tSubMenuButton_twothree.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
46         tSubMenuButton_twothree.setName("shopping");
47         tSubMenuButton_twothree.setKey("23");
48 
49         // 加入導航菜單
50         tLevelMenuTwo.setSub_button(new SubMenuButton[]
51         { tSubMenuButton_twoone, tSubMenuButton_twotwo, tSubMenuButton_twothree });
52 
53         // 第三個導航菜單的子菜單
54         SubMenuButton tSubMenuButton_threeone = new SubMenuButton();
55         tSubMenuButton_threeone.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
56         tSubMenuButton_threeone.setName("cring");
57         tSubMenuButton_threeone.setKey("31");
58 
59         SubMenuButton tSubMenuButton_threetwo = new SubMenuButton();
60         tSubMenuButton_threetwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
61         tSubMenuButton_threetwo.setName("laughing");
62         tSubMenuButton_threetwo.setKey("32");
63 
64         // 加入導航菜單
65         tLevelMenuThree.setSub_button(new SubMenuButton[]
66         { tSubMenuButton_threeone, tSubMenuButton_threetwo });
67 
68         menu.setButton(new MenuButton[]
69         { tLevelMenuOne, tLevelMenuTwo, tLevelMenuThree });
70 
71         return menu;
72 
73     }
74 
75     /**
76      * 獲取微信網頁受權頁面連接
77      * @return
78      */
79     private String getAuthorUrl()
80     {
81         String uri = "http://damonhouse.iok.la/Servlet/WeChatAuthorService";
82 
83         uri = WeChatUtil.urlEnCode(uri);
84 
85         String authorUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
86 
87         authorUrl = authorUrl.replace("APPID", "appid").replace("REDIRECT_URI", uri).replace("SCOPE", "snsapi_userinfo");
88 
89         return authorUrl;
90     }
View Code

先看一下具體效果:app

點擊會彈出一個受權的頁面(因爲我已經受權過,因此這裏會自動登陸)jsp

 

這個時候後臺尚未對應的處理,咱們須要進行返回頁面的處理,這裏定義對應的service類,在doGet方法中進行處理:ide

 1 /**
 2  * 微信受權接口類
 3  * @author Damon
 4  */
 5 public class WeChatAuthorService extends HttpServlet
 6 {
 7 
 8     @Override
 9     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
10     {
11         // TODO Auto-generated method stub
12         System.out.println("受權成功,進行返回處理!");
13         req.setCharacterEncoding("utf-8");
14         resp.setCharacterEncoding("utf-8");
15 
16         String code = req.getParameter("code");
17 
18         String state = req.getParameter("state");
19 
20         System.out.println("code :" + code + " and stat :" + state);
21 
22         // 業務處理,獲取受權用戶信息
23         WeChatAuthorBL tWeChatAuthorBL = new WeChatAuthorBL();
24         AuthorUserInfo tAuthorUserInfo = tWeChatAuthorBL.getAuthorData(code, state);
25 
26         req.setAttribute("nickname", tAuthorUserInfo.getNickname());
27         // 獲取信息成功,回寫成功頁面
28         req.getRequestDispatcher("../wechat/authorsucc.jsp").forward(req, resp);
29 
30     }
31 
32     @Override
33     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
34     {
35         // TODO Auto-generated method stub
36         super.doPost(req, resp);
37     }
38 
39 
40 }
View Code

 能夠從受權中獲取到 code 和state(可自定義用與此處校驗), 而後就是經過code來進行獲取受權的用戶信息:工具

從前面分析可知,須要先獲取受權的acces_token,而後才能獲取到受權的用戶信息,那麼結合前面2節內容,先定義2個實體類:

一、用戶受權Token類

 1 /**
 2  * 用戶受權Token
 3  * @author Damon
 4  */
 5 public class AuthorToken
 6 {
 7     // 網頁受權接口調用憑證,注意:此access_token與基礎支持的access_token不一樣
 8     private String access_token = "";
 9 
10     // access_token接口調用憑證超時時間,單位(秒)
11     private int expires_in = 0;
12 
13     // 用戶刷新access_token ="";
14     private String refresh_token = "";
15 
16     // 用戶惟一標識,請注意,在未關注公衆號時,用戶訪問公衆號的網頁,也會產生一個用戶和公衆號惟一的OpenID
17     private String openid = "";
18 
19     // 用戶受權的做用域,使用逗號(,)分隔
20     private String scope = "";
21 
22     public String getAccess_token()
23     {
24         return access_token;
25     }
26 
27     public void setAccess_token(String access_token)
28     {
29         this.access_token = access_token;
30     }
31 
32     public int getExpires_in()
33     {
34         return expires_in;
35     }
36 
37     public void setExpires_in(int expires_in)
38     {
39         this.expires_in = expires_in;
40     }
41 
42     public String getRefresh_token()
43     {
44         return refresh_token;
45     }
46 
47     public void setRefresh_token(String refresh_token)
48     {
49         this.refresh_token = refresh_token;
50     }
51 
52     public String getOpenid()
53     {
54         return openid;
55     }
56 
57     public void setOpenid(String openid)
58     {
59         this.openid = openid;
60     }
61 
62     public String getScope()
63     {
64         return scope;
65     }
66 
67     public void setScope(String scope)
68     {
69         this.scope = scope;
70     }
71 
72 }
View Code

二、受權用戶信息類

  1 /**
  2  * 經過網頁受權獲取的用戶信息
  3  * @author Damon
  4  */
  5 public class AuthorUserInfo
  6 {
  7     // 用戶的惟一標識
  8     private String openid = "";
  9 
 10     // 用戶暱稱
 11     private String nickname = "";
 12 
 13     // 用戶的性別,值爲1時是男性,值爲2時是女性,值爲0時是未知
 14     private String sex = "";
 15 
 16     // 用戶我的資料填寫的省份
 17     private String province = "";
 18 
 19     // 普通用戶我的資料填寫的城市
 20     private String city = "";
 21 
 22     // 國家,如中國爲CN
 23     private String country = "";
 24 
 25     // 用戶頭像,最後一個數值表明正方形頭像大小(有0、4六、6四、9六、132數值可選,0表明640*640正方形頭像),用戶沒有頭像時該項爲空。若用戶更換頭像,原有頭像URL將失效。
 26     private String headimgurl = "";
 27 
 28     // 用戶特權信息,json 數組,如微信沃卡用戶爲(chinaunicom)
 29     private List<String> privilege = new ArrayList<String>();
 30 
 31     // 只有在用戶將公衆號綁定到微信開放平臺賬號後,纔會出現該字段。
 32     private String unionid = "";
 33 
 34     public String getOpenid()
 35     {
 36         return openid;
 37     }
 38 
 39     public void setOpenid(String openid)
 40     {
 41         this.openid = openid;
 42     }
 43 
 44     public String getNickname()
 45     {
 46         return nickname;
 47     }
 48 
 49     public void setNickname(String nickname)
 50     {
 51         this.nickname = nickname;
 52     }
 53 
 54     public String getSex()
 55     {
 56         return sex;
 57     }
 58 
 59     public void setSex(String sex)
 60     {
 61         this.sex = sex;
 62     }
 63 
 64     public String getProvince()
 65     {
 66         return province;
 67     }
 68 
 69     public void setProvince(String province)
 70     {
 71         this.province = province;
 72     }
 73 
 74     public String getCity()
 75     {
 76         return city;
 77     }
 78 
 79     public void setCity(String city)
 80     {
 81         this.city = city;
 82     }
 83 
 84     public String getCountry()
 85     {
 86         return country;
 87     }
 88 
 89     public void setCountry(String country)
 90     {
 91         this.country = country;
 92     }
 93 
 94     public String getHeadimgurl()
 95     {
 96         return headimgurl;
 97     }
 98 
 99     public void setHeadimgurl(String headimgurl)
100     {
101         this.headimgurl = headimgurl;
102     }
103 
104     public List<String> getPrivilege()
105     {
106         return privilege;
107     }
108 
109     public void setPrivilege(List<String> privilege)
110     {
111         this.privilege = privilege;
112     }
113 
114     public String getUnionid()
115     {
116         return unionid;
117     }
118 
119     public void setUnionid(String unionid)
120     {
121         this.unionid = unionid;
122     }
123 
124 }
View Code

下一步,就是經過調用接口來實現咱們的功能了~

  1     /**
  2      * 獲取受權用戶
  3      * @param code
  4      * @param state
  5      * @return
  6      */
  7     public AuthorUserInfo getAuthorData(String code, String state)
  8     {
  9 
 10         // 一、經過code獲取受權的authortoken
 11         AuthorToken tAuthorToken = getAuthorToken("appid", "appsecret", code);
 12 
 13         // 二、經過獲取的 access_token和 openid 獲取用戶信息
 14         AuthorUserInfo tAuthorUserInfo = getAuthorUserInfo(tAuthorToken.getAccess_token(), tAuthorToken.getOpenid());
 15 
 16         return tAuthorUserInfo;
 17     }
 18 
 19 
 20     /**
 21      * 獲取受權的access_token
 22      * @param appid
 23      * @param appsceret
 24      * @param code
 25      * @return
 26      */
 27     private AuthorToken getAuthorToken(String appid, String appsceret, String code)
 28     {
 29 
 30         String path = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code ";
 31 
 32         path = path.replace("APPID", appid).replace("SECRET", appsceret).replace("CODE", code);
 33 
 34         AuthorToken tAuthorToken = new AuthorToken();
 35 
 36         try
 37         {
 38             String strResp = WeChatUtil.doHttpsGet(path, "");
 39 
 40             System.out.println(strResp);
 41 
 42             // 解析獲取的token信息
 43             Map<String, Object> tMap = WeChatUtil.jsonToMap(strResp);
 44 
 45             System.out.println(tMap.toString());
 46 
 47             // 封裝 authortoken
 48 
 49             tAuthorToken.setAccess_token((String) tMap.get("access_token"));
 50             tAuthorToken.setExpires_in(Integer.parseInt((String) tMap.get("expires_in")));
 51             tAuthorToken.setOpenid((String) tMap.get("openid"));
 52             tAuthorToken.setScope((String) tMap.get("scope"));
 53             tAuthorToken.setRefresh_token((String) tMap.get("refresh_token"));
 54 
 55         }
 56         catch (HttpException e)
 57         {
 58             // TODO Auto-generated catch block
 59             e.printStackTrace();
 60         }
 61         catch (IOException e)
 62         {
 63             // TODO Auto-generated catch block
 64             e.printStackTrace();
 65         }
 66 
 67         return tAuthorToken;
 68     }
 69 
 70 
 71     /**
 72      * 經過受權的access_token及用戶的openid來拉取用戶信息
 73      * @param access_token
 74      * @param openid
 75      * @return
 76      */
 77     private AuthorUserInfo getAuthorUserInfo(String access_token, String openid)
 78     {
 79         String path = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
 80 
 81         path = path.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
 82 
 83         AuthorUserInfo tAuthorUserInfo = new AuthorUserInfo();
 84 
 85         try
 86         {
 87             String strResp = WeChatUtil.doHttpsGet(path, "");
 88 
 89             System.out.println(strResp);
 90 
 91             // 解析獲取的token信息
 92             Map<String, Object> tMap = WeChatUtil.jsonToMap(strResp);
 93 
 94             System.out.println(tMap.toString());
 95 
 96             // 封裝 authortoken
 97             tAuthorUserInfo.setOpenid((String) tMap.get("openid"));
 98             tAuthorUserInfo.setNickname((String) tMap.get("nickname"));
 99             tAuthorUserInfo.setSex((String) tMap.get("sex"));
100             tAuthorUserInfo.setCountry((String) tMap.get("country"));
101             tAuthorUserInfo.setProvince((String) tMap.get("province"));
102             tAuthorUserInfo.setCity((String) tMap.get("city"));
103             tAuthorUserInfo.setHeadimgurl((String) tMap.get("headimgurl"));
104             tAuthorUserInfo.setPrivilege((List<String>) tMap.get("privilege"));
105             tAuthorUserInfo.setUnionid((String) tMap.get("unionid"));
106         }
107         catch (HttpException e)
108         {
109             // TODO Auto-generated catch block
110             e.printStackTrace();
111         }
112         catch (IOException e)
113         {
114             // TODO Auto-generated catch block
115             e.printStackTrace();
116         }
117 
118         return tAuthorUserInfo;
119     }
View Code

 

這些搞定,咱們就已經獲取到了用戶的信息了。 最後咱們來給用戶一個好的界面體驗~

這裏新增一個頁面,顯示獲取到的用戶暱稱:

 1 <%@ page language="java" contentType="text/html; charset=GBK"
 2     pageEncoding="GBK"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 7 <title>damon's house</title>
 8 </head>
 9 <body>
10 <%
11 String nickname=request.getAttribute("nickname").toString();
12 %>
13 <table><tr><%=nickname %> 您好,感謝受權Damon的奇趣小屋!</tr></table>
14 </body>
15 </html>
View Code

來看一下效果吧~

 

微信網頁受權,獲取用戶信息就到這啦~  

相關文章
相關標籤/搜索