【尚医通】微信扫码登录和手机号登录冲突问题解决思路

2023-05-16

【尚医通】微信扫码登录和手机号登录冲突问题解决思路

问题描述

最近做尚医通遇到一个问题,微信扫码登录手机号登录特殊情况 下会发生冲突,导致无法登录的问题。下面就描述一下几种情况。

正常情况:用户第一次一上来就使用微信扫码登录,后端在调用回调函数的时候就完成了用户注册,由于是第一次登录,需要绑定手机号,于是又调用了一次手机号登录的接口,手机号登录成功之后就完成了绑定。之后就可以随便使用扫码登录或手机号登录了。

特殊情况:用户第一次一上来就使用手机号登录,后端会根据手机号去数据库搜索“唯一”的一条数据,如果结果为空则说明是第一次登录,直接注册;如果不为空,说明已经注册过,就直接登录。用户第二次登录时使用的是微信扫码登录,后端在调用回调函数的时候再次完成用户注册,然后又绑定手机号。那么现在数据库就有两条手机号相同的数据了。第三次登陆时若使用手机号登录,那么“唯一”查询就不满足了,就会报错,最后登录不了。


回顾流程

首先回顾一下扫码登录的流程。

在这里插入图片描述

更多详情请见:资源中心 - 微信开放平台 (qq.com)

解决思路

上回调函数代码!

//微信扫描后回调的方法
    @GetMapping("/callback")
    public String callback(@RequestParam("code") String code, @RequestParam("state") String state) {
        //1.获取临时票据 code
        log.info("code:{}", code);
        //2.拿着code和微信id和密钥,请求微信固定地址,得到两个值
        //2.1使用code和appid以及appscrect换取access_token
        // %s表示一个占位符
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                ConstantWxPropertiesUtil.WX_OPEN_APP_ID,
                ConstantWxPropertiesUtil.WX_OPEN_APP_SECRET,
                code);
        //3.使用httpclient请求这个地址
        try {
            String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);
            log.info("accesstokenInfo:{}", accesstokenInfo);
            //4.从返回字符串中获取两个值 openid 和access_token
            JSONObject jsonObject = JSON.parseObject(accesstokenInfo);
            String access_token = jsonObject.getString("access_token");
            //openid为每个微信用户唯一
            String openid = jsonObject.getString("openid");
            log.info("access_token:{}", access_token);
            log.info("openid:{}", openid);
            //5.根据access_token获取微信用户的基本信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);
            String resultInfo = HttpClientUtils.get(userInfoUrl);
            log.info("resultInfo:{}", resultInfo);
            JSONObject resultUserInfoJson = JSON.parseObject(resultInfo);
            //6.解析用户信息
            //6.1用户名称
            String nickname = resultUserInfoJson.getString("nickname");
            //6.2用户头像
            String headimgurl = resultUserInfoJson.getString("headimgurl");

            //7.如果第一次微信登录添加到数据库
            UserInfo userInfo = userInfoService.saveUser(nickname, openid);

            //8.返回name和token字符串
            String name = userInfo.getName();
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            //判断userInfo是否有手机号,如果手机号为空,返回openid
            //如果手机号不为空,返回openid值是空字符串
            //前端根据“openid”判断:如果openid为空,已绑定手机号(不需要再绑定手机号),否则需要绑定手机号
            if (StringUtils.isEmpty(userInfo.getPhone())) {
                openid = userInfo.getOpenid();
            } else {
                openid = "";
            }
            //使用jwt生成token字符串
            String token = JwtHelper.createToken(userInfo.getId(), name);
            //跳转到前端页面
            return "redirect:" + ConstantWxPropertiesUtil.YYGH_BASE_URL
                    + "/weixin/callback?token=" + token + "&openid="
                    + openid + "&name=" + URLEncoder.encode(name, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

问题主要出现在第七步。

解决思路如下:

  1. 如果数据库中已经存在了手机号登录时的数据,那么微信登录时就不应该再向数据库中添加数据。
  2. 但是在回调函数中我们无法通过手机号查询数据库。所以我们无法在回调函数中实现是否注册的判断,那不如索性把第七步给删了,改成只搜索用户信息,不保存用户信息

回调函数中无法一口气解决所有的问题,所以我们只得把重心调转到登录方法上。

上登录方法代码!!!:

//手机号登录接口
    @Override
    public Map<String, Object> loginUser(LoginVo loginVo) {
        //1.从loginVo获取输入的手机号和验证码
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        //2.判断手机号和验证码是否为空
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(code)) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }
        //3.判断手机验证码和输入的验证码是否一致
        String redisCode = redisTemplate.opsForValue().get(phone);
        if (!code.equals(redisCode)) {
            throw new YyghException(ResultCodeEnum.CODE_ERROR);
        }

        //4.绑定手机号
        UserInfo userInfo = null;
        if (!StringUtils.isBlank(loginVo.getOpenid())) {
            userInfo = this.selectWxInfoByOpenId(loginVo.getOpenid());
            if (null != userInfo) {
                userInfo.setPhone(loginVo.getPhone());
                updateById(userInfo);
            } else {
                throw new YyghException(ResultCodeEnum.DATA_ERROR);
            }
        }
        //5.如果userinfo为空,进行正常的手机登录
        if (userInfo == null) {
            //判断是否第一次登录:根据手机号查询数据库,如果不存在相同手机号就是第一次登录
            LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserInfo::getPhone, phone);
            userInfo = baseMapper.selectOne(queryWrapper);
            if (userInfo == null) {
                //第一次登录,添加信息到数据库
                userInfo = new UserInfo();
                userInfo.setName("");
                userInfo.setPhone(phone);
                userInfo.setStatus(1);
                baseMapper.insert(userInfo);
            }
        }


        //6.校验是否禁用
        if (userInfo.getStatus() == 0) {
            throw new YyghException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }
        //7.不是第一次,直接登录
        //返回登录信息
        //返回登录用户名
        //返回token信息
        Map<String, Object> map = new HashMap<>();
        String name = userInfo.getName();
        if (StringUtils.isBlank(name)) {
            name = userInfo.getNickName();
        }
        if (StringUtils.isBlank(name)) {
            name = userInfo.getPhone();
        }
        map.put("name", name);
        // token生成
        String token = JwtHelper.createToken(userInfo.getId(), name);
        map.put("token", token);
        return map;
    }

我们重写第4步代码。

解决思路如下:

在第4步绑定手机号的时候,我们先根据手机号把用户给查询出来。

  1. 如果用户存在且还没设置openid,那么我们就将前端传过来的openid设置给该用户,完成绑定;
  2. 如果用户存在且也已经设置了openid,那么我们直接抛一个异常,提示前端该手机已经绑定了微信号。
  3. 如果用户不存在,那么我们利用openid,phone直接注册一个新用户并登录,实现注册,绑定,登录一条龙。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【尚医通】微信扫码登录和手机号登录冲突问题解决思路 的相关文章

  • 解决UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position

    在抓取网页上面的一些源代码的时候 xff0c 将uft 8的编码写入文档 xff0c 并输出的时候 xff0c 出现这了这个报错 xff0c 说gbk无法编码 xbb 查找相关资料 xff1a 1 str转bytes叫encode xff0
  • FIFO(First-In First-Out)先进先出页面置换算法详解

    FIFO xff08 First In First Out xff09 先进先出页面置换算法 xff1a FIFO淘汰算法总是淘汰最先装入内存的页面 xff0c 即选择在内存中驻留时间最久的页面进行淘汰 该算法实现只需把一个进程已调入内存的
  • 解决方法:git遇到过的错误

    用git也是走了很多弯路 比如 xff1a 这种错误 1 git commit a fatal Unable to create 39 E git index lock 39 File exists Another git process
  • 路径规划学习入门

    运动规划简介 当虚拟人开始一次漫游时 xff0c 首先全局规划器根据已有的长期信息进行全局静态规划 xff0c 确定虚拟人应该经过的最优化路线 然后全局规划器控制执行系统按照该路径运动 在运动过程中 xff0c 感知系统会持续对周围环境进行
  • 测试开发工程师面试题目

    测试开发工程师面试题目 1 什么是兼容性测试 兼容性测试侧重哪些方面 主要检验的是软件的可移植性 xff0c 检查软件在不同的硬件平台软件平台上是否可以正常的运行 细分会有 xff1a 平台的兼容 xff0c 网络兼容 xff0c 数据库兼
  • 【ROS2】四、使用tf坐标变换实现小海龟跟随

    1 创建功能包 创建工作空间并在工作空间下创建功能包 xff1a span class token function mkdir span p turtle tf ws src span class token builtin class
  • 滑模控制简单理解(hm-1)

    变结构控制 xff08 VSC xff09 是一种特殊的非线性控制器 xff0c 表现为控制的不连续性 xff0c 又称滑模控制 xff08 SMC xff09 一般步骤为滑模面的设计 趋近率的设计 控制器的求解 滑模控制的理解 如图所示
  • BP神经网络的数学本质

    原创文章 xff0c 转载请说明来自 老饼讲解 BP神经网络 xff1a bp bbbdata com 目录 一 隐神经元与tansig函数 二 BP本质 三 BP神经网络的曲线拟合要素 一 误差函数 二 拟合基函数 三 待解参数与求解算法
  • GAZEBO_PLUGIN_PATH 设置方法

    http answers gazebosim org question 13391 how to set gazebo plugin path correctly and add the plugin into gazebo ros Hi
  • Linux 0.11 系统调用的实现机制

    Linux 0 11 系统调用的实现机制 一 系统调用概述 系统调用本质上是一种中断 xff0c 中断号为0x80 xff0c 即128号中断 通常我们使用的是库函数 xff0c 而不是直接使用系统调用 xff0c 这主要是因为库函数一般都
  • 滤波算法及优缺点

    传感器比如关节力矩传感器采用滑动平均滤波算法 xff0c 滤波点数选1则为原始数据 xff0c 选点数100则采样100个求平均 点数越大滤波延迟越大 xff0c 越平滑 所以需要根据实际项目测试 在matlab中采用了三种滤波方法 xff
  • putty支持多标签,支持log每行加时间

    在现在的免费telnet 串口连接工具中 Tera Term 支持脚本ttl 且有每行时间记录 有一个不好的是个终端连接不友好 xff0c 也能用 xff0c 就是看起来不方便 xff0c 是一个外挂的补丁 putty 不支持多标签 不支持
  • Jetson xavier nx 入门系列—— jeston系列性能对比

    官方对比网址 xff1a https developer nvidia com embedded develop hardware family 算力对比 参考 xff1a https blog csdn net u013673476 ar
  • 在C语言中,字符串总是以‘\0‘作为结尾

    字符串结束标志 xff08 划重点 xff09 字符串是一系列连续的字符的组合 xff0c 要想在内存中定位一个字符串 xff0c 除了要知道它的开头 xff0c 还要知道它的结尾 找到字符串的开头很容易 xff0c 知道它的名字 xff0
  • cmake 学习笔记(一)

    最大的Qt4程序群 KDE4 采用cmake作为构建系统Qt4的python绑定 pyside 采用了cmake作为构建系统开源的图像处理库 opencv 采用cmake 作为构建系统 看来不学习一下cmake是不行了 xff0c 一点一点
  • 如何用github创建博客

    1 创建一个仓库 xff0c 设置名称为用户名 github io xff0c 不然会报404 2 在设置中找到github pages选项 xff0c 选择theme 3 将仓库使用github客户端克隆到本地 4 将克隆到本地仓库内容清
  • VS创建的aspx文件下没有设计-拆分-源 并且工具箱中的控件为灰色

    首先在视图中打开工具箱 这时是没有控件的 右键点击全部显示 但是仍然是灰色 没法使用 我的 Master文件夹里有设计 拆分 源 但是aspx文件里没有 解决方法
  • 【支线】输电杆塔识别-YOLO v5在Aidlux的部署

    目录 0 前言1 模型训练1 1 任务描述1 2 输电杆塔数据集采集1 3 输电杆塔数据集标注1 4 数据增强1 5 折腾1 6 训练1 7 测试 2 NX部署2 1 软硬件2 2 Tensor RT 优化推理2 3 ROS Topic发送
  • 程序员与厨师

    不管你信不信 反正我是信了 每一个程序员上辈子都是呆在厨房的厨子 好吧 你不信 我来证明给你看 1 下厨前 你得知道做的是早餐还是中晚餐 中晚餐的话 怎么也得走趟超市 如遇到好友聚会 怎么着也得做出一桌对得起朋友的饭菜 还有你得分析 朋友中
  • 用研扬科技的UP Square做软路由是不是杀鸡用牛刀啊?

    折腾了好几遍终于整踏实了 xff01

随机推荐

  • 炎炎夏日,看小Y重燃烈焰战火——Y450外接显卡

    xfeff xfeff 目录 前言 实际效果 预算VS结算 配件开箱 硬件连接 软件环境配置 xff08 重点 xff09 前言 我家小Y已经陪伴我4年多了 xff0c 四年里 xff0c 她带给我的欢乐是超值的 xff08 联保了4年多
  • 深度学习情感分类常用方法(综述)

    论文原文 xff1a Deep Learning for Sentiment Analysis A Survey 原文地址 xff1a https arxiv org ftp arxiv papers 1801 1801 07883 pdf
  • 嵌入式单片机之stm32串口你懂了多少!!

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术 xff0c 相信大家都有所接触 xff0c 今天这篇就给大家详细的分析下有关于stm32的出口 xff0c 还不是很清楚的朋友要注意看看了哦 xff0c 在最后还会为大家分享有些关
  • uC/OS-II 学习笔记之:消息邮箱

    更多原创 uC OS II学习笔记之 xff1a 系列 基础及嵌入式相关知识详解 xff0c 请访问可乐虎博客 xff1a http blog csdn net dcx1205 相信不会让您失望 xff01 xff01 一 消息邮箱的概念
  • uC/OS-II 学习笔记之:信号量、消息邮箱、消息队列之间的使用区别

    更多原创 uC OS II学习笔记之 xff1a 系列 基础及嵌入式相关知识详解 xff0c 请访问可乐虎博客 xff1a http blog csdn net dcx1205 相信不会让您失望 xff01 xff01 1 用信号量进行行为
  • Python3抓取糗百、不得姐、kanqu.com

    测试电脑配置有点低 xff0c 正常配置速度会比较快 有问题可以加群 xff1a 544471255 交流 使用必看 1 该代码使用Python3 6 43 版本 2 需要安装依赖库如下 可使用类似 pip install requests
  • 基于STM32F4实现FOC(磁场定向控制)一:电流采样和波形产生

    一 xff0e ADC的配置问题 1 GPIO初始化配置 开始ADC对应的GPIO口 xff0c 本驱动程序使用到五个GPIO xff0c 分别对应U V W三相电流及母线电压和温度采样 xff0c 统一配置为模拟输入 GPIO的配置代码如
  • 基于ADRC的FOC位置环控制

    ADRC位置环控制 ADRC介绍1 非线性跟踪微分器2 非线性ESO观测器3 非线性状态误差反馈控制律原理 NLSEF 4 调参流程 xff1a 1 调TD2 调ESO3 调NLSEF 5 基于ADRC的位置环设计ADRC框图基于ADRC的
  • 结构体和联合体在通信协议解析的应用

    在串口通信中 xff0c 我们往往会解析很多协议 xff0c 而且在协议中会出现不同数据类型的协议 xff1b 当然我们也可以把协议都定义成某一种数据格式 xff0c 但是那样会出现协议的复杂度 xff0c 但是不那样处理的话 xff0c
  • ubuntu14.04 怎么查看哪个串口才是有效的搜索?

    使用以上命令 xff0c 可以看见相对应的芯片型号 比如图中的 xff0c cp210x 对应的 ttyUSB0 FT232RL 对应 ttyUSB1 minicom 命令 xff1a CTRL 43 A 然后 O xff1b
  • 13_STM32Cubeide开发_RS485总线驱动

    一 485总线和硬件电路 典型的串行通讯标准是RS232和RS485 xff0c 它们定义了电压 阻抗等 xff0c 但不对软件协议给予定义 RS 485总线标准规定了总线接口的电气特性标准即对于2个逻辑状态的定义 xff1a 正电平在 4
  • 无人机系列之飞控算法

    一 无人机的分类 按飞行平台构型分类 无人机可分为固定翼无人机 旋翼无人机 无人飞艇 伞翼无人机 扑翼无人机等 图1 无人机平台构型 多轴飞行器multirotor 是一种具有三个以上旋翼轴的特殊的直升机 旋翼的总距固定而不像一般直升机那样
  • Java中==和equals的区别

    Java中 61 61 和equal的区别为 1 61 61 表示 判断2个变量或对象实例是否指向同一个内存空间 xff0c equals 表示 判断2个变量或对象实例所指向的内存空间的值是否相同 2 61 61 表示 对内存地址进行比较
  • Android注解(annotation)介绍及其应用

    我的新书 Android App开发入门与实战 已于2020年8月由人民邮电出版社出版 xff0c 欢迎购买 点击进入详情 文章目录 介绍自定义注解注解的应用 xff1a 反射注解的应用 xff1a APT其它 介绍 Annotation
  • 源代码管理的另类比较:TortoiseGit vs SourceTree

    文章目录 源代码得管理那就Git吧图形化Git管理软件对比暗色主题图形分支与提交历史仓库与工程代码改动对比分支切换提交到多个远端仓库编码UTF8与Ansi总结 Git提供网站免费部分对比GitHubGitee华为云总结 源代码得管理 以往用
  • kali Linux使用putty远程连接输入密码一直提示错误

    使用命令打开配置文件 xff1a leafpad etc ssh sshd config 修改AddressFamily any 前面的 删除修改PermitRootLogin yes 前面的 删除 修改PasswordAuthentica
  • ros安装并测试是否安装成功

    目录 一 xff0c 安装步骤二 xff0c 测试是否安装成功 一 xff0c 安装步骤 1 xff0c 首先前4项勾选 xff0c 然后源换成国内清华的源 2 xff0c 打开终端开始输入命令 xff1a span class token
  • C++ 双冒号::符号详解

    一 作用域符号 xff1a 作用域符号 的前面一般是类名称 xff0c 后面一般是该类的成员名称 xff0c C 43 43 为例避免不同的类有名称相同的成员而采用作用域的方式进行区分 例如 xff1a A B 表示两个类 xff0c 在
  • 嵌入式软件工程师前期职业生涯规划

    ARM 43 LINUX路线 xff0c 主攻嵌入式Linux操作系统及其上应用软件开发目标 xff1a xff08 1 xff09 掌握主流嵌入式微处理器的结构与原理 xff08 初步定为arm9 xff09 xff08 2 xff09
  • 【尚医通】微信扫码登录和手机号登录冲突问题解决思路

    尚医通 微信扫码登录和手机号登录冲突问题解决思路 问题描述 最近做尚医通遇到一个问题 xff0c 微信扫码登录和手机号登录在 特殊情况 下会发生冲突 xff0c 导致无法登录的问题 下面就描述一下几种情况 正常情况 xff1a 用户第一次一