网页授权参考 微信官方文档
对接步骤:
- 第一步:用户同意授权,获取code
- 第二步:通过code换取网页授权access_token
- 第三步:刷新access_token(如果需要)
- 第四步:拉取用户信息(需scope为 snsapi_userinfo)
用户同意授权,获取code
后端拼接授权连接,授权连接返回前端,前端可根据授权连接唤醒微信授权页面。weChatRedirectUri该参数为回调地址,用户点击是否允许登录,微信会回调这个地址。一般情况回调地址为前端页面地址不是后端接口。如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE,前端就可以获取到code。
@ResponseBody
@RequestMapping(value = "/getAuthorizeUrl",produces = "application/json;charset=utf-8")
public Result getAuthorizeUrl(String weChatRedirectUri) {
StringBuffer authorizeUrl = new StringBuffer();
authorizeUrl.append(WeChatUtils.weChatAuthorizeUrl);
authorizeUrl.append("?appid=");
authorizeUrl.append(WeChatUtils.weChatAppid);
authorizeUrl.append("&redirect_uri=");
try {
authorizeUrl.append(URLEncoder.encode(weChatRedirectUri, "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
authorizeUrl.append("&response_type=code");
authorizeUrl.append("&scope=snsapi_userinfo");
authorizeUrl.append("&state=STATE#wechat_redirect");
Result result = new Result();
result.setData(authorizeUrl.toString());
result.setState(Result.S);
return result;
}
微信登录获取openid及其它信息
步骤:1. 通过code换取网页授权access_token和openid,2.通过access_token和openid拉取用户信息了
@ResponseBody
@RequestMapping(value = "/weChatLogin",produces = "application/json;charset=utf-8")
public Result weChatLogin(String code,HttpServletRequest request) {
//1 通过code换取网页授权access_token
StringBuffer getAccessTokenUrl = new StringBuffer();
getAccessTokenUrl.append(WeChatUtils.weChatAccessTokenUrl);
getAccessTokenUrl.append("?appid=");
getAccessTokenUrl.append(WeChatUtils.weChatAppid);
getAccessTokenUrl.append("&secret=");
getAccessTokenUrl.append(WeChatUtils.weChatAppsecret);
getAccessTokenUrl.append("&code=");
getAccessTokenUrl.append(code);
getAccessTokenUrl.append("&grant_type=authorization_code");
String resultData = HttpUtils.doGet(getAccessTokenUrl.toString());
JSONObject jsonObject = JSON.parseObject(resultData);
String openid = jsonObject.getString("openid");
String accessToken = jsonObject.getString("access_token");
//2 拉取用户信息
StringBuffer getUserinfoUrl = new StringBuffer();
getUserinfoUrl.append(WeChatUtils.weChatUserinfoUrl);
getUserinfoUrl.append("?access_token=");
getUserinfoUrl.append(accessToken);
getUserinfoUrl.append("&openid=");
getUserinfoUrl.append(openid);
getUserinfoUrl.append("&lang=zh_CN");
resultData = HttpUtils.doGet(getUserinfoUrl.toString());
jsonObject = JSON.parseObject(resultData);
String nickname = jsonObject.getString("nickname");
String province = jsonObject.getString("province");
String city = jsonObject.getString("city");
String country = jsonObject.getString("country");
String headimgurl = jsonObject.getString("headimgurl");
//获取到用户信息,后面就是自己的业务逻辑了...
Result result = new Result();
result.setState(Result.S);
return result;
}
HttpUtils 工具类
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
public class HttpUtils {
/**
* @TODO :
* @AUTH : linfeng
* @DATE : 2020年7月16日 上午11:46:32
* @return_type : String
* @param url
* @param jsonstr
* @param charset
* @return
*/
public static String doPost(String url,String jsonstr){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = HttpClients.createDefault();
httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
StringEntity se = new StringEntity(jsonstr,"utf-8");
se.setContentType("text/json");
se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
httpPost.setEntity(se);
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity, "utf-8");
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
/**
* @TODO :
* @AUTH : linfeng
* @DATE : 2022年1月4日 下午5:28:43
* @return_type : String
* @param url
* @return
*/
public static String doGet(String url){
HttpClient httpClient = null;
HttpGet httpGet = null;
String result = null;
try{
httpClient = HttpClients.createDefault();
httpGet = new HttpGet(url);
httpGet.addHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity, "utf-8");
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
}
WeChatUtils 工具类
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class WeChatUtils {
public static String weChatAppid = "微信公众号appid,请用自己的。";
public static String weChatAppsecret ="微信公众号Appsecret,请用自己的。";
public static String weChatRedirectUri = "http://www.baidu.com";
public static String weChatAuthorizeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
public static String weChatAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
public static String weChatUserinfoUrl = "https://api.weixin.qq.com/sns/userinfo";
/**
* 获取微信Jsapi的accessToken
*/
public static String getAccessToken() throws IOException{
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
url = url.replace("APPID",weChatAppid).replace("APPSECRET",weChatAppsecret);
String result = HttpUtils.sendGet(url);
JSONObject jsonObject = JSON.parseObject(result);
String accessToken = jsonObject.getString("access_token");
return accessToken;
}
/**
*
* @Title: getNonceStr
* @Description: 生成随机字符串
* @param @return
* @return String 返回类型
* @throws
*/
public static String getNonceStr() {
String currT = getCurrTime();
String strT = currT.substring(8, currT.length());
String strRandom = buildRandom(4) + "";
return strT + strRandom;
}
/**
*
* @Title: buildRandom
* @Description: 生成随机数
* @param @param length
* @param @return
* @return int 返回类型
* @throws
*/
public static int buildRandom(int length) {
int mm= 1;
double random = Math.random();
if (random < 0.1) {
random = random + 0.1;
}
for (int i = 0; i < length; i++) {
mm= mm* 10;
}
return (int) ((random * mm));
}
/**
*
* @Title: getCurrTime
* @Description: 获取当前时间
* @param @return
* @return String 返回类型
* @throws
*/
public static String getCurrTime() {
Date date = new Date();
SimpleDateFormat of= new SimpleDateFormat("yyyyMMddHHmmss");
String s = of.format(date);
return s;
}
/**
* 随机字符串
* @return
*/
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
/**
*
* @Title: createSignBySha1
* @Description: 生成签名
* @param @param params
* @param @return
* @return String 返回类型
* @throws
*/
@SuppressWarnings("rawtypes")
public static String createSignBySha1(SortedMap<Object, Object> params) {
StringBuffer sb = new StringBuffer();
Set es = params.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (v != null && !v.equals("")) {
sb.append(k + "=" + v + "&");
}
}
String result = sb.toString().substring(0, sb.toString().length()-1);
return getSHA1(result);
}
/**
*
* @Title: getTimestamp
* @Description: 获取时间戳(秒)
* @param @return 参数
* @return String 返回类型
* @throws
*/
public static String getTimestamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
}
/**
*
* @Title: getSHA1
* @Description: SHA1签名生成
* @param @param str
* @param @return 参数
* @return String 返回类型
* @throws
*/
public static String getSHA1(String str){
StringBuffer hexstr = new StringBuffer();
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return hexstr.toString();
}
/**
*
* @Title: getJsapiTicket
* @Description: 获取JsapiTicket
* @param @param access_token
* @param @return
* @return String 返回类型
* @throws
*/
public static String getJsapiTicket(String access_token) throws IOException{
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi".replace("ACCESS_TOKEN",access_token);
String result = HttpUtils.sendGet(url);
JSONObject jsonObject = JSON.parseObject(result);
String ticket= jsonObject.getString("ticket");
return ticket;
}
public static String createLinkString(Map<String, String> params){
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
// try {
// value = URLEncoder.encode(value, "UTF-8");
// }catch (Exception e){
// e.printStackTrace();
// }
if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
}