体验
我的小程序
前期准备
个人网站
个人小程序
概述
自己搞了个人网站和小程序之后,发现各种各样的限制真的好多;最近做了一个小程序,给它配一个PC网站,就遇上了各种各样的问题,废话就不多说,先看思维导图。
整体流程
实现逻辑核心思想
核心是用户扫小程序一个页面的二维码,来通知网站用户已在微信小程序登录。
具体步骤
1.用户打开网站的的登录页面时,前端页面通过生成一个随机码(这个随机码是串联整个登录流程的信息),请求访问后端服务
这里的scene就是随机码,url为图片展示地址
scene = decodeURIComponent(Date.now());
url.value = `${servUrl}/login/qrcode?scene=${scene}`;
2.后端服务缓存随机码,用作记录这次登录的情况,带着随机码调用微信服务getUnlimitedQRCode接口,获取二维码图片流
注意,这里涉及到access_token这个参数,这是调用微信服务的凭据,每获取一次的默认生效时间是7200秒,获取access_token需要用到个人小程序的appId和secret,这些调用微信服务接口的实现,没放在前端的原因就是会暴露个人小程序的appId和secret
HashMap<String, Object> params = new HashMap<>();
params.put("scene", scene);
params.put("env_version", wechatConfig.getEnv());
params.put("check_path", false);
params.put("page", "pages/login/login");
InputStream inputStream = RestTemplateUtil.sendPostByJson(wechatConfig.getQrCodeUrl()+"?access_token="+token, params, InputStream.class);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\""+ IdUtil.getSnowflakeNextIdStr() +".png\"");
try {
IoUtil.copy(inputStream, response.getOutputStream());
} catch (IOException e) {
throw new BizException();
}finally {
IoUtil.close(inputStream);
}
3.前端加载完成返回的图片,立刻开始轮询登录状态,如登录成功,立刻完成登录
前端:
if(res.isFinish && res.state == 'SUCCESS'){
setToken(res.token)
loginFinish = true;
setCookie("user", res.user)
store.commit("login", res.user)
messageSucc("登录成功")
}if(res.isFinish && res.state == 'CANCEL'){
qrcodeExpire.value = true;
}else{
if(!loginFinish){
setTimeout(() => handleLoadLoginState(), 1000);
}
}
后端:
String userId = WechatLoginCache.getScene(scene);
if(userId == null){
return new LoginState().setIsFinish(true).setState(WechatQrCodeLoginState.CANCEL);
}
if(WechatLoginCache.CACHE_INIT_VALUE.equals(userId)){
return new WechatQrCodeLoginStateVo().setIsFinish(false).setState(WechatQrCodeLoginState.LOGGING);
}
User user = userGateway.findOne(userId);
return new LoginState()
.setIsFinish(true)
.setState(WechatQrCodeLoginState.SUCCESS)
.setToken(LoginRegisterUtils.buildLoginVo(user).getToken())
.setUser(UserBuilder.toVo(user));
4.用户通过返回来的二维码扫码,就会带着随机码scene访问到小程序的页面(pages/login/login),在小程序就可以获取到微信用户的唯一ID,完成登录操作
前端
onLoad(options) {
scene = options.scene;
wx.login({
success: (res) => {
wechatLogin({ code }).then(res2 => {
const { token, user } = res2.data;
wx.setStorageSync('token', token)
wx.setStorageSync('user', user)
wx.switchTab({
url: '/pages/home/home',
})
updateWechatLogin({scene, userId: user.id, state:'SUCCESS'});
})
}
})
}
后端
WechatQrCodeLoginState state = param.getState();
if(state == WechatQrCodeLoginState.FAIL || state == WechatQrCodeLoginState.CANCEL){
WechatLoginCache.removeScene(scene);
return;
}
if(state == WechatQrCodeLoginState.SUCCESS){
WechatLoginCache.updateScene(scene, param.getUserId());
}
5.到此,整个实现逻辑已完成,感谢完成阅读
以上参考的内容来自《个人网站实现微信扫码登录》
在此抛转引玉,有不对的地方请大家指出,共同讨论、进步。