https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=aa96840e02282c418d755b333218e800ed53f04e&lang=zh_CN
这个是微信开发官网上的,绝对正确.
好,现在开始微信登录流程.
1:引导用户打开授权页面
可以做一个 a 标签,href="
https://open.weixin.qq.com/connect/qrconnect?
appid=APPID
&redirect_uri=REDIRECT_URI
&response_type=code
&scope=SCOPE
&state=STATE#wechat_redirect"
其中APPID为你申请之后微信官网给你的,
redirect_uri为用户点击手机上的同意之后的回调地址,即用户同意之后,网页就会跳到你写的地址上,并且这个url需要 UrlEncode编码 才可以.(这个url必须和你申请的时候写的一样.比如,你申请的时候,填写的是 www.wowowo.com 现在写的时候,必须是 http://www.wowowo.com/weixin 这样子.而且要经过编码.后面的weixin是我自己加的,你可以换成自己的.用户同意之后,浏览器就会从授权页面跳到
http:www.wowowo.com/weixin?code=XXXXXX&state=state)
scope直接填 snsapi_login
state 可以不写,也可以写,建议写上,因为 用户同意之后,会回跳到你自己写的url上,并且会带上参数code和state.你给了什么state,返回来的url上跟着什么state
一开始的时候,我一直打不开授权页面,配置也没错,也不知道为什么.后来直接用 http:www.wowowo.com,后面不加别的路径,跳到首页之后,用java代码获取code和state,判断不为空并且state.equals(自己给的state),满足条件之后就跳,记得附带上code参数.
2:通过用户授权得到的code,进一步得到用户的openID和基础信息.
下面开始贴我的代码.
web.xml中的代码:
<servlet-mapping>
<servlet-name>weixin</servlet-name>
<url-pattern>/weixin</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>weixin</servlet-name>
<servlet-class>com.XXXX.plugin.weixin.WeiXinLoginAfter</servlet-class>
</servlet>
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class WeiXinLoginAfter extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1992726828107519063L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// 用户同意授权后,能获取到code
String code = request.getParameter("code");
String state = request.getParameter("state");
// 用户同意授权
if (!"".equals(code) && "weixin".equals(state)) {
//APPSECRET 是申请成功之后给的秘钥,一般放在资源文件中,需要的时候读出来.
// 获取网页授权access_token,下面只得到了openId,还有 accessToken
WeixinOauth2Token weixinOauth2Token = AdvancedUtil.getOauth2AccessToken("wx9a9733ca700029be",PropertiesUtil.getParam("APPSECRET"), code);
// 网页授权接口访问凭证
String accessToken = weixinOauth2Token.getAccessToken();
// 用户标识
String openId = weixinOauth2Token.getOpenId();
// 获取用户信息(比较具体,有昵称,头像url,性别,城市等)
SNSUserInfo snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken, openId);
//现在你已经得到openid和用户基础信息,可以做你想做的了.
}else{
}
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
public class AdvancedUtil {
private static Logger log = LoggerFactory.getLogger(AdvancedUtil.class);
/**
* 获取网页授权凭证
*
* @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.weixin.qq.com/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.getInteger("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.getInteger("errcode");
String errorMsg = jsonObject.getString("errmsg");
log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return wat;
}
/**
* 通过网页授权获取用户信息
*
* @param accessToken 网页授权接口调用凭证
* @param openId 用户标识
* @return SNSUserInfo
*/
public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {
SNSUserInfo snsUserInfo = null;
// 拼接请求地址
String requestUrl = "https://api.weixin.qq.com/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.getInteger("sex"));
// 用户所在国家
snsUserInfo.setCountry(jsonObject.getString("country"));
// 用户所在省份
snsUserInfo.setProvince(jsonObject.getString("province"));
// 用户所在城市
snsUserInfo.setCity(jsonObject.getString("city"));
// 用户头像
snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
} catch (Exception e) {
snsUserInfo = null;
int errorCode = jsonObject.getInteger("errcode");
String errorMsg = jsonObject.getString("errmsg");
log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return snsUserInfo;
}
}
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class CommonUtil {
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
/**
* 发送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 =JSON.parseObject(buffer.toString());
} catch (ConnectException ce) {
log.error("连接超时:{}", ce);
} catch (Exception e) {
log.error("https请求异常:{}", e);
}
return jsonObject;
}
}
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;
}
}
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;
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;
}
}
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 类名: MyX509TrustManager </br>
* 描述:信任管理器 </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;
}
}
最后,我用的json是阿里巴巴的fastjson,你使用的时候可能需要转换.
我也是通过 https://share.weiyun.com/73d6445f788e33fafe603dd1adb8db83
下载别人的代码,经过修改,做成自己的.希望可以给你帮助.