上一个博客也写了微信公众号获取OpenId,但是现在这个和上一个有什么区别呢。
其实呢,是差不多的,只是这个是通过用户授权。
但是,又会有人问了,明明可以未授权获取到用户的openId,那我为什么要让用户进行授权呢,我偷偷的获取不就好了吗?
好像很有道理,但是呢,那微信又干嘛多一个接口呢?
其实,授权和未授权的区别就是:未授权的获取方式是需要用户关注你的公众号的,但是,授权的情况下,只要用户点击确定,用户是不需要去关注你的公众号的,你就可以获取到用户的openId以及用户的基本信息!!!
下面我讲一下流程:其实呢,流程是和上一个博客差不多的(请注意加红部分)(最后我会附上我的Utils)
1.在公众号后台设置回调的域名(大多情况下是你的项目)
开发-接口权限-网页账号-用户授权获取用户基础信息中修改
2.在页面上访问下面的网址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=*******&redirect_uri=你回调的地址&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
上面的会返回到你回调的地址?code=xxxxxxxxx
也就是说它会返回到你回调的地址并且带上code参数,一般情况下,回调的地址设置为后端的action即可,然后就可以获取到code了,当你获取到code,已经成功了一大半。
3.根据code获取到网页授权access_token(此token不是基础服务里的access_token,请记得区分),返回值内就含有openId
4.然后根据openId以及access_token你就可以获取用户基本信息了
下面我附上我的代码,已经封装好了,你只需修改appId以及secret即可,还有记得导入JSONObject的包哦,MyX509TrustManager就不贴了。
Utils:
package com.survey.common.wechat;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.survey.toysrus.model.WeChatAccessToken;
import com.survey.toysrus.model.WechatUserinfo;
import net.sf.json.JSONObject;
import com.survey.toysrus.model.WechatAccessTokenCheck;
public class weChatUtils {
// 微信公众号的appId以及secret
private static String appId = "";
private static String secret = "";
// 获取网页授权access_token的Url,和基础服务access_token不同,记得区分
private static String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
// 刷新网页授权access_token的Url,和基础服务access_token不同,记得区分
private static String getRefreshAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
// 检验授权凭证access_token是否有效,和基础服务access_token不同,记得区分
private static String checkAccessTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";
// 获取用户信息的Url
private static String getWXUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 根据code获取到网页授权access_token
*
* @author Shen
* @param code
* 微信回调后带有的参数code值
*/
public static WeChatAccessToken getAccessToken(String code) {
String url = weChatUtils.getAccessTokenUrl.replace("APPID", weChatUtils.appId).replace("SECRET", secret)
.replace("CODE", code);
JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null));
return (WeChatAccessToken) JSONObject.toBean(jsonObj,WeChatAccessToken.class);
}
/**
* 根据在获取accessToken时返回的refreshToken刷新accessToken
*
* @author Shen
* @param refreshToken
*/
public static WeChatAccessToken getRefreshAccessToken(String refreshToken) {
String url = weChatUtils.getRefreshAccessTokenUrl.replace("APPID", weChatUtils.appId).replace("REFRESH_TOKEN",
refreshToken);
JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null));
return (WeChatAccessToken) JSONObject.toBean(jsonObj,WeChatAccessToken.class);
}
/**
* 获取微信用户信息
*
* @author Shen
* @param openId
* 微信标识openId
* @param accessToken
* 微信网页授权accessToken
*/
public static WechatUserinfo getWXUserInfoUrl(String openId, String accessToken) {
String url = weChatUtils.getWXUserInfoUrl.replace("OPENID", openId).replace("ACCESS_TOKEN", accessToken);
JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null));
return (WechatUserinfo) JSONObject.toBean(jsonObj,WechatUserinfo.class);
}
/**
* 检验授权凭证accessToken是否有效
*
* @author Shen
* @param openId
* @param accessToken
*/
public WechatAccessTokenCheck checkAccessToken(String openId, String accessToken) {
String url = weChatUtils.checkAccessTokenUrl.replace("OPENID", openId).replace("ACCESS_TOKEN", accessToken);
JSONObject jsonObj=JSONObject.fromObject(httpRequest(url, "POST", null));
return (WechatAccessTokenCheck) JSONObject.toBean(jsonObj,WechatAccessTokenCheck.class);
}
/**
* get或者post请求
*
* @author Shen
* @param requestUrl
* @param requestMethod
* GET or POST 需要大写*
* @param outputStr
* @return
*/
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = new StringBuffer();
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 httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
} catch (ConnectException ce) {
System.out.println("Weixin server connection timed out." + ce.getMessage());
} catch (Exception e) {
System.out.println("https request error:{}" + e.getMessage());
}
return buffer.toString();
}
}
WeChatAccessToken:
package com.survey.toysrus.model;
/**
* 此AccessToken不是基础模块的AccessToken,是一个特殊的网页授权access_token,请记得区分
*
* @author Shen date : 2018-01-22
*/
public class WeChatAccessToken {
/**
* 直接引用了微信的返回值,不使用驼峰等命名 access_token
* 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 expires_in
* access_token接口调用凭证超时时间,单位(秒) refresh_token 用户刷新access_token openid
* 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID scope
* 用户授权的作用域,使用逗号(,)分隔
*/
private String access_token;
private int expires_in;
private String refresh_token;
private String openid;
private String scope;
// 额外的信息
private int errcode;
private String errmsg;
public int getErrcode() {
return errcode;
}
public void setErrcode(int errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
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;
}
}