先看完,把思路搞清楚!!!!!!
微信网页授权官方地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
这里,我们只要根据官方文档一步一步的走即可。
第一步:用户同意授权,获取code
参数说明:
scope参数:他的值可分为两种:snsapi_base和snsapi_userinfo,两者具有一定的区别,其中前者又称为静态授权,只可以获取到微信用户的openid;后者称为动态授权,即跳出授权页面,必须用户同意授权后才可以获取到用户的基本信息(手机号已转移到小程序中,这里就不在讲)。
redirect_uri参数:即用户点击授权后,跳转的页面(通俗)用官方的话来讲是“授权后重定向的回调链接地址”,这里需要注意的是“urlEncode对链接进行处理”
说明:
网页进行转换:http://www.jsons.cn/urlencode
JAVA代码实现: URLEncoder.encode(redirect_uri)
解:
这一步只是简单的拼接参数,起到去引导用户点击的作用,所以这一步放在前端或者后端都无所谓。
最后拼接成的样式为:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
尤其注意:跳转回调redirect_uri,应当使用 https 链接来确保授权 code 的安全性。
用户同意授权后才会依据redirect_uri跳转,跳转样式为:redirect_uri/?code=CODE&state=STATE。这里的code是为第二步做准备的。
常见错误及解决方式:
redirect_uri域名与后台配置不一致:https://blog.csdn.net/qq_40994734/article/details/120935289
第二步:通过 code 换取网页授权access_token
如果redirect_uri设置的是一个前端页面,需要前端获取到code之后传入后端,获取方法:
getUrlCode(name){
var code=decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1]
.replace(/\+/g, '%20')) || null
}
Name更换为code即可(mounted函数中使用),之后在进行URL的拼接
拼接样式:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
这里不推荐前端直接拼接,因为官方文档声明“由于公众号的 secret 和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。”所以,只需要把截取到的code数据传入后端,其余交给后端处理最好。
如果redirect_uri设置的是一个后端接口,例如:sql接口,具体代码如下:
@RequestMapping("sq1")
@ResponseBody
public Map iotest(String code) {
//拼接URL
String grant_type = "authorization_code";
String url = WxSqmain.CODEHQTOKEN + "appid=" + wxPayV2Bean.getAppId() + "&secret=" + wxPayV2Bean.getAppSecret() + "&code=" + code + "&grant_type=" + grant_type;
//java读取url中json文件中的json数据
String s = readData.readByUrlData(url,"POST");//可能会报错,建议捕获一下
//String转JSON
JSON parse = JSONUtil.parse(s);
String ture_access_token = parse.getByPath("access_token").toString();
String ture_openid = parse.getByPath("openid").toString();
}
把可能报错的地方捕获一下:
@RequestMapping("sq1")
@ResponseBody
public Map iotest(String code) {
//拼接URL
String grant_type = "authorization_code";
String url = WxSqmain.CODEHQTOKEN + "appid=" + wxPayV2Bean.getAppId() + "&secret=" + wxPayV2Bean.getAppSecret() + "&code=" + code + "&grant_type=" + grant_type;
//java读取url中json文件中的json数据
String s = readData.readByUrlData(url,"POST");//可能会报错,建议捕获一下
//String转JSON
JSON parse = JSONUtil.parse(s);
try{
String access_token = post.getByPath("access_token").toString();
String openid = post.getByPath("openid").toString();
}catch (NullPointerException ne){
Map<String, String> map = new HashMap<>();
String errmsg = post.getByPath("errmsg").toString();
log.error(errmsg);
map.put("errmsg",errmsg);
return map;
}
}
常见错误及解决办法:
{"errcode":40029,"errmsg":"invalid code"} Code 无效错误
查看白名单、appid、AppSecret是否正确
第三步:刷新access_token(如果需要)
因为access_token拥有较短的有效期,所以建议都调用一下该方法
/** 检验授权凭证(access_token)是否有效 */
public Map checkAccesstoken(String accesstoken,String openid){
HashMap<String, String> map = new HashMap<>();
/** 拼接微信URL */
String wxUrl = WxSqmain.TESTTOKEN+"access_token="+accesstoken+"&openid="+openid;
log.warn("检验授权凭证(access_token)是否有效的URL:"+wxUrl);
/** 读取URL中的参数 ,并转换为Map格式*/
Map post = JSONUtil.parseObj(JSONUtil.parse(readData.readByUrlData(wxUrl, "POST")));
/** 判断是否有效 */
if(!"ok".equals(post.get("errmsg").toString())){
/** 无效的情况 */
/** 获取refreshToken */
String refreshToken = JSONUtil.parse(readData.readByUrlData(wxUrl, "POST")).getByPath("refresh_token").toString();
/** 刷新access_token*/
String access_token = RefreshAccesstoken(refreshToken).get("access_token").toString();
String openid1 = RefreshAccesstoken(refreshToken).get("openid").toString();
map.put("access_token",access_token);
map.put("openid",openid1);
return map;
}else{
/** 有效的情况下,直接对会员表进行操作 */
map.put("access_token",accesstoken);
map.put("openid",openid);
return map;
}
}
常见错误同第二步。
第四步:拉取用户信息(需 scope 为 snsapi_userinfo)
/** 拉取授权人的信息 */
public Map getH5authorization(String accessToken,String openId){
/** 拼接微信URL */
String wxUrl = WxSqmain.GETUSERMGS+"access_token="+accessToken+"&openid="+openId+"&lang=zh_CN";
/** 读取URL中的参数 ,并转换为Map格式*/
Map post = JSONUtil.parseObj(JSONUtil.parse(readData.readByUrlData(wxUrl, "POST")));
return post;
}
具体参数信息请查看微信官方文档。
到此,结束
readData类:https://blog.csdn.net/weixin_44699658/article/details/126185660
代码完整版:见资源,微信网页授权(保姆级)