最近对微信开发学习了一番,下面是自己的学习记录,有什么问题的话欢迎指出!
首先先看看官方文档:
链接地址: http://mp.weixin.qq.com/wiki/home/。
关于其中的概念和注意点文档里都介绍的挺仔细的,我就不贴出来了。
网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code
2、通过code换取网页授权access_token(与基础支持中的access_token不同)
3、如果需要,开发者可以刷新网页授权access_token,避免过期
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
1. 配置授权回调页面域名
我用的测试公众号,登录后找到 网页服务–网页帐号–网页授权获取用户基本信息后的修改。
授权回调域名配置规范为全域名并且不带http,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权。
2. 用户授权并获取code
这一步其实就是将需要授权的页面url拼接到微信的认证请求接口里面,比如需要用户在访问页面guodd.tunnel.qydev.com/auth 时进行授权认证,那么拼接后的授权验证地址为:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxx&redirect_uri=http://guodd.tunnel.qydev.com/auth&response_type=code&scope=snsapi_userinfo&state=xxxx_state#wechat_redirect
这里面需要替换appid、redirect_uri为实际的信息。其中的scope参数有两个值:
snsapi_base:只能获取到用户openid。好处是静默认证,无需用户手动点击认证按钮,感觉上像是直接进入网站一样。
snsapi_userinfo:可以获取到openid、昵称、头像、所在地等信息。需要用户手动点击认证按钮。
/**
* 生成用于获取access_token的Code的Url
*
* @return
*/
public String getCode() {
String requestUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
return requestUrl.replace("APPID", AppConstant.APPID).replace(
"redirect_uri", CommonUtil.urlEncodeUTF8(redirect_uri));
}
这边的redirect_uri要进行urlEncode处理
/**
* URL编码(utf-8)
*
* @param source
* @return
*/
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
3、通过第一步获取的code换取网页授权access_token(与基础支持中的access_token不同)
/**
* 获取网页授权凭证
*
* @param appId
* 公众账号的唯一标识
* @param appSecret
* 公众账号的密钥
* @param code
* @return WeixinAouth2Token
*/
public static WeixinOauth2Token getOauth2AccessToken(String appId,
String appSecret, String code) {
WeixinOauth2Token wat = null;
// 拼接请求地址
String requestUrl = ACCESS_TOKEN_URL.replace("APPID", appId)
.replace("SECRET", appSecret).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"));
System.out.println("获取网页授权凭证成功");
} catch (Exception e) {
wat = null;
int errorCode = jsonObject.getInt("errcode");
String errorMsg = jsonObject.getString("errmsg");
System.out.println("获取网页授权凭证失败");
}
}
return wat;
}
这个方法可以获取网页授权凭证,其中的WeixinAouth2Token类
/**
* 类名: WeixinOauth2Token </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;
}
}
获取用户信息的方法和获取网页授权凭证的方法都在AdvancedUtil工具类中,代码如下:
public class AdvancedUtil {
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 获取网页授权凭证
*
* @param appId
* 公众账号的唯一标识
* @param appSecret
* 公众账号的密钥
* @param code
* @return WeixinAouth2Token
*/
public static WeixinOauth2Token getOauth2AccessToken(String appId,
String appSecret, String code) {
WeixinOauth2Token wat = null;
// 拼接请求地址
String requestUrl = ACCESS_TOKEN_URL.replace("APPID", appId)
.replace("SECRET", appSecret).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"));
System.out.println("获取网页授权凭证成功");
} catch (Exception e) {
wat = null;
int errorCode = jsonObject.getInt("errcode");
String errorMsg = jsonObject.getString("errmsg");
System.out.println("获取网页授权凭证失败");
}
}
return wat;
}
/**
* 获取用户信息
*
* @param accessToken
* @param openId
* @return
*/
public static WeixinUserInfo getUserInfo(String accessToken, String openId) {
String url = GET_USERINFO_URL.replace("ACCESS_TOKEN", accessToken)
.replace("OPENID", openId);
WeixinUserInfo userInfo = null;
JSONObject jsonObject = CommonUtil.httpsRequest(url, "GET", null);
if (null != jsonObject) {
try {
userInfo = new WeixinUserInfo();
userInfo.setOpenId(jsonObject.getString("openid"));
userInfo.setNickname(jsonObject.getString("nickname"));
userInfo.setSex(jsonObject.getInt("sex"));
userInfo.setProvince(jsonObject.getString("province"));
userInfo.setCountry(jsonObject.getString("country"));
userInfo.setCity(jsonObject.getString("city"));
userInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
System.out.println("获取用户信息成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("获取用户信息失败");
}
}
return userInfo;
}
}
其中的微信用户类:
/**
* 类名: WeixinUserInfo </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_CN
private 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;
}
}
在页面获取到用户信息:
/**
* 类名: OAuthServlet </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");
// 用户同意授权后,能获取到code
String code = request.getParameter("code");
// 用户同意授权
if (!"authdeny".equals(code)) {
// 获取网页授权access_token
WeixinOauth2Token weixinOauth2Token = AdvancedUtil
.getOauth2AccessToken(AppConstant.APPID,
AppConstant.APPSECRET, code);
System.out.println(weixinOauth2Token);
// 网页授权接口访问凭证
String accessToken = weixinOauth2Token.getAccessToken();
// 用户标识
String openId = weixinOauth2Token.getOpenId();
// 获取用户信息
WeixinUserInfo userInfo = AdvancedUtil.getUserInfo(accessToken,
openId);
System.out.println(userInfo);
// 设置要传递的参数
request.setAttribute("userInfo", userInfo);
request.getRequestDispatcher("index.jsp")
.forward(request, response);
}
}
}
代码基本都贴上去了,希望对你们有所帮助!!!