本文主要介紹部分功能的代碼實現,在此之前需認真閱讀微信公衆平臺技術文檔之微信網頁授權
該工具類包括功能如下:
- 通過前端獲取到的code換取網頁授權access_token、openId等
- 拉取用戶信息(需scope爲 snsapi_userinfo)
需要注意的是,此時獲取到的access_token與另一篇文章(微信公衆號開發----獲取access_token,定時刷新access_token)中的獲取的access_token是不一樣的
關於網頁授權access_token和普通access_token的區別
-
微信網頁授權是通過OAuth2.0機制實現的,在用戶授權給公衆號後,公衆號可以獲取到一個網頁授權特有的接口調用憑證(網頁授權access_token),通過網頁授權access_token可以進行授權後接口調用,如獲取用戶基本信息;
-
其他微信接口,需要通過基礎支持中的“獲取access_token”接口來獲取到的普通access_token調用。
一、相關jar包
FastJson和JackJson可二選一
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 日誌相關 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
二、公衆號相關常量及接口地址
前提:公衆號的appId 和appsecret
/**
* 公衆號相關
*/
public class WechartConst {
//公衆號的唯一標識
public static final String appId = "公衆號的唯一標識";
//公衆號的appsecret
public static final String appSecret = "公衆號的appsecret";
//通過code換取網頁授權信息
public static final String GET_WEBAUTH_URL ="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
//獲取用戶基本信息(包括UnionID機制)
public static final String GET_WEIXIN_USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
//獲取用戶基本信息(沒有subscribe等字段)
public static final String Get_USER_URL = " https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 獲取access_token的URL
*/
public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
}
三、 HttpUtil類
用於發送POST或GET請求:HttpsUtil類
四、實體類
- UserAccessToken類(主要獲取openId)
- AccessToken類(定時刷新accessToken)
- WechatUserInfo類(用戶個人信息)
UserAccessToken類
介紹兩種方法,作用都是把該屬性的名稱序列化爲另外一個名稱
(1)利用fastJson中的@JSONField
import com.alibaba.fastjson.annotation.JSONField;
/**
* 微信用戶授權token
*/
public class UserAccessToken {
//獲取到的憑證
@JSONField(name = "access_token")
private String accessToken;
//access_token接口調用憑證超時時間,單位(秒)
@JSONField(name = "expires_in")
private String expiresIn;
//用戶刷新access_token
@JSONField(name = "refresh_token")
private String refreshToken;
//該用戶在此公衆號下的身份表示,對於此微信號具有唯一性
@JSONField(name = "openid")
private String openId;
//用戶授權的作用域
@JSONField(name = "scope")
private String scope;
}
(2)使用JackJson中的@JsonProperty
/**
* 微信用戶實體類
*
*/
public class WechatUser implements Serializable {
private static final long serialVersionUID = -4681067645282292327L;
// openId,標識該公衆號下面的該用戶的唯一Id
@JsonProperty("openid")
private String openId;
// 用戶暱稱
@JsonProperty("nick_name")
private String nickName;
// 性別
@JsonProperty("sex")
private int sex;
// 省份
@JsonProperty("province")
private String province;
// 誠實
@JsonProperty("city")
private String city;
// 區
@JsonProperty("country")
private String country;
// 頭像圖片地址
@JsonProperty("headimgurl")
private String headimgurl;
}
AccessToken類
/**
* 封裝AccessToken實體
*/
public class AccessToken {
private String accessToken;
private int expiresIn;
}
WechatUserInfo類
public class WechatUserInfo {
//用戶是否訂閱該公衆號標識,值爲0時,代表此用戶沒有關注該公衆號,拉取不到其餘信息
private int subscribe;
//用戶的唯一標識
private String openid;
//用戶暱稱
private String nickname;
//用戶的性別,值爲1時是男性,值爲2時是女性,值爲0時是未知
private int sex;
//用戶個人資料填寫的省份
private String province;
//普通用戶個人資料填寫的城市
private String city;
//國家,如中國爲CN
private String country;
//用戶頭像,最後一個數值代表正方形頭像大小
private String headimgurl;
五、WechartUtil工具類
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.jfinal.json.Json;
public class WechartUtil {
private static Logger log = LogManager.getLogger(WechartUtil.class);
/**
* 通過code獲取UserAccessToken實體類
* @param code
* @return
*/
public static UserAccessToken getUserAccessToken(String code) {
String appId = WechartConst.appId;
String appSecret = WechartConst.appSecret;
//根據傳入的code,拼接出訪問微信定義好的接口的URL
String requestUrl = WechartConst.GET_WEBAUTH_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);
//向相應URL發送請求獲取JSON數據包
JSONObject jsonObject = HttpsUtil.request(requestUrl, "GET", null);
if (jsonObject!= null) {
Integer errCode = jsonObject.getInteger("errcode");
String resultMsg = jsonObject.toJSONString();
if (errCode != null) {
throw new ParameterException("獲取用戶accessToken失敗:" + resultMsg);
}
try {
// 將json字符串轉換成相應對象
//Jfinal框架中具有的Json.getJson().parse(String jsonString, Class<T> type)方法
// UserAccessToken token = Json.getJson().parse(tokenStr, UserAccessToken.class);
//利用JackJson
ObjectMapper objectMapper = new ObjectMapper();
UserAccessToken token = objectMapper.readValue(tokenStr, UserAccessToken.class);
return token;
}catch (JSONException e) {
String errorMsg = jsonObject.getString("errmsg");
throw new ParameterException("獲取用戶accessToken失敗:" + errorMsg);
}
}else {
throw new ParameterException("獲取用戶accessToken失敗" );
}
}
/**
* 網頁授權作用域爲snsapi_userinfo,獲取用戶基本信息(UnionID機制)
* 前提:必須有一個微信開放平臺賬號綁定了至少一個微信公衆賬號或者網站應用或者小程序
* @param accessToken 網頁授權accessToken
* @param openId
* @return
*/
public static WechatUserInfo getUserInfo(String accessToken, String openId) {
String requestUrl = WechartConst.GET_WEIXIN_USER_URL.replace("ACCESS_TOKEN", accessToken).replace( "OPENID", openId);
JSONObject jsonObject = HttpsUtil.request(requestUrl, "GET", null);
if (jsonObject!= null) {
Integer errCode = jsonObject.getInteger("errcode");
String resultMsg = jsonObject.toJSONString();
if (errCode != null) {
String errorMsg = jsonObject.getString("errmsg");
throw new ParameterException("獲取用戶基本信息失敗:" + errorMsg);
}
try {
//Jfinal框架中具有的Json.getJson().parse(String jsonString, Class<T> type)方法
//WechatUserInfo user= Json.getJson().parse(jsonObject.toJSONString(), WechatUserInfo.class);
user.setSubscribe(jsonObject.getInteger("subscribe"));
user.setOpenId(jsonObject.getString("openid"));
user.setNickName(jsonObject.getString("nickname"));
user.setSex(jsonObject.getInt("sex"));
user.setProvince(jsonObject.getString("province"));
user.setCity(jsonObject.getString("city"));
user.setCountry(jsonObject.getString("country"));
user.setHeadimgurl(jsonObject.getString("headimgurl"));
return user;
} catch (JSONException e) {
throw new ParameterException("獲取用戶accessToken失敗:" + resultMsg);
}
}else {
throw new ParameterException("獲取用戶accessToken失敗" );
}
}
}
四、使用示例
public static void main(String[] args) {
//獲取從前端傳過來的code
String code = "";
UserAccessToken userAccessToken = getUserAccessToken(code);
String accessToken = userAccessToken.getAccessToken();
String openId = userAccessToken.getOpenId();
WechatUserInfo getUserInfo = getUserInfo(accessToken,openId);
}