700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 微信公众平台开发实战Java版之如何网页授权获取用户基本信息

微信公众平台开发实战Java版之如何网页授权获取用户基本信息

时间:2019-11-06 01:56:35

相关推荐

微信公众平台开发实战Java版之如何网页授权获取用户基本信息

第一部分:微信授权获取基本信息的介绍

我们首先来看看官方的文档怎么说:

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。

关于网页授权回调域名的说明

1、在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的开发者中心页配置授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加http://等协议头;2、授权回调域名配置规范为全域名,比如需要网页授权的域名为:,配置以后此域名下面的页面/music.html 、 /login.html 都可以进行OAuth2.0鉴权。但 、 、 无法进行OAuth2.0鉴权3、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可

关于网页授权的两种scope的区别说明

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

关于网页授权access_token和普通access_token的区别

1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。

关于UnionID机制

1、请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.)绑定公众号后,才可利用UnionID机制来满足上述需求。2、UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。

关于特殊场景下的静默授权

1、上面已经提到,对于以snsapi_base为scope的网页授权,就静默授权的,用户无感知;2、对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。

具体而言,网页授权流程分为四步:

1、引导用户进入授权页面同意授权,获取code2、通过code换取网页授权access_token(与基础支持中的access_token不同)3、如果需要,开发者可以刷新网页授权access_token,避免过期4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

第二部分:实现微信网页授权的详细方法

下面,我们来按照这个步骤来实现这个功能:

第一步:用户同意授权,获取code

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面

参考链接(请在微信客户端中打开此链接体验)Scope为snsapi_basehttps://open./connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirectScope为snsapi_userinfohttps://open./connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

参数说明

下图为scope等于snsapi_userinfo时的授权页面:

用户同意授权后

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE

code说明 :code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

温馨提醒:以下的省略了搭建环境和导入jar的过程,以下的方法提供参考。如果需要的话,需要看下前面的系列文章。

我们首先创建一些需要用到的pojo :

1.通过网页授权获取的用户信息

用户信息类:SNSUserInfo类

package com.souvc.weixin.pojo;import java.util.List;/*** 类名: SNSUserInfo </br>* 描述: 通过网页授权获取的用户信息 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class SNSUserInfo {// 用户标识private String openId;// 用户昵称private String nickname;// 性别(1是男性,2是女性,0是未知)private int sex;// 国家private String country;// 省份private String province;// 城市private String city;// 用户头像链接private String headImgUrl;// 用户特权信息private List<String> privilegeList;public String getOpenId() {return openId;}public void setOpenId(String openId) {this.openId = openId;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getHeadImgUrl() {return headImgUrl;}public void setHeadImgUrl(String headImgUrl) {this.headImgUrl = headImgUrl;}public List<String> getPrivilegeList() {return privilegeList;}public void setPrivilegeList(List<String> privilegeList) {this.privilegeList = privilegeList;}}

View Code

2.凭证实体类

package com.souvc.weixin.pojo;/*** 类名: Token </br>* 描述: 凭证 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class Token {// 接口访问凭证private String accessToken;// 凭证有效期,单位:秒private int expiresIn;public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public int getExpiresIn() {return expiresIn;}public void setExpiresIn(int expiresIn) {this.expiresIn = expiresIn;}}

View Code

3.网页授权信息 WeixinOauth2Token类

package com.souvc.weixin.pojo;/*** 类名: WeixinOauth2Token </br>* 描述: 网页授权信息 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class WeixinOauth2Token {// 网页授权接口调用凭证private String accessToken;// 凭证有效时长private int expiresIn;// 用于刷新凭证private String refreshToken;// 用户标识private String openId;// 用户授权作用域private String scope;public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public int getExpiresIn() {return expiresIn;}public void setExpiresIn(int expiresIn) {this.expiresIn = expiresIn;}public String getRefreshToken() {return refreshToken;}public void setRefreshToken(String refreshToken) {this.refreshToken = refreshToken;}public String getOpenId() {return openId;}public void setOpenId(String openId) {this.openId = openId;}public String getScope() {return scope;}public void setScope(String scope) {this.scope = scope;}}

View Code

4.微信用户的基本信息WeixinUserInfo类

package com.souvc.weixin.pojo;/*** 类名: WeixinUserInfo </br>* 描述: 微信用户的基本信息 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class WeixinUserInfo {// 用户的标识private String openId;// 关注状态(1是关注,0是未关注),未关注时获取不到其余信息private int subscribe;// 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间private String subscribeTime;// 昵称private String nickname;// 用户的性别(1是男性,2是女性,0是未知)private int sex;// 用户所在国家private String country;// 用户所在省份private String province;// 用户所在城市private String city;// 用户的语言,简体中文为zh_CNprivate String language;// 用户头像private String headImgUrl;public String getOpenId() {return openId;}public void setOpenId(String openId) {this.openId = openId;}public int getSubscribe() {return subscribe;}public void setSubscribe(int subscribe) {this.subscribe = subscribe;}public String getSubscribeTime() {return subscribeTime;}public void setSubscribeTime(String subscribeTime) {this.subscribeTime = subscribeTime;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getLanguage() {return language;}public void setLanguage(String language) {this.language = language;}public String getHeadImgUrl() {return headImgUrl;}public void setHeadImgUrl(String headImgUrl) {this.headImgUrl = headImgUrl;}}

View Code

5. 封装AdvancedUtil来实现以下方法 。

但是如何获取到token值呢?

/*** 获取网页授权凭证* * @param appId 公众账号的唯一标识* @param appSecret 公众账号的密钥* @param code* @return WeixinAouth2Token*/public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {WeixinOauth2Token wat = null;// 拼接请求地址String requestUrl = "https://api./sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";requestUrl = requestUrl.replace("APPID", appId);requestUrl = requestUrl.replace("SECRET", appSecret);requestUrl = requestUrl.replace("CODE", code);// 获取网页授权凭证JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);if (null != jsonObject) {try {wat = new WeixinOauth2Token();wat.setAccessToken(jsonObject.getString("access_token"));wat.setExpiresIn(jsonObject.getInt("expires_in"));wat.setRefreshToken(jsonObject.getString("refresh_token"));wat.setOpenId(jsonObject.getString("openid"));wat.setScope(jsonObject.getString("scope"));} catch (Exception e) {wat = null;int errorCode = jsonObject.getInt("errcode");String errorMsg = jsonObject.getString("errmsg");log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);}}return wat;}

View Code

获取用户信息:

/*** 通过网页授权获取用户信息* * @param accessToken 网页授权接口调用凭证* @param openId 用户标识* @return SNSUserInfo*/@SuppressWarnings( { "deprecation", "unchecked" })public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {SNSUserInfo snsUserInfo = null;// 拼接请求地址String requestUrl = "https://api./sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);// 通过网页授权获取用户信息JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);if (null != jsonObject) {try {snsUserInfo = new SNSUserInfo();// 用户的标识snsUserInfo.setOpenId(jsonObject.getString("openid"));// 昵称snsUserInfo.setNickname(jsonObject.getString("nickname"));// 性别(1是男性,2是女性,0是未知)snsUserInfo.setSex(jsonObject.getInt("sex"));// 用户所在国家snsUserInfo.setCountry(jsonObject.getString("country"));// 用户所在省份snsUserInfo.setProvince(jsonObject.getString("province"));// 用户所在城市snsUserInfo.setCity(jsonObject.getString("city"));// 用户头像snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));// 用户特权信息snsUserInfo.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class));} catch (Exception e) {snsUserInfo = null;int errorCode = jsonObject.getInt("errcode");String errorMsg = jsonObject.getString("errmsg");log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);}}return snsUserInfo;}

View Code

6. 封装https请求类 CommonUtil 类。

上面我们用到了一个支持发送https请求的工具:

package com.souvc.weixin.util;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import .ssl.X509TrustManager;/*** 类名: MyX509TrustManager </br>* 描述:信任管理器 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class MyX509TrustManager implements X509TrustManager {// 检查客户端证书public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}// 检查服务器端证书public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}// 返回受信任的X509证书数组public X509Certificate[] getAcceptedIssuers() {return null;}}

View Code

/*** 发送https请求* * @param requestUrl 请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr 提交的数据* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)*/public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {JSONObject jsonObject = null;try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setSSLSocketFactory(ssf);conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);// 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 从输入流读取返回内容InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}// 释放资源bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();jsonObject = JSONObject.fromObject(buffer.toString());} catch (ConnectException ce) {log.error("连接超时:{}", ce);} catch (Exception e) {log.error("https请求异常:{}", e);}return jsonObject;}

View Code

二、写授权类:

注意替换成自己的appid 和 密钥

package com.souvc.weixin.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.souvc.weixin.pojo.SNSUserInfo;import com.souvc.weixin.pojo.WeixinOauth2Token;import com.souvc.weixin.util.AdvancedUtil;/*** 类名: OAuthServlet </br>* 描述: 授权后的回调请求处理 </br>* 开发人员: souvc </br>* 创建时间: -11-27 </br>* 发布版本:V1.0 </br>*/public class OAuthServlet extends HttpServlet {private static final long serialVersionUID = -1847238807216447030L;public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");// 用户同意授权后,能获取到codeString code = request.getParameter("code");String state = request.getParameter("state");// 用户同意授权if (!"authdeny".equals(code)) {// 获取网页授权access_tokenWeixinOauth2Token weixinOauth2Token = AdvancedUtil.getOauth2AccessToken("wxe34a90ac7bxxcab85c", "1207d566090a8344xxxd6224c02c", code);// 网页授权接口访问凭证String accessToken = weixinOauth2Token.getAccessToken();// 用户标识String openId = weixinOauth2Token.getOpenId();// 获取用户信息SNSUserInfo snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken, openId);// 设置要传递的参数request.setAttribute("snsUserInfo", snsUserInfo);request.setAttribute("state", state);}// 跳转到index.jsprequest.getRequestDispatcher("index.jsp").forward(request, response);}}

View Code

三、授权后,显示信息的页面

<%@ page language="java" pageEncoding="utf-8"%><%@ page import="com.souvc.weixin.pojo.SNSUserInfo,java.lang.*"%><html><head><title>OAuth2.0网页授权</title><meta name="viewport" content="width=device-width,user-scalable=0"><style type="text/css">*{margin:0; padding:0}table{border:1px dashed #B9B9DD;font-size:12pt}td{border:1px dashed #B9B9DD;word-break:break-all; word-wrap:break-word;}</style></head><body><% // 获取由OAuthServlet中传入的参数SNSUserInfo user = (SNSUserInfo)request.getAttribute("snsUserInfo"); String state=request.getAttribute("state").toString();if(null != user) {%><table width="100%" cellspacing="0" cellpadding="0"><tr><td width="20%">属性</td><td width="80%">值</td></tr><tr><td>OpenID</td><td><%=user.getOpenId()%></td></tr><tr><td>昵称</td><td><%=user.getNickname()%></td></tr><tr><td>性别</td><td><%=user.getSex()%></td></tr><tr><td>国家</td><td><%=user.getCountry()%></td></tr><tr><td>省份</td><td><%=user.getProvince()%></td></tr><tr><td>城市</td><td><%=user.getCity()%></td></tr><tr><td>头像</td><td><%=user.getHeadImgUrl()%></td></tr><tr><td>特权</td><td><%=user.getPrivilegeList()%></td></tr><tr><td>state:</td><td><%=state%></td></tr></table><%}else out.print("用户不同意授权,未获取到用户信息!");%></body></html>

View Code

四、写请求的路径

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="/xml/ns/javaee"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/xml/ns/javaee /xml/ns/javaee/web-app_2_5.xsd"><!--<servlet><servlet-name>coreServlet</servlet-name><servlet-class>com.souvc.weixin.servlet.CoreServlet</servlet-class></servlet>--><!-- /coreServlet用于指定该Servlet的访问路径 <servlet-mapping> <servlet-name>coreServlet</servlet-name> <url-pattern>/coreServlet</url-pattern> </servlet-mapping>--><servlet><servlet-name>oauthServlet</servlet-name><servlet-class>com.souvc.weixin.servlet.OAuthServlet</servlet-class></servlet><servlet-mapping><servlet-name>oauthServlet</servlet-name><url-pattern>/oauthServlet</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>

View Code

五、替换官方的链接成我们的方法路径:

官方的请求链接:

https://open./connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

需要修改的地方:

(1)替换自己的AppID

(2)将redirect_url换成自己的授权请求链接URL。注意这个连接需要经过UTF-8编码。

(3)需要修改scope。需要弹出页面则要修改为snsapi_userinfo 。

scope参数的解释:

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

/*** URL编码(utf-8)* * @param source* @return*/public static String urlEncodeUTF8(String source) {String result = source;try {result = .URLEncoder.encode(source, "utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return result;}

View Code

package com.souvc.weixin.util;public class TestURL {/*** 方法名:main</br>* 详述:生成URL编码 </br>* 开发人员:souvc </br>* 创建时间:-1-4 </br>* @param args 说明返回值含义* @throws 说明发生此异常的条件*/public static void main(String[] args) {String source="/oauthServlet";System.out.println(CommonUtil.urlEncodeUTF8(source));}}

View Code

也可以直接在线url编码:/Tools/URLEncode.aspx

六、复制上面替换好的链接,然后丢进浏览器,然后用微信来扫一扫。会出现以下的效果:

说明,恭喜你,我们获取到了用户的基本信息。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。