思路:
- uniapp通过appid获取jscodo
- 调用后端接口,利用jscode、appid、secret获得openId
- 后端鉴别用户openId是否已注册,是登录成功,否则需要注册或绑定手机号
操作列子
- Uniapp登录按钮
<button @click="wxLogin" class="login-btn cu-btn block bg-blue lg round" type="primary">微信登录</button>
- 登录获得jscode
// 微信登录,这里获得 jscode 传给后端去获取openID
async wxLogin() {
this.$modal.loading("登录中,请耐心等待...")
var that=this;
uni.login({
provider: "weixin",
success: function(res) {
console.log(res.code)
that.$store.dispatch('WXLogin', res.code).then(() => {
that.$modal.closeLoading()
that.loginSuccess()
}).catch(() => {
})
},
});
},
- uniapp的Store Action中访问后端接口,获得token
// 微信登录
WXLogin({commit}, jscode) {
console.warn(jscode)
//后端接口去验证 jscode 获得的OpenID是否存在,存在则说明该用户登录成功,返回token
//在后端获取OpenID是安全的操作
return new Promise((resolve, reject) => {
wxLogin(jscode).then(res => {
setToken(res.data.access_token)
commit('SET_TOKEN', res.data.access_token)
resolve()
}).catch(error => {
reject(error)
})
})
},
4.Java后端接口,利用appid、jscode、secret获得openId,然后刷新token
public LoginUser wxLogin(String jsCode) {
if (StringUtils.isAnyBlank(jsCode)) {
recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "微信登录的JsCode为空");
throw new ServiceException("微信登录的JsCode为空");
}
try {
// 这里应该优化,需要数据库建立一个表单,记录小程序的appid,传上来后,后端这里通过appid获取secret,这样可以适配多个小程序
String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=(你的AppId)&secret=(你的Secret)&grant_type=authorization_code&js_code=%s", jsCode);
//获取微信OpenID
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
//RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url(url)
.get()
.build();
Response response = client.newCall(request).execute();
String openid="";
if(response.isSuccessful()){
String res = response.body().string();
System.out.printf(res);
// 对应获取对象
JSONObject object= JSONObject.parseObject(res);
// 如果所含对象的值 是null 返回的值 并不是对象 null 只是一个字符串 null
openid=object.getString("openid");
}
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfoByOpenId(openid, SecurityConstants.INNER);
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "jsCode对应的OpenID用户不存在");
throw new ServiceException("jsCode:" + jsCode + " 对应的OpenID用户不存在");
}
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + jsCode + " 已被删除");
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + jsCode + " 已停用");
}
recordLogService.recordLogininfor(userInfo.getUsername(), Constants.LOGIN_SUCCESS, "微信JsCode登录成功");
return userInfo;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
- 当然这里我个人觉得需要优化的地方是,前端把appid,jscode一起传参。后端多租户即可实现按照不同的appid来处理用户的token