准备工作:
在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。
提交审核到通过大概需要一个礼拜的时间,通过后可以拿到AppId和AppSecret,有这两个就可以调用微信api换取微信用户信息了。
第一步:获得code
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:
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 | 是 | 回调地址,就是扫码完成之后 微信会将code作为参数传到这个地址上(注意这里回调地址需要urlEncode处理) |
response_type | 是 | 填code |
scope | 是 | 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即 |
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
这里只需要拼接好这个链接,就可以获取到微信提供的一个微信二维码链接,如果获取不了二维码说明就仔细检查参数看看有没有问题。最后看到的登录页面如下:
第二步:用code换取access_token
通过扫码,用户确认登录后,微信会将code值发生到我们提供的回调地址上,拿到code值之后我们就可以搞事情了
地址:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 | 是否必须 | 说明 |
appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
secret | 是 | 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 |
code | 是 | 填写第一步获取的code参数 |
grant_type | 是 | 填authorization_code |
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.collections.MapUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class Test {
private static final String APPID = "";// 微信应用唯一标识
private static final String SECRET = "";
public void main(String code) {
JSONObject jsonObject = JSON.parseObject(getAccess_token(code));
// 获取unionId,不同平台下唯一标识(小程序/网页应用/移动应用等不管什么应用下都是唯一的),
String unionId = MapUtils.getString(jsonObject, "unionid"); //建议使用unionid作为区别标识
// 获取token,换取用户个人信息时需要使用,过期需要刷新
String access_token = MapUtils.getString(jsonObject, "access_token");
// 获取openId,仅授权应用下唯一
String openId = MapUtils.getString(jsonObject, "openid");
//获取微信用户个人信息
JSONObject userInfo = JSON.parseObject(getUserInfomation(access_token, openId));
}
/**
* 获取用户个人信息
*
* @param access_token
* @param openId
* @return
*/
public static String getUserInfomation(String access_token, String openId) {
String stringToken = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", access_token, openId);
String response = HttpUtils.httpsRequestToString(stringToken, "GET", null);
return response;
}
/**
* code换取openId以及unionId,access_token
*
* @param code
*/
public static String getAccess_token(String code) {
String stringToken = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?", APPID, SECRET, code);
String response = HttpUtils.httpsRequestToString(stringToken, "GET", null);
return response;
}
/**
* 发送https请求
*
* @param path
* @param method
* @param body
* @return
*/
public static String httpsRequestToString(String path, String method, String body) {
if (path == null || method == null) {
return null;
}
String response = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
HttpsURLConnection conn = null;
try {
// 创建SSLConrext对象,并使用我们指定的信任管理器初始化
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
TrustManager[] tm = { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上面对象中得到SSLSocketFactory
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(path);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(get|post)
conn.setRequestMethod(method);
// 有数据提交时
if (null != body) {
OutputStream outputStream = conn.getOutputStream();
outputStream.write(body.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
inputStream = conn.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
response = buffer.toString();
} catch (Exception e) {
} finally {
if (conn != null) {
conn.disconnect();
}
try {
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
} catch (IOException execption) {
}
}
return response;
}
}
通过获取了unionId以及用户的个人信息,登录流程就基本完成了。