多平台统一管理软件接口,如何实现多平台统一管理软件接口
274
2022-08-27
Java如何优雅的实现微信登录注册
目录引言问题分析解决思路方案实现最后
引言
今天我们来聊一聊微信登录注册遇到的一些事儿。
在我们的业务系统中,一个用户在系统中肯定会有一个唯一标识,并且这个唯一标识一般是从系统外部获取的,而不是系统自动生成的,例如:手机号或者身份证。
但是,理想很丰满,现实很骨感,我们遇到的情况肯定不会如此的简单。
问题分析
当一个系统运行的足够久,用户量足够多,那么你总会遇到各种奇奇怪怪的问题。
在上一节,我们知道正常情况遇到的场景会比较简单,用户、微信号、手机号三者是1:1:1的关系,也就说三者可以等价,我用其中一个信息,总是可以查询出另外两个的信息,例如:我可以用手机号,查询出用户ID和微信openid。
所以,根据以上思路,我们很容易设计出用户表:cus_info ,基本表结构如下:
用户ID微信openid用户手机号逻辑删除其他字段idopenidmobiledel_flg...
但是当遇到以下2个场景的时候,这个表结构设计就无法满足需求了。
一个用户2个微信号有些用户是拥有两个微信号,并且绑定同一个手机号(这个逻辑可以通过微信换绑手机号实现)。
在这个场景下,一旦用户换了个微信号登录进入系统的时候,根据微信openid进行登录,因为表数据找不到该openid,则走注册流程;在注册的时候,又根据手机号查询用户信息,发现用户已经存在,返回登录流程,最终造成逻辑死循环。
一个用户2个手机号另外还有一些用户拥有2个手机号,并且绑定同一个手机号(这个逻辑在用户授权手机号的时候添加另外一个手机号实现)。
在这个场景下,第一次用户使用手机号A注册并登录,我们在后端绑定了手机号A和对应的微信openid;第二次用户使用手机号B注册并登录,这时候数据库会有2条记录,不同手机号相同的openid。这样子会导致在某些场景下(例如支付回调),根据openid获取用户信息的时候,找到2个用户,从而导致业务异常。
解决思路
以上2个问题,在不同的业务场景下,不同的人会有不同的解法。有以手机号作为用户的唯一标识,有以微信openid作为用户唯一标识。在这里,我们提供以手机号作为用户唯一标识的解法。
在这里,我们认为一个手机号就是一个用户,一个用户会有多个微信号。关系如下:
一个用户2个微信号针对该问题,我们在登录注册的时候,会通过逻辑控制,保证一个手机号只能找到一个微信openid。处理方式如下:
根据当前的手机号查询到所有的微信openid,做逻辑删除处理根据当前的openid查询到所有的手机号,做逻辑删除处理根据当前手机号和openid查询是否存在记录,如果不存在则新增,如果存在则逻辑删除标识重置为正常。
一个用户2个手机号针对该问题,我们在业务上做处理。因为我们认为了一个手机号就是一个用户,如果一个用户拥有两个手机号,那么在我们系统上我们认为是两个用户,他们的数据是相互独立的。
另外在这个场景下,我们还需要提供一个手机号换绑的功能。这样当用户有2个手机号,也能给实现切换的需求。
方案实现
以上,相关解决思路我们有了。那么接下来就是设计和编码。
根据以上,我们会设计如下2张表结构:
cus_info 用户信息表
用户ID用户手机号逻辑删除其他字段idmobiledel_flg...
cus_wx_info 用户和微信关联表
ID用户手机号微信appId微信openid开放平台unionid逻辑删除其他字段idmobileapp_idopenidunioniddel_flg...
接着我们实现一个注册方法。
@Service
public class CsInfoServiceImpl implements CsInfoService {
@Autowired
private CsInfoRepository csInfoRepository;
@Autowired
private CsWxInfoRepository csWxInfoRepository;
@Autowired
private CsInfoConvert csInfoConvert;
@Override
@Transactional(rollbackFor = Throwable.class, timeout = 60)
public CsWxInfoDTO register(CsInfoRegisterDTO param) {
// 根据手机号查询用户信息
CsInfo info = csInfoRepository.infoByMobile(param.getMobile());
Long id = info == null ? 0 : info.getId();
// 如果用户不存在,则创建
if(id == 0){
id = csInfoRepository.create(param.getMobile(), param.getRegisterSource().getCode());
}
// 逻辑删除当前手机号绑定的openid
// 逻辑删除当前openid绑定的手机号
csWxInfoRepository.handleOpenidMobileUnique(param.getMobile(), param.getOpenid(), param.getAppId());
// 保证当前手机号和openid在系统中1:1的关系
CsWxInfo wxInfo = csWxInfoRepository.infoByMobileOpenid(param.getMobile(), param.getOpenid(), param.getAppId());
if(wxInfo == null){
wxInfo = new CsWxInfo();
wxInfo.setAppId(param.getAppId());
wxInfo.setMobile(param.getMobile());
wxInfo.setOpenid(param.getOpenid());
wxInfo.setUnionid(param.getUnionid());
wxInfo.setAvatarUrl(param.getAvatarUrl());
wxInfo.setNickName(param.getNickName());
csWxInfoRepository.save(wxInfo);
}else{
CsWxInfo model = new CsWxInfo();
model.setId(wxInfo.getId());
model.setDelFlg(Integer.valueOf(DelFlgEnum.NORMAL.getCode()));
csWxInfoRepository.updateById(model);
}
CsWxInfoDTO result = csInfoConvert.getCsWxInfoDTO(wxInfo);
result.setInfoId(id);
return result;
}
}
其中handleOpenidMobileUnique方法对应的SQL处理如下:
update cs_wx_info set del_flg = 0 ,update_time = now()
del_flg = 1
and app_id = #{appId}
and openid = #{openid}
and mobile != #{mobile}
update cs_wx_info set del_flg = 0 ,update_time = now()
del_flg = 1
and app_id = #{appId}
and mobile = #{mobile}
and openid != #{openid}
最后
至此,关于微信登录注册遇到的一些小问题,我们找到了一个相对比较好解决方案,你还不快实践到你自己项目上去?
相关源码地址:Anyin Cloud
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~