开放平台PC端扫码登录功能个⼈总结
最近公司给我安排⼀个登录的功能,需求是这样的:
1.登录授权
点击⼆维码图标后,登录界⾯切换为如下样式(⼆维码),扫描⼆维码并授权,即可成功登录;
若当前账号未绑定账号,扫描后提⽰“您的账号未绑定号,请先登录绑定”;
点击“返回”按钮,界⾯切换为账号密码登录;
若号绑定多个账号在,则展⽰所绑定全部账号的⽤户名和企业名,选择账号后点击登录按钮成功登录;
2.扫描绑定
账号登录后检测当前账号open_id为空,则展⽰当前弹窗(001管理员账号除外);
⽤户扫描⼆维码后,将当前号绑定⾄对应账号;
若号之前绑定其他账号,则对应open_id下增加⼀个账号;
3.个⼈资料
新增⼀个'号'字段:显⽰账号是否绑定
好,现在整理逻辑,理清思路,画图:
声明⼀下,PC端的扫码登录是开放平台,移动端关注是跳转第三⽅应⽤的,⽤的是公众平台,两个的接⼝地址拿的openId不⼀样,开放平台下⾯如果创建多个应⽤或者绑定多个,各之间⽤unionId打通。
公司或者企业在开发前登录开放平台,注册认证,创建⼀个应⽤(应⽤就是你的项⽬,产品,不知道就直接让产品帮你注册认证,⼀般需要⼀个礼拜时间审批+300⼈民币,完了拿到AppId和AppSecret)
⾃⼰的本地环境要映射到外⽹,那样才能访问到⾃⼰接⼝来。推荐使⽤ngrok,不会的⽹上有教程,我的是直接让⼈帮我配的。
准备⼯作做好,开始开发:
第⼀步:根据⽂档⽣成⼆维码(开放平台 --> 资源中⼼ --> ⽹站应⽤ --> 登录功能 --> ⽹站应⽤登录开发指南)
我这⾥不需要⽣成整个页⾯,⽽是在⼀个div⾥⽣成,所以⽤js⽣成:
1.在页⾯中先引⼊如下JS⽂件(⽀持https):
<script src="res.wx.qq/connect/zh_CN/htmledition/js/wxLogin.js"></script>
2.在需要使⽤登录的地⽅实例以下JS对象:
var obj = new WxLogin({
id:"login_container", //div的id
appid: "",
scope: "",
redirect_uri: "", //回调地址
state: "", //参数,可带可不带
style: "", //样式提供"black"、"white"可选,默认为⿊⾊⽂字描述
href: "" //⾃定义样式链接,第三⽅可根据实际需求覆盖默认样式。
});
这⾥⽣成的⼆维码供⽤户扫描,扫描成功,移动端出现授权页⾯,需⽤户确认。
回调地址⾥⾯的域名要在开放平台去配:
⼆维码就⽣成好了,可以看看效果,还没调样式:
再来看授权步骤:
第⼀步,获取code。
接⼝中参数如下:
⾃⼰代码:
1 @Override
2public Map<String, String> weixinLoginUrl() {
3 String url = "open.weixin.qq/connect/qrconnect?appid=" + openPlatformAppId + "&redirect_uri="
4 + de("'"+ openPlatformRedirect_uri +"'/getWxLoginCode") + "&response_type=code" + "&scope=snsapi_login"
5 + "&state=STATE#wechat_redirect";
6 Map<String, String> map = new HashMap<String, String>();
7 map.put("url", url);
8 map.put("getRedirect_uri", openPlatformRedirect_uri); //openPlatformRedirect_uri为配置⽂件⾥的域名(开放平台配好的)
9 return map;
10 }
解释代码:
openPlatformAppId为⾃⼰的AppId,
openPlatformRedirect_uri为⾃⼰配的域名,(请忽略我的⽅法命名和参数命名...别学我!)
这⾥提⼀下,登录的scope=snsapi_login,公众平台⾥scope有userInfo(⽤户有感知)和baseInfo(⽤户⽆感知,静默授权)
返回给controller,controller重新请求⼀遍地址,这时候进⼊的是回调地址了,⾥⾯就会有code参数,根据code参数就可以拿access_token了,controller代码:
1 @RequestMapping(value = "/wxLoginCheck", method = RequestMethod.GET)
2 @ResponseBody
3public String wxLoginCheck() {
4 Map<String, String> weixinLoginUrl = alarmWxMessageService.weixinLoginUrl();
5 String url = ("url");
6return "<script>location.href='" + url + "'</script>";
7 }
这时候return的回调地址变成了第⼀步回调地址参数的那个地址("/getWxLoginCode"),域名没写了
第⼆步,通过code获取access_token
接⼝中参数如下:
⾃⼰代码:
controller:
1 @RequestMapping(value = "/getWxLoginCode", method = RequestMethod.GET)
2public String getWxLoginCode(String code) {
3 WeixinOauth2Token wxot=alarmWxMessageService.wxLogingetCode(code);
4 String openId = OpenId();
5 String accessToken = AccessToken();
6 }
解释代码:
code直接能拿到了,WeixinOauth2Token 为实体类,封装openId和access_token之类字段
serviceImpl:
1 @Override
2public WeixinOauth2Token wxLogingetCode(String code) {
3 WeixinOauth2Token wat = null;
4 String getTokenUrl = "api.weixin.qq/sns/oauth2/access_token?appid=" + openPlatformAppId
5 + "&secret=" + openPlatformAppSecret
6 + "&code=" + code
7 + "&grant_type=authorization_code";
8// 获取⽹页授权凭证
9 JSONObject jsonObject = JSONObject.fromObject(HttpUtil.Get(getTokenUrl));
10if (jsonObject != null) {
11try {
12 wat = new WeixinOauth2Token();
13 wat.String("access_token"));
14 wat.String("openid"));15 } catch (Exception e) {
16 wat = null;
17int errorCode = Int("errorCode");
18 String errorMsg = String("errorMsg");
19 ("获取⽹页授权失败errorCode=" + errorCode + ",errorMsg=" + errorMsg);
20 }
21 }
22return wat;
23 }
解释代码:
openPlatformAppId为⾃⼰的AppId,
openPlatformAppSecret为⾃⼰的密码,
code为之前获取到的code,
json那⼀段是重新发送⼀个get请求,⽅法在HttpUtil⾥封装的,下⾯贴出。
1/**
2 * 向指定URL发送GET⽅法的请求
3 *
4 * @param url 发送请求的URL
5 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
6 * @return URL 所代表远程资源的响应结果
7*/
8public static String Get(String url) {
9int connectionTimeOut=HTTP_CONNECTION_TIMEOUT, readTimeOut =HTTP_READ_TIMEOUT;
10 String result = "";
11 BufferedReader in = null;
12 String urlNameString = url;
13try {
14 logger.info("请求url+参数:" + urlNameString);
15 URL realUrl = new URL(urlNameString);
16// 打开和URL之间的连接
17 URLConnection connection = realUrl.openConnection();
18// 设置通⽤的请求属性
19 connection.setRequestProperty("accept", "*/*");
20 connection.setRequestProperty("connection", "Keep-Alive");
21 connection.setConnectTimeout(connectionTimeOut);
22 connection.setReadTimeout(readTimeOut);
23// 建⽴实际的连接
24 t();
25// 获取所有响应头字段
26// 定义 BufferedReader输⼊流来读取URL的响应
27 in = new BufferedReader(new InputStream()));
28 String line;
29while ((line = in.readLine()) != null) {
30 result += line;
31 }
32 } catch (Exception e) {
33 ("发送GET请求出现异常!url: " + urlNameString + ", " + e);
34 }
35// 使⽤finally块来关闭输⼊流
36finally {
37try {
38if (in != null) {
39 in.close();
40 }
41 } catch (Exception e2) {
42 ("close exception", e2);
43 }
44 }
45return result;
46 }
代码转换到这⾥,已经授权完了,能拿到⽤户的openId,⽤这个去完成公司相关业务。⽂档上⾯的刷新access_token没有做,⾃⼰可以去了解下
后来做完了,推送消息那边要拿我这个openId,才发现,登录是开放平台的,推送消息是公众平台的,平台都不⼀样,openId肯定不⼀样,所以⼜重新开发⼀遍登录,什么东西都是⾃⼰实现。。。。。。
注意:unionId,统⼀管理多个或者多个应⽤⽽产⽣的⼀个机制,像这次开发的,开放平台和公众平台不能⽤这个
个⼈总结⼀下,开发⼀个东西之前,思路⼀定要理清,不然会绕来绕去把⾃⼰绕晕,技术都不是问题,重要的是思路;
代码部分,命名符合规范,让⼈看的懂是什么意思,注释也要全,让⼈明⽩写的什么;
登录模块要好好研究⼀下,调⽤登录⽅法去登录,实现的原理和登录时安全问题要考虑到;
技术上新⽤ModelMap这个对象,后台存储:map.put("名字","值"),前台直接拿:var corpUsers = '${requestScope.名字}';
List Map json 互相转换、传值、接收值;
重发请求的GET、POST⽅法;
spring重定向、jsp重定向等。
开发⼩⽩,如果有错误的地⽅尽请⼤佬们指出,谢谢
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论