这里通过 code 换取的是一个特殊的网页授权 access_token, 与基础支持中的 access_token(该 access_token 用于调用其他接口)不同。公众号可通过下述接口来获取网页授权 access_token。如果网页授权的作用域为 snsapi_base,则本步骤中获取到网页授权 access_token 的同时,也获取到了 openid,snsapi_base 式的网页授权流程即到此为止。
尤其注意:由于公众号的 secret 和获取到的 access_token 安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新 access_token、通过 access_token 获取用户信息等步骤,也必须从服务器发起。
请求参数封装
- package com.phil.wechatauth.model.req;
- import java.io.Serializable;
- import java.util.Map;
- import java.util.TreeMap;
- import com.phil.common.params.AbstractParams;
- /**
- * 获取授权请求token的请求参数
- * @author phil
- * @date 2017年7月2日
- *
- */
- public class AuthTokenParams extends AbstractParams implements Serializable {
- /**
- *
- */
- private static final long serialVersionUID = 4652953400751046159L;
- private String appid; //公众号的唯一标识
- private String secret; //公众号的appsecret
- private String code; //填写第一步获取的code参数
- private String grant_type = "authorization_code";
- public AuthTokenParams() {
- super();
- }
- public AuthTokenParams(String appid, String secret, String code, String grant_type) {
- super();
- this.appid = appid;
- this.secret = secret;
- this.code = code;
- this.grant_type = grant_type;
- }
- /**
- * 参数组装
- * @return
- */
- public Map < String,
- String > getParams() {
- Map < String,
- String > params = new TreeMap < String,
- String > ();
- params.put("appid", this.appid);
- params.put("secret", this.secret);
- params.put("code", this.code);
- params.put("grant_type", this.grant_type);
- return params;
- }
- public String getAppid() {
- return appid;
- }
- public void setAppid(String appid) {
- this.appid = appid;
- }
- public String getSecret() {
- return secret;
- }
- public void setSecret(String secret) {
- this.secret = secret;
- }
- public String getCode() {
- return code;
- }
- public void setCode(String code) {
- this.code = code;
- }
- public String getGrant_type() {
- return grant_type;
- }
- }
返回的 json 封装
- package com.phil.wechatauth.model.resp;
- /**
- * 网页授权access_token
- *
- * @author phil
- * @date 2017年7月2日
- *
- */
- public class AuthAccessToken extends AccessToken {
- private String refresh_token; // 用户刷新access_token
- private String openid; // 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
- private String scope; // 用户授权的作用域,使用逗号(,)分隔
- public String getRefresh_token() {
- return refresh_token;
- }
- public void setRefresh_token(String refresh_token) {
- this.refresh_token = refresh_token;
- }
- 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;
- }
- }
获取 access_token 方法
- /**
- * 获取网页授权凭证
- * @param basic
- * @param path
- * @return
- */
- public AuthAccessToken getAuthAccessToken(AbstractParams basic, String path) {
- AuthAccessToken authAccessToken = null;
- //获取网页授权凭证
- try {
- String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, path, basic.getParams(), null);
- if (result != null) {
- authAccessToken = JsonUtil.fromJson(result, AuthAccessToken.class);
- }
- } catch(Exception e) {
- authAccessToken = null;
- logger.info("error" + e.getMessage());
- }
- return authAccessToken;
- }
获取授权进入页面
- // 获取token的链接
- private final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
- @RequestMapping(value = "bindWxPhone", method = {
- RequestMethod.GET
- }) public String prize(HttpServletRequest request, HttpServletResponse response, String url) throws Exception {
- AuthAccessToken authAccessToken = null;
- // 用户同意授权后可以获得code,检验state
- String code = request.getParameter("code");
- if (code == null) {
- return null;
- }
- String state = request.getParameter("state");
- if (state.equals(MD5Util.MD5Encode("ceshi", ""))) {
- AuthTokenParams authTokenParams = new AuthTokenParams();
- authTokenParams.setAppid("");
- authTokenParams.setSecret("");
- authTokenParams.setCode(code);
- authAccessToken = oAuthService.getAuthAccessToken(authTokenParams, ACCESS_TOKEN_URL);
- }
- if (authAccessToken != null) {
- logger.info("网页授权的accessToken=" + authAccessToken.getAccess_token());
- logger.info("正在绑定的openid=" + authAccessToken.getOpenid());
- }
- return "/system/wxuserprize/bindPhone";
- }
由于 access_token 拥有较短的有效期,当 access_token 超时后,可以使用 refresh_token 进行刷新,refresh_token 有效期为 30 天,当 refresh_token 失效之后,需要用户重新授权。
请求参数封装
- package com.phil.wechatauth.model.req;
- import java.io.Serializable;
- import java.util.Map;
- import java.util.TreeMap;
- import com.phil.common.params.AbstractParams;
- /**
- * 刷新token请求
- * @author phil
- * @date 2017年7月2日
- *
- */
- public class RefreshTokenParams extends AbstractParams implements Serializable {
- /**
- *
- */
- private static final long serialVersionUID = -7200815808171378571L;
- private String appid;
- private String grant_type = "refresh_token";
- private String refresh_token;
- public RefreshTokenParams(String appid, String grant_type, String refresh_token) {
- super();
- this.appid = appid;
- this.grant_type = grant_type;
- this.refresh_token = refresh_token;
- }
- /**
- * 参数组装
- *
- * @return
- */
- public Map < String,
- String > getParams() {
- Map < String,
- String > params = new TreeMap < String,
- String > ();
- params.put("appid", this.appid);
- params.put("grant_type", this.grant_type);
- params.put("refresh_token", this.refresh_token);
- return params;
- }
- public String getAppid() {
- return appid;
- }
- public void setAppid(String appid) {
- this.appid = appid;
- }
- public String getGrant_type() {
- return grant_type;
- }
- public String getRefresh_token() {
- return refresh_token;
- }
- public void setRefresh_token(String refresh_token) {
- this.refresh_token = refresh_token;
- }
- }
- /**
- * 刷新网页授权验证
- * @param basic 参数
- * @param path 请求路径
- * @return
- */
- public String refreshAuthAccessToken(AbstractParams basic, String path) {
- AuthAccessToken authAccessToken = null;
- //刷新网页授权凭证
- try {
- String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, path, basic.getParams(), null);
- if (result != null) {
- authAccessToken = JsonUtil.fromJson(result, AuthAccessToken.class);
- }
- } catch(Exception e) {
- authAccessToken = null;
- logger.info("error" + e.getMessage());
- }
- return authAccessToken == null ? null: authAccessToken.getAccess_token();
- }
如果网页授权作用域为 snsapi_userinfo,则此时可以通过 access_token 和 openid 拉取用户信息了
通过网页授权获取的用户信息
- /**
- * 通过网页授权获取的用户信息
- *
- * @author phil
- */
- public class AuthUserInfo {
- // 用户标识
- private String openid;
- // 用户昵称
- private String nickname;
- // 性别(1是男性,2是女性,0是未知)
- private String sex;
- // 国家
- private String country;
- // 省份
- private String province;
- // 城市
- private String city;
- // 用户头像链接
- private String headimgurl;
- // 用户特权信息
- private List < String > privilege;
- // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
- private String unionid;
- 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 String getSex() {
- return sex;
- }
- public void setSex(String 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;
- }
- public List < String > getPrivilege() {
- return privilege;
- }
- public void setPrivilege(List < String > privilege) {
- this.privilege = privilege;
- }
- public String getUnionid() {
- return unionid;
- }
- public void setUnionid(String unionid) {
- this.unionid = unionid;
- }
- }
获取方法
- //获取授权用户信息
- private final String USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
- /**
- * 通过网页授权获取用户信息
- * @param accessToken
- * @param openid
- * @return
- */
- public AuthUserInfo getAuthUserInfo(String accessToken, String openid) {
- AuthUserInfo authUserInfo = null;
- //通过网页授权获取用户信息
- Map < String,
- String > params = new TreeMap < String,
- String > ();
- params.put("openid", openid);
- params.put("access_token", accessToken);
- String result = HttpReqUtil.HttpsDefaultExecute(HttpReqtUtil.GET_METHOD, USERINFO_URL, params, null);
- if (null != result) {
- try {
- authUserInfo = JsonUtil.fromJson(result, AuthUserInfo.class);
- } catch(JsonSyntaxException e) {
- logger.info("transfer exception");
- }
- }
- return authUserInfo;
- }
- //判断用户accessToken是否有效
- private final String AUTH_URL = "https://api.weixin.qq.com/sns/auth";
- /**
- * 检验授权凭证(access_token)是否有效
- * @param accessToken 网页授权接口调用凭证
- * @param openid 用户的唯一标识
- * @return { "errcode":0,"errmsg":"ok"}表示成功 { "errcode":40003,"errmsg":"invalid openid"}失败
- */
- public ResultState authToken(String accessToken, String openid) {
- ResultState state = null;
- Map < String,
- String > params = new TreeMap < String,
- String > ();
- params.put("access_token", accessToken);
- params.put("openid", openid);
- String json = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, AUTH_URL, params, "");
- if (json != null) {
- state = JsonUtil.fromJson(json, ResultState.class);
- }
- return state;
- }
来源: http://www.bubuko.com/infodetail-2253120.html