微信第三方登录有两种方式,参照官网https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
以下要说的是内嵌进自己页面的方式的微信登录
第一步
$(".wx_dr2").on('click',function(){
var obj = new WxLogin({
self_redirect:false,//true将微信返回的页面跳转放在ifream里面 false直接跳转到要跳转的页面
id:"weix_tankuang", //二维码图片在哪个div显示,这个是div的id
appid: "wxc2795eded4d670b1",
scope: "snsapi_login",
redirect_uri: "http%3a%2f%2fwww.wangdaibus.com%2fwechat%2fcallback", //这个是回调地址,这里要注意的是,微信只能是网址,不能要QQ一样精确到某个@RequestMapping
state: "",
style: "",
href: "data:text/css;base64,LmltcG93ZXJCb3ggLnN0YXR1c3tkaXNwbGF5OiBub25lfQouaW1wb3dlckJveCAudGl0bGV7ZGlzcGxheTogbm9uZX0=" //这里写的是你要修改的css样式 经过base64加密过后的数据
});
})
参数详解
self_redirect | 否 | true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。 |
id | 是 | 第三方页面显示二维码的容器id |
appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
scope | 是 | 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 |
redirect_uri | 是 | 重定向地址,需要进行UrlEncode |
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
style | 否 | 提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ |
href | 否 | 自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ |
第二步 和 第三步都在一起
第二步:根据code 和appid 和secret(应用密钥AppSecret,在微信开放平台提交应用审核通过后获得) 获取到access_token 和oppenid
第三步:根据oenid 和access_token 获取到用户信息
@RequestMapping("/callback")
public String loginCallBack(HttpServletRequest request,HttpServletResponse response,String code,String state) throws QQConnectException, IOException{
System.out.println("这个是code值:"+code);
System.out.println("这个是state值:"+state);
//根据code 和appid 和secret(应用密钥AppSecret,在微信开放平台提交应用审核通过后获得) 获取到access_token 和oppenid
String url= "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxc2795eded4d670b1&secret=6145d0ca2cf1b090bea546a6169eb270&code="+code+"&grant_type=authorization_code";
Map<String,String> req = new HashMap<>();
String []accrss_TOKEN = HttpClientUtil.doPostQueryCmd(url, req);
//获取到accrss_TOKEN 和appid
System.out.println(accrss_TOKEN.toString()+"这个是请求返回的值");
System.out.println("这个是第一个的值:"+accrss_TOKEN[0]);
System.out.println("这个是第二个的值:"+accrss_TOKEN[1]);
/*{"access_token":"15_xjPqdAryBUnw0o3cXpPEZw_-MinTKqn5VIEv8kCJFi5VFadmu4ChisoR_F3oGgkHPd4MEzLMppliO3B1Vhcn_g",
"expires_in":7200,"refresh_token":"15_wVtX9w2kHgGpxG_pZfVfi31wvkNKjslwasKei1TH2UyDiWruDjcojqG8IyAmO3hBdyfo_uKSIlk-1KCZ1rZzuw",
"openid":"odNMw1QALQnqNJOdBzXgyHW3pZS4","scope":"snsapi_login","unionid":"otFVy50N1h5W5EgmyUTxQGlvSSrI"}*/
String accrs_code = accrss_TOKEN[0];
if(accrs_code.equals("200")){//请求成功
String string = accrss_TOKEN[1];
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(string);
String access_token = (String) jsonObject.get("access_token");
String openid = (String) jsonObject.get("openid");
System.out.println("这个是token的值:"+access_token);
System.out.println("这个是openid的值:"+openid);
//根据oenid 和access_token 获取到用户信息
String url2 = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
String [] userinfo = HttpClientUtil.doPostQueryCmd(url2, req);
String userinfo_code = userinfo[0];
if(userinfo_code.equals("200")){
String userinfo_str = userinfo[1];
System.out.println("这个是userinfo第一个的值:"+userinfo_code);
System.out.println("这个是userinfo第二个的值:"+userinfo_str);
com.alibaba.fastjson.JSONObject jsonObject2 = JSON.parseObject(userinfo_str);
String openId= (String) jsonObject2.get("openid");
String uid = state;
String nickname = (String) jsonObject2.get("nickname"); //微信昵称
session.setAttribute("wxnickname", nickname);//存放微信昵称到session
String wxbiaoshi = "0";
if(!StringUtil.isEmpty(uid)){
//查询当前用户信息
PreCommonMember preCommonMember = preCommonMemberService.selectById(Long.valueOf(uid));
//查询当前微信是不是有人绑定过了!如果有就提示不能绑定
PreConnectMemberBindLog pcm = preConnectMemberBindLogService.selectOne(new EntityWrapper<PreConnectMemberBindLog>()
.eq(true, "type", 2).eq(true, "uin", openId).eq(true, "isbind", 1));
if(pcm != null && pcm.getUid() != null){
wxbiaoshi = "1";
}else{
PreConnectMemberBindLog pcm2 = preConnectMemberBindLogService.selectOne(new EntityWrapper<PreConnectMemberBindLog>()
.eq(true, "type", 2).eq(true, "uin", openId).eq(true, "isbind", 2).eq(true, "uid", preCommonMember.getUid()));
if(!StringUtil.isEmpty(pcm2)){ //就是以前绑定过但又解绑的
pcm2.setIsbind(1);
pcm2.setNickname(nickname);
pcm2.setDateline(System.currentTimeMillis()); //更新绑定时间
preConnectMemberBindLogService.updateById(pcm2);
preConnectMemberBindLogDetilService.insertDetil(pcm2);
wxbiaoshi = "2";
}else{
PreConnectMemberBindLog p = new PreConnectMemberBindLog();
p.setUid(Long.valueOf(uid));
p.setUin(openId);
p.setType(2); //QQ
p.setNickname(nickname);
p.setDateline(System.currentTimeMillis());
p.setIsolduse(preCommonMember.getIsold());//0 新用户 1老用户
p.setIsbind(1);//1表示绑定 0表示没有绑定
preConnectMemberBindLogService.insert(p);
preConnectMemberBindLogDetilService.insertDetil(p);
wxbiaoshi = "2";
}
}
request.getSession().setAttribute("WXBIND", "YES"); //表示是登录用户 跳转绑定业务
request.getSession().setAttribute("wxbinding", wxbiaoshi);
PreCommonMember pre = getDecryptionPreCommonMember(preCommonMember);
String avatarpathstr = preCommonMemberService.getUserAvatarpath(pre,null);
pre.setAvatarpathstr(avatarpathstr);//拼接的用户头像
request.getSession().setAttribute(Session_Constant.USER, pre); //把用户信息存进session中 并且跳转到首页
PreUcenterMembers members = preUcenterMembersService.selectOne(new EntityWrapper<PreUcenterMembers>().eq(true, "uid", preCommonMember.getUid()));
request.getSession().setAttribute(Session_Constant.USERSECURITYINFO, members);// 用户安全信息
Long id = preCommonMember.getUid();
HttpSession session = request.getSession();
String sessionId = session.getId();
MyMapSessionId.getInstance().AddSession(id, sessionId);// 不同浏览器登录绑定
return "redirect:/user/personalCenter/personIndex.action"; //直接跳转到个人中心首页
}
PreConnectMemberBindLog pcm = preConnectMemberBindLogService.selectOne(new EntityWrapper<PreConnectMemberBindLog>()
.eq(true, "type", 2).eq(true, "uin", openId).eq(true, "isbind", 1));
if(!StringUtil.isEmpty(pcm)){//用户已经绑定过了,直接跳转登录页面
pcm.setNickname(nickname);
preConnectMemberBindLogService.updateById(pcm); //把老用户绑定过的QQ的昵称都加上
System.out.println("我进登录了");
//根据uid 查询用户信息,并存进session
PreCommonMember preCommonMember = preCommonMemberService.selectById(pcm.getUid());
PreCommonMember pre = getDecryptionPreCommonMember(preCommonMember);
String avatarpathstr = preCommonMemberService.getUserAvatarpath(pre,null);
pre.setAvatarpathstr(avatarpathstr);//拼接的用户头像
request.getSession().setAttribute(Session_Constant.USER, pre); //把用户信息存进session中 并且跳转到首页
//查询用户安全信息表
PreUcenterMembers members = preUcenterMembersService.selectOne(new EntityWrapper<PreUcenterMembers>().eq(true, "uid", pcm.getUid()));
request.getSession().setAttribute(Session_Constant.USERSECURITYINFO, members);// 用户安全信息
Long id = preCommonMember.getUid();
HttpSession session = request.getSession();
String sessionId = session.getId();
MyMapSessionId.getInstance().AddSession(id, sessionId);// 不同浏览器登录绑定
return "redirect:/";
}else{
session.setAttribute("weixoppId", openId);//存放 oppid到session
//跳转绑定用户页面
return "redirect:/wechat/bindUser";
}
}else{
return "redirect:/?loginName=logout";
}
}else{
System.out.println("请求失败:"+accrs_code);
return "redirect:/?loginName=logout";
}
}
微信第三方登录踩过的坑:
1.授权回调域 www.wangdaibus.com 只允许是网址,不能在后面加www.wangdaibus.com/aa/bb等
2.微信返回的二维码图片大小和title 和底部文字,如果不需要的情况下,可以用以下方式解决
把你要覆盖微信css的样式经过base64加密过后放入href 就可以了