参考博客
https://www.cnblogs.com/0201zcr/p/5133062.html
官方文档
SpringBoot整合HttpClient
https://blog.csdn.net/wsywb111/article/details/80311716
主要代码:
1.获取二维码
//获取二维码的链接
public class Get2WeiCode {
// 请求微信相关参数
//站内绑定微信 的 回调
static String bindCallBack = "";
登陆页微信登陆 的 回调
static String loginCallBack = "";
static String appid = "";
static String scope = "snsapi_login";
//获取二维码-----------state里放userid ,用于网站内部,重新登陆
public static String get2WeiCodeWithUserid(RegUser user) throws UnsupportedEncodingException {
// 生成6位随机数
String random = String.valueOf(new Random().nextInt(899999) + 100000);
Integer userId = user.getId();
// state 随机数 + userid
String state = random + userId;
// 配置二维码链接--要更改appid 和 redirect_uri
String oauthUrl = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";
String redirect_uri = URLEncoder.encode(bindCallBack, "utf-8");
oauthUrl = oauthUrl.replace("APPID", appid).replace("REDIRECT_URI", redirect_uri).replace("SCOPE", scope)
.replace("STATE", state);
return oauthUrl;
}
//获取二维码-----------state里 不放userid ,用于登陆页面
public static String get2WeiCodeWithoutUserid() throws UnsupportedEncodingException {
// 配置二维码链接--要更改appid 和 redirect_uri
String oauthUrl = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";
String redirect_uri = URLEncoder.encode(loginCallBack, "utf-8");
oauthUrl = oauthUrl.replace("APPID", appid).replace("REDIRECT_URI", redirect_uri).replace("SCOPE", scope);
return oauthUrl;
}
}
2.回调函数
static String appid = "";
static String appSecret = "";
// 授权后回调方法--站内
@RequestMapping("/callBack")
public String callBack(HttpSession session, String code, String state, Model model) throws Exception {
// 获取当前登陆用户id
String userId = state.substring(6);
Integer userId2 = Integer.valueOf(userId);
RegUser user = regUserService.findUserById(userId2);
String registerNo = user.getRegisterNo();
String phone = user.getPhone();
// 1. 获取扫码者微信信息
WechatInfo wechatInfo = wechatInfoService.getWechatInfo(code, state, appid, appSecret);
// 2.通过openid查微信表是否有记录
WechatInfo record = wechatInfoService.findWechatInfoByOpenid(wechatInfo.getOpenid());
// 3. 通过userId查微信表是否有记录
WechatInfo record2 = wechatInfoService.findWechatInfoByBindUserid(userId);
//registerNo,phone用于登录,相当于用户名密码
session.setAttribute("registerNo", registerNo);
session.setAttribute("phone", phone);
if(record == null) {
if(record2 == null) {
//无记录,未绑定 ,添加微信信息到微信表,绑定后进首页-
wechatInfo.setBinduserid(userId);
wechatInfoService.addWechat(wechatInfo);
session.setAttribute("bindStatus", "Success");
return "/netbar/wechat-skip1";
}else {
//该帐号被其他微信绑定过
session.setAttribute("bindStatus", "OtherWechatBind");
return "/netbar/wechat-skip1";
}
}else {
if(record2 == null) {
//该微信绑定过其他帐号
session.setAttribute("bindStatus", "BindOtherAccount");
return "/netbar/wechat-skip1";
}else {
//该微信已绑定当前帐号
session.setAttribute("bindStatus", "IsBinding");
return "/netbar/wechat-skip1";
}
}
}
// 授权后回调方法--登陆页面二维码
@SuppressWarnings("unused")
@RequestMapping("/callBack/forLogin")
public String callBackForLogin(HttpSession session, String code, String state, Model model) throws Exception {
// 1. 获取扫码者微信信息
WechatInfo wechatInfo = wechatInfoService.getWechatInfo(code, null, appid, appSecret);
// 2.通过openid查微信表是否有记录
WechatInfo record = wechatInfoService.findWechatInfoByOpenid(wechatInfo.getOpenid());
if (record == null) {
// 提示当前微信未绑定过帐户,无法登陆。跳转到登陆页面
System.out.println("微信没绑定过");
// session里放个标记,用来在登陆页面提示该微信未绑定微信,不能登陆
session.setAttribute("isBind", "no");
return "redirect:/reglogin";
} else {
System.out.println("微信可以登陆");
String binduserid = record.getBinduserid();
Integer userId = Integer.valueOf(binduserid);
// 查出该微信绑定的用户的用户信息
RegUser user = regUserService.findUserById(userId);
String registerNo = user.getRegisterNo();
String phone = user.getPhone();
return "redirect:/regdologin3?registerNo=" + registerNo + "&phone=" + phone;
}
}
3. 获取扫码者微信信息
// 此方法只调微信接口,返回扫码者微信信息。不接通本项目数据库。
@Override
public WechatInfo getWechatInfo(String code, String state, String appid, String appSecret) throws Exception {
WechatInfo info = new WechatInfo();
// 1.通过code获取access_token
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
url = url.replace("APPID", appid).replace("SECRET", appSecret).replace("CODE", code);
String getAccessToken = httpAPIService.doGet(url);
JSONObject jsonObject = JSON.parseObject(getAccessToken);
String access_token = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
// 2.通过access_token和openid获取用户信息
String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
userInfoUrl = userInfoUrl.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
String getUserInfo = httpAPIService.doGet(userInfoUrl);
JSONObject jsonObject2 = JSON.parseObject(getUserInfo);
String nickname = jsonObject2.getString("nickname");
String sex = jsonObject2.getString("sex");
String province = jsonObject2.getString("province");
String city = jsonObject2.getString("city");
String headimgurl = jsonObject2.getString("headimgurl");
String unionid = jsonObject2.getString("unionid");
info.setNickname(nickname);
info.setSex(sex);
info.setProvince(province);
info.setCity(city);
info.setHeadimgurl(headimgurl);
info.setOpenid(openid);
info.setUnionid(unionid);
return info;
}
4. 跳转的中间页示例。
<body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden">
<input type="hidden" name="bindStatus" id="bindStatus" value="<c:out value="${bindStatus}" />">
<input type="hidden" name="registerNo" id="registerNo" value="<c:out value="${registerNo}" />">
<input type="hidden" name="phone" id="phone" value="<c:out value="${phone}" />">
<script src="<%=context%>/js/jquery.min.js?v=2.1.4"></script>
<script src="<%=context%>/js/bootstrap.min.js?v=3.3.6"></script>
<script src="<%=context%>/js/plugins/metisMenu/jquery.metisMenu.js"></script>
<script src="<%=context%>/js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
<script src="<%=context%>/js/plugins/layer/layer.min.js"></script>
<script src="<%=context%>/js/hplus.min.js?v=4.1.0"></script>
<script type="text/javascript" src="<%=context%>/js/contabs.min.js"></script>
<script src="<%=context%>/js/plugins/pace/pace.min.js"></script>
<script type="text/javascript">
/* 站内绑定微信,弹出绑定结果 */
$(function(){
var bindStatus = $("#bindStatus").val();
var registerNo = $("#registerNo").val();
var phone = $("#phone").val();
if(bindStatus != '' & bindStatus == "Success"){
alert("绑定成功");
window.location.href="/regdologin2?registerNo=" + registerNo + "&phone=" + phone;
//return "redirect:/regdologin2?registerNo=" + registerNo + "&phone=" + phone;
}
if(bindStatus != '' & bindStatus == "OtherWechatBind"){
alert("该帐号被其他微信绑定过");
window.location.href="/regdologin2?registerNo=" + registerNo + "&phone=" + phone;
}
if(bindStatus != '' & bindStatus == "BindOtherAccount"){
alert("该微信绑定过其他帐号");
window.location.href="/regdologin2?registerNo=" + registerNo + "&phone=" + phone;
}
if(bindStatus != '' & bindStatus == "IsBinding"){
alert("该微信已绑定当前帐号");
window.location.href="/regdologin2?registerNo=" + registerNo + "&phone=" + phone;
}
});
</script>
</body>
5.微信表
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `wechat_info`;
CREATE TABLE `wechat_info` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`openid` varchar(100) NOT NULL,
`nickname` varchar(50) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`sex` varchar(50) DEFAULT NULL,
`province` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`headimgurl` varchar(300) DEFAULT NULL,
`privilege` varchar(300) DEFAULT NULL,
`unionid` varchar(300) DEFAULT NULL,
`bindUserid` varchar(20) NOT NULL,
`preSet1` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `openid` (`openid`),
UNIQUE KEY `bindUserid` (`bindUserid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='微信信息表';
6. 页面接收二维码链接
<a href="${oauthUrl}">
<img src="微信图标路径">
</a>
遇到的问题:
1.用户名密码登录后,站内绑定微信,微信回调后,登录的认证信息失效。解决方式(偷偷的再次登录):回调地址里的state里包含上userid(微信回调时会把state原样带回来),通过userid获取用户名密码,带上参数,重定向到登录的controller。如:
return "redirect:/ login?username="+username+"&password="+password;
认证通过后重定向到首页 return "redirect:/ index";
感觉这种方式有点二,如果你有更好的办法,欢迎指教。
待续。。。。