上一篇讲了模板消息管理,这一篇讲网页授权获取用户基本信息。
场景:
用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
网页授权流程分为四步: 1. 引导用户进入授权页面同意授权,获取code 1. 通过 code 换取网页授权access_token(与基础支持中的access_token不同) 1. 如果需要,开发者可以刷新网页授权access_token,避免过期 1. 通过网页授权access_token和 openid 获取用户基本信息(支持 UnionID 机制) 复制代码
1 第一步:用户同意授权,获取code
首先需要引导用户点击授权链接,如果用户同意授权就可以拿到用户的code,进行下一步。
1.1 微信常量类新增设置引导链接URL OAUTH2_AUTHORIZE ()
/** * 引导链接 */ public static final String OAUTH2_AUTHORIZE = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"; 复制代码
参数说明:
appid: 公众号的唯一标识
redirect_uri: 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理 (设置方式如图:
网络异常,图片无法展示
|
注意: 这块有个细节,如果设置错了1.2步骤回调时就汇报(10003 redirect_uri域名与后台配置不一致 ),一定是域名不要带着http:// 等协议头。见官文
网络异常,图片无法展示
|
网络异常,图片无法展示
|
response_type: 返回类型,请填写code
scope: 我们使用snsapi_userinfo (弹出授权页面,可通过 openid 拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state: 重定向后会带上 state 参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect: 无论直接打开还是做页面302重定向时候,必须带此参数
1.2 修改文本消息处理类 TextMessageService
我们修改文本消息处理类,设置当用户文本为“授权登录”时,展示用户登录链接,用户点击链接则获取到用户的code
private final WeCharConfig weCharConfig; public TextMessageService(WeCharConfig weCharConfig) { this.weCharConfig = weCharConfig; } @Override public String handler(Map<String, Object> param) { String content = "你好呀,欢迎关注我的测试公众号!!"; if (param.get(WeCharConstant.CONTENT).toString().equals("授权登录")) { content = WeCharConstant.OAUTH2_AUTHORIZE.replace("APPID", weCharConfig.getAppId()) .replace("REDIRECT_URI", "https://6016a95m81.zicp.fun/v1/weChar/getCode").replace("SCOPE", "snsapi_userinfo"); System.out.println(content); content = "您好,请点击<a href='" + content + "'>授权登录</a>进行更多的操作。"; } return TextMessage.ofSendMsg(param, content).toXml(); } 复制代码
1.3 增加回调处理类 UserInfoController
import cn.org.spring.common.util.HttpClientUtils; import com.alibaba.fastjson.JSON; import com.ctsi.sddx.config.WeCharConfig; import com.ctsi.sddx.constants.WeCharConstant; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; /** * @Author : lizzu * @create 2022/10/5 16:05 */ @Slf4j @RestController @RequestMapping("/v1/weChar") public class UserInfoController { @Autowired private WeCharConfig charConfig; /** * 回调链接 * 1、获取code -> 获取accessToken ->获取用户基本信息 */ @RequestMapping("/getCode") public String getCode(@RequestParam("code") String code, @RequestParam("state") String state) { System.out.println(code); System.out.println(state); return code+"----"+state; } } 复制代码
1.4 测试
网络异常,图片无法展示
|
网络异常,图片无法展示
|
2 第二步:通过 code 换取网页授权access_token
2.1 微信常量类新增获取OAUTH认证的access_token URL OAUTH_GET_AT
/** * 获取OAUTH认证的access_token */ public static final String OAUTH_GET_AT = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; 复制代码
2.2 修改 UserInfoController 回调方法getCode() ,增加获取accessToken 和 openID 方法getAccessToken(String code)
@Autowired private WeCharConfig charConfig; /** * 回调链接 * 1、获取code -> 获取accessToken ->获取用户基本信息 */ @RequestMapping("/getCode") public String getCode(@RequestParam("code") String code, @RequestParam("state") String state) throws IOException { System.out.println(code); System.out.println(state); String userInfo = getAccessToken(code); return userInfo; } /** * 获取accessToken 和 openID * * @param code * @return * @throws IOException */ public String getAccessToken(String code) throws IOException { String s = HttpClientUtils.get(WeCharConstant.OAUTH_GET_AT.replace("APPID", charConfig.getAppId()) .replace("SECRET", charConfig.getSecret()).replace("CODE", code)); System.out.println("获取access token " + s); String access_token = JSON.parseObject(s).getString("access_token"); String openid = JSON.parseObject(s).getString("openid"); return "access_token:"+access_token+" openid:"+openid; } 复制代码
2.3 测试:
获取access token {"access_token":"61_ZumbIGiicy0Efksa3Ru5doVykU-qWCqFRf8EbWh8nHEstNhq6qV-5YRnc38X8Zf4gjyIY3BblJ0MVaTLW68MoB75UuKPp7S-cFa9omcgm7M","expires_in":7200,"refresh_token":"61_Y62Fo2Bdxp3U0fYkgPjTFMBNqU1073xikXko8eYq904qVUPiJfj3UmxJt76u4aEib1HfQLUmBdxrBUVigxK5Sa5xTvc8-j7VBrELaxfhLdM","openid":"oITpR58LM-HJG0Fa4BY6MkOCG5lM","scope":"snsapi_userinfo"} 格式化: { "access_token": "61_ZumbIGiicy0Efksa3Ru5doVykU-qWCqFRf8EbWh8nHEstNhq6qV-5YRnc38X8Zf4gjyIY3BblJ0MVaTLW68MoB75UuKPp7S-cFa9omcgm7M", "expires_in": 7200, "refresh_token": "61_Y62Fo2Bdxp3U0fYkgPjTFMBNqU1073xikXko8eYq904qVUPiJfj3UmxJt76u4aEib1HfQLUmBdxrBUVigxK5Sa5xTvc8-j7VBrELaxfhLdM", "openid": "oITpR58LM-HJG0Fa4BY6MkOCG5lM", "scope": "snsapi_userinfo" } 复制代码
可以看到已经拿到了access_token,有效期expires_in、刷新token refresh_token 等。
3 第三步:刷新access_token(如果需要)
如果超时,即可使用
**请求方法** > 获取第二步的refresh_token后,请求以下链接获取access_token: > https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN 复制代码
4 第四步:拉取用户信息(需 scope 为 snsapi_userinfo)
4.1微信常量类新增获取用户基本信息 URL OAUTH_USER_INFO
/** * 获取用户基本信息 */ public static final String OAUTH_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; 复制代码
4.2修改 UserInfoController 增加获取用户基本信息方法 getUserInfo
/** * 获取用户基本信息 * * @param accessToken * @param openId * @return * @throws IOException */ public String getUserInfo(String accessToken, String openId) throws IOException { return HttpClientUtils.get(WeCharConstant.OAUTH_USER_INFO.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId)); } 复制代码
4.3测试
网络异常,图片无法展示
|
格式化数据 { "openid": "oITpR58LM-HJG0Fa4BY6MkOCG5AA", "nickname": "? 奇了怪了怪", "sex": 0, "language": "", "city": "", "province": "", "country": "", "headimgurl": "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoNc4aUZJT2w05SMIqFLQLxofkjuADnj3icyeIiaNDVlxKbFfkQRDchfwYI3FQTdxPu0NDGBSBUzVqg/135", "privilege": [] } 复制代码
5 附:检验授权凭证(access_token)是否有效
5.1 微信常量类新增获取用户基本信息 URL OAUTH_USER_INFO
/** * 获取用户基本信息 */ public static final String CHECK_USER_INFO = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID"; 复制代码
5.2 UserInfoController 新增检验授权凭证(access_token)是否有效方法 checkAccessToken(String accessToken, String openId)
完整UserInfoController
import cn.org.spring.common.util.HttpClientUtils; import com.alibaba.fastjson.JSON; import com.ctsi.sddx.config.WeCharConfig; import com.ctsi.sddx.constants.WeCharConstant; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; /** * @Author : lizzu * @create 2022/10/5 16:05 */ @Slf4j @RestController @RequestMapping("/v1/weChar") public class UserInfoController { @Autowired private WeCharConfig charConfig; /** * 回调链接 * 1、获取code -> 获取accessToken ->获取用户基本信息 */ @RequestMapping("/getCode") public String getCode(@RequestParam("code") String code, @RequestParam("state") String state) throws IOException { System.out.println(code); System.out.println(state); String userInfo = getAccessToken(code); log.info("获取用户的基本信息 【{}】", userInfo); return userInfo; } /** * 获取accessToken 和 openID * * @param code * @return * @throws IOException */ public String getAccessToken(String code) throws IOException { String s = HttpClientUtils.get(WeCharConstant.OAUTH_GET_AT.replace("APPID", charConfig.getAppId()) .replace("SECRET", charConfig.getSecret()).replace("CODE", code)); System.out.println("获取access token " + s); String access_token = JSON.parseObject(s).getString("access_token"); String openid = JSON.parseObject(s).getString("openid"); checkAccessToken(access_token, openid);//检验授权凭证(access_token)是否有效 return getUserInfo(access_token, openid); } /** * 获取用户基本信息 * * @param accessToken * @param openId * @return * @throws IOException */ public String getUserInfo(String accessToken, String openId) throws IOException { return HttpClientUtils.get(WeCharConstant.OAUTH_USER_INFO.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId)); } /** * 检验授权凭证(access_token)是否有效 * * @param accessToken * @param openId * @return * @throws IOException */ public String checkAccessToken(String accessToken, String openId) throws IOException { String s = HttpClientUtils.get(WeCharConstant.CHECK_USER_INFO.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId)); String errmsg = JSON.parseObject(s).getString("errmsg"); log.info("校验结果: 【{}】", errmsg); return s; } } 复制代码
5.3测试:
网络异常,图片无法展示
|
至此网页授权获取用户基本信息相关接口的代码实现已完成
下一篇: 本想着找个实战的结果没找到....就先欠着下一篇写小程序的吧。