官方文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
HttpClientUtil.java
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClientUtil {
private static class SingletonHolder{
private final static HttpClientUtil INSTANCE=new HttpClientUtil();
}
private HttpClientUtil(){}
public static HttpClientUtil getInstance(){
return SingletonHolder.INSTANCE;
}
public String get(String url){
CharsetHandler handler = new CharsetHandler("UTF-8");
CloseableHttpClient client = null;
try {
HttpGet httpget = new HttpGet(new URI(url));
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
client= httpClientBuilder.build();
client = (CloseableHttpClient) wrapClient(client);
return client.execute(httpget, handler);
} catch (Exception e) {
//e.printStackTrace();
return "";
}finally {
try {
if(client!=null){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String post(String url, String params,String contentType)
{
//創建HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//HttpClient
CloseableHttpClient client = httpClientBuilder.build();
client = (CloseableHttpClient) wrapClient(client);
HttpPost post = new HttpPost(url);
CloseableHttpResponse res = null;
try
{
StringEntity s = new StringEntity(params,"UTF-8");
if(StringUtils.isBlank(contentType)){
s.setContentType("application/json");
}
s.setContentType(contentType);
s.setContentEncoding("utf-8");
post.setEntity(s);
res = client.execute(post);
HttpEntity entity = res.getEntity();
return EntityUtils.toString(entity, "utf-8");
}
catch (Exception e)
{
e.printStackTrace();
} finally {
try {
res.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
public static String post(String urlStr,String xmlInfo) {
String line1 = "";
try {
URL url = new URL(urlStr);
URLConnection con = url.openConnection();
con.setDoOutput(true);
//con.setRequestProperty("Pragma:", "no-cache");
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Content-Type", "text/xml");
OutputStreamWriter out = new OutputStreamWriter(con
.getOutputStream());
out.write(new String(xmlInfo.getBytes("utf-8")));
out.flush();
out.close();
BufferedReader br = new BufferedReader(new InputStreamReader(con
.getInputStream()));
String line = "";
for (line = br.readLine(); line != null; line = br.readLine()) {
line1+=line;
}
return new String(line1.getBytes(),"utf-8");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private class CharsetHandler implements ResponseHandler<String> {
private String charset;
public CharsetHandler(String charset) {
this.charset = charset;
}
public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if (entity != null) {
if (!StringUtils.isBlank(charset)) {
return EntityUtils.toString(entity, charset);
} else {
return EntityUtils.toString(entity);
}
} else {
return null;
}
}
}
private static HttpClient wrapClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLSv1");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
return httpclient;
} catch (Exception ex) {
return null;
}
}
}

(注:獲取到的code只能使用一次,每次請求都要重新獲取一次code,因此以下方法,如果用戶重新刷新了頁面,就會報錯,建議把使用過的code放在緩存中,每次請求接口前判斷code是否已經使用,如果使用了就重新獲取code去請求接口)
MessageAct.java
package com.test;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class MessageAct {
private String appid="公眾號的APP_ID";
private String secret="公眾號的APP_SECRET";
/**
* 微信登錄
*
* @param code
* @param redirectUrl 返回用戶的登錄地址
* @param request
* @param response
* @param model
* @return
* @throws IOException
*/
@RequestMapping(value = "/weixinLogin")
public String weixinLogin(String code, String redirectUrl, HttpServletRequest request, HttpServletResponse response, ModelMap model) throws IOException {
String redirect_uri = "redirectUrl是授權登錄后要進行跳轉的鏈接“
//-----在這里判斷code是否已經存在於緩存中,如果存在,說明code已經使用過,需要重新獲取code------
List list = (List) request.getSession().getAttribute("openid_list");
if (StringUtils.isNotBlank(code) && list != null && list.contains(code)) {
//用過了
code = "";
}
//獲取code
if (StringUtils.isBlank(code)) {
try {
PrintWriter out = response.getWriter();
out.println("<script>window.location.href='" + getCodeUrl(redirect_uri) + "'</script>");
out.flush();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
String[] s = getOpenId(code);
String openId = s[0];
String accessToken = s[1];
String[] userInfo = getUserInfo(openId, accessToken);//獲取用戶信息
System.out.println("手機登錄openId=================================>" + openId);
User user = userMng.findById(openId); //查詢用戶是否存在,openId 作為查詢條件
if (user != null) {
//用戶已經存在
} else {
//用戶不存在,進行注冊操作
}
return "redirect:" + redirectUrl;
}
/**
* 獲取用戶授權 得到openId,accessToken
*
* @param code
* @return
*/
public String[] getOpenId(String code) {
String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
tokenUrl = tokenUrl + "&appid=" + appid + "&secret=" + secret + "&code=" + code;
JSONObject json = null;
try {
json = new JSONObject(HttpClientUtil.getInstance().get(tokenUrl));
//------------在這里把使用過的code存入到緩存中--------
} catch (JSONException e2) {
e2.printStackTrace();
}
String openId = "";
String accessToken = "";
String[] s = new String[2];
if (json != null) {
try {
openId = json.getString("openid");
accessToken = json.getString("access_token");
s[0] = openId;
s[1] = accessToken;
} catch (JSONException e) {
String errcode = null;
try {
errcode = json.getString("errcode");
System.out.println("errcode================>手機登錄 獲取用戶授權失敗" + errcode);
} catch (JSONException e1) {
e1.printStackTrace();
}
}
}
return s;
}
/**
* 獲取用戶信息 拉取用戶信息(需scope為 snsapi_userinfo)
* 只有在用戶將公眾號綁定到微信開放平台帳號后,可以獲取unionid
*
* @param
* @param
* @return
*/
public String[] getUserInfo(String openid, String accessToken) {
String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN";
userInfoUrl = userInfoUrl + "&access_token=" + accessToken + "&openid=" + openid;
JSONObject json = null;
try {
json = new JSONObject(HttpClientUtil.getInstance().get(userInfoUrl));
} catch (JSONException e2) {
e2.printStackTrace();
}
String nickname = ""; //用戶昵稱
String sex = ""; //用戶的性別
String province = ""; //用戶個人資料填寫的省份
String city = ""; //普通用戶個人資料填寫的城市
String country = ""; //國家,如中國為CN
String headimgurl = ""; //用戶頭像,
String unionid = ""; //
String[] s = new String[6];
if (json != null) {
try {
nickname = json.getString("nickname");
sex = json.getString("sex");
province = json.getString("province");
city = json.getString("city");
country = json.getString("country");
headimgurl = json.getString("headimgurl");
s[0] = nickname;
s[1] = sex;
s[2] = province;
s[3] = city;
s[4] = country;
s[5] = headimgurl;
} catch (JSONException e) {
String errcode = null;
try {
errcode = json.getString("errcode");
System.out.println("errcode================>獲取用戶信息失敗" + errcode);
} catch (JSONException e1) {
e1.printStackTrace();
}
}
}
return s;
}
/**
* 獲取code請求地址
*
* @param redirect_uri 回調地址 這個回調地址需要在微信公眾號后台也進行配置 不然會顯示"redirect_uri域名還是與后台配置不一致"
* @param
* @return
*/
public String getCodeUrl(String redirect_uri) {
redirect_uri=URLEncoder.encode(redirect_uri); //使用 urlEncode 對鏈接進行處理
String codeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
codeUrl = codeUrl + "?appid=" + appid + "&redirect_uri=" + redirect_uri
+ "&response_type=code&scope=snsapi_userinfo&state=jetcms#wechat_redirect";
return codeUrl;
}
}
