手机验证码登录以及发送短信通知

一、注册微信公众号

进入微信公众平台:微信公众平台 (qq.com)注册账号类型选择 订阅号 ,填写信息完成注册

二、开通腾讯云短信服务

搜索短信,免费领取
在这里插入图片描述

三、申请短信签名与模版

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
填写参数,每个参数官方都提供了说明,右侧会根据填写的参数自动生成相关的代码
在这里插入图片描述
在这里插入图片描述

三、编写发送短信的工具类
@Slf4j
public class SmsUtil {
    /**
     * 发送短信
     */
    public static boolean send(SmsVo smsVo) throws TencentCloudSDKException {
        // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
        String secretId = "AKIDkSDpFRPAi2MXVotHXgZMzUlofIhwxkLi";
        String secretKey = "FIBqJrOkyzuoZ9Yn170gGpKsFUXSAh7I";
        Credential cred = new Credential(secretId, secretKey);

        // 实例化一个http选项,可选的,没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("sms.tencentcloudapi.com");
        // 实例化一个client选项,可选的,没有特殊需求可以跳过
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        SmsClient client = new SmsClient(cred, "ap-beijing", clientProfile);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        SendSmsRequest req = new SendSmsRequest();
        String[] phoneNumberSet1 = {"+86" + smsVo.getPhone()};
        req.setPhoneNumberSet(phoneNumberSet1);

        req.setSmsSdkAppId("1400829403");
        req.setSignName("朝月余晖");
        req.setTemplateId(smsVo.getTemplateId());
        req.setTemplateParamSet(smsVo.getParam());

        // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
        SendSmsResponse resp = client.SendSms(req);
        //获取响应数据中的Code
        SendStatus sendStatus = resp.getSendStatusSet()[0];
        String code = sendStatus.getCode();
        if("Ok".equals(code)){
            return true;
        }
        //记录错误日志
        log.error(sendStatus.getMessage());
        return false;
    }
四、编写后端发送短信验证码的接口
 @ApiOperation("发送验证码")
    @GetMapping("/sendCode/{phone}")
    public R sendCode(@PathVariable String phone) throws TencentCloudSDKException {
        Boolean key = redisTemplate.hasKey(phone);
        if (key) {
            return R.ok();
        }
        String code = RandomUtil.getFourBitRandom();
        int time = 5;
        redisTemplate.opsForValue().set(phone, code, time, TimeUnit.MINUTES);
        SmsVo smsVo = new SmsVo();
        smsVo.setPhone(phone);
        smsVo.setTemplateId("950651"); //短信模版ID
        smsVo.setParam(new String[]{code, Integer.toString(time)}); //模版的参数
        boolean send = SmsUtil.send(smsVo);
        if (send) {
            return R.ok();
        }
        return R.error().message("发送验证码失败!!!");
    }

//随机验证码的工具类
public class RandomUtil {

    private static final Random random = new Random();

    private static final DecimalFormat fourdf = new DecimalFormat("0000");

    private static final DecimalFormat sixdf = new DecimalFormat("000000");

    /**
     * 生成4位随机数
     */
    public static String getFourBitRandom() {
        return fourdf.format(random.nextInt(10000));
    }

    /**
     * 生成6位随机数
     */
    public static String getSixBitRandom() {
        return sixdf.format(random.nextInt(1000000));
    }
}

五、配置redis的序列化方式

redis默认是采用的JDK的IO序列化,这样会出现乱码,所有我们要将其配置为Json格式的序列化方式来解决乱码问题。

@Configuration
public class RedisConfig {

    /**
     * 设置RedisTemplate规则
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //序列号key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
六、登录验证
 public Map<String, Object> login(LoginVo loginVo) {
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) {
            throw new YyghException(ResultCode.ERROR, "手机号和验证码不能为空");
        }
        Object codeRedis = redisTemplate.opsForValue().get(phone);
        if (!code.equals(codeRedis)) {
            throw new YyghException(ResultCode.ERROR, "验证码错误!!!");
        }
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", phone);
        UserInfo userInfo = this.getOne(wrapper);
        if (!StringUtils.isEmpty(userInfo) && userInfo.getStatus() == 0) {
            throw new YyghException(ResultCode.ERROR, "账号被禁用请联系管理员!!!!");
        }
        //根据openid判断是否是微信扫码登录
        String openid = loginVo.getOpenid();
        //不是扫码登录
        if (StringUtils.isEmpty(openid)) {
            //并且手机号不存在
            if (userInfo == null) {
                userInfo = new UserInfo();
                userInfo.setPhone(phone);
                this.save(userInfo);
            }
        } else {  //是微信扫码登录
            QueryWrapper<UserInfo> userWx = new QueryWrapper<>();
            userWx.eq("openid", openid);
            UserInfo userInfoWx = this.getOne(userWx);
            //根据手机号查询到的用户不存在
            if (userInfo == null) {
                UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("openid", openid).set("phone", phone);
                this.update(updateWrapper);
                //将微信账号信息赋值给UserInfo
                userInfo = userInfoWx;
            } else {  //手机号的账号已存在
                //手机号已与另一个微信号绑定
                if (!StringUtils.isEmpty(userInfo.getOpenid())) {
                    throw new YyghException(ResultCode.ERROR, "该手机号已绑定");
                }
                //手机号存在但是没有绑定
                userInfo.setOpenid(openid);
                userInfo.setNickName(userInfoWx.getNickName());
                this.updateById(userInfo);
                this.removeById(userInfoWx);
            }

        }
        return UserUtil.getResults(userInfo);
    }

public class UserUtil {
    public static Map<String, Object> getResults(UserInfo info){
        String name = info.getName();
        if (StringUtils.isEmpty(name)) {
            name = info.getNickName();
        }
        if (StringUtils.isEmpty(name)) {
            name = info.getPhone();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("name", name);
        map.put("token", JwtHelper.createToken(info.getId(), name));
        return map;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力奋斗的JAVA小余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值