用户一键注册登录(一)- 对接短信平台

news2024/11/27 2:42:26

1. 流程图

image-20241022082440460

2. 详细设计

2.1 用户表结构设计

CREATE TABLE `users` (
  `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '手机号',
  `nickname` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '昵称',
  `real_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '真实姓名',
  `show_which_name` int NOT NULL DEFAULT '2' COMMENT '对外展示名,1:真实姓名,2:昵称',
  `sex` int NOT NULL COMMENT '性别,1:男 0:女 2:保密',
  `face` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户头像',
  `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `country` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '国家',
  `province` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '省份',
  `city` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '城市',
  `district` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '区县',
  `description` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '介绍',
  `start_work_date` date DEFAULT NULL COMMENT '我参加工作的时间',
  `position` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '我当前职位/职务',
  `role` int NOT NULL COMMENT '身份角色,1: 求职者,2: HR。切换为HR时也可以登录求职者',
  `hr_in_which_company_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '成为HR后,认证的(绑定的)公司主键id',
  `hr_signature` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '我的一句话签名',
  `hr_tags` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '我的个性化标签',
  `created_time` datetime NOT NULL COMMENT '创建时间',
  `updated_time` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `mobile` (`mobile`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

2.2 注册云短信服务

这里使用到了腾讯云短信,为什么用腾讯云不用阿里云呢?因为腾讯云免费100条…够测试使用了

image-20241022084827814

2.3 配置依赖

在common包的pom中加入依赖

<dependency>
    <groupId>com.tencentcloudapi</groupId>
    <artifactId>tencentcloud-sdk-java</artifactId>
  	<!-- 可以在这里查最新的 https://central.sonatype.com/artifact/com.tencentcloudapi/tencentcloud-sdk-java -->
    <version>3.1.1129</version>
</dependency>

2.4 全局统一返回 R

package resp;

import common.HttpStatusEnum;
import lombok.Getter;

@Getter
public class R<T> {
    /**
     *标识返回状态
     */
    private Integer code;

    /**
     * 标识返回消息
     */
    private String message;

    /**
     * 标识返回内容
     */
    private T data;

    public R() {

    }

    public R(Integer code, T data, String message) {
        this.code = code;
        this.data = data;
        this.message = message;
    }

    /**
     * 成功返回
     */
    public static <T> R<T> ok(T data){
        return new R<>(HttpStatusEnum.SUCCESS.getCode(),data,HttpStatusEnum.SUCCESS.getMessage());
    }

    /**
     * 成功返回
     */
    public static <T> R<T> ok(T data,String message){
        return new R<>(HttpStatusEnum.SUCCESS.getCode(), data, message);
    }

    /**
     * 失败返回
     */
    public static <T> R<T> failed(HttpStatusEnum httpStatusEnum){
        return new R<>(httpStatusEnum.getCode(),null, httpStatusEnum.getMessage());
    }

    /**
     * 失败返回
     */
    public static <T> R<T> failed(String message){
        return new R<>(HttpStatusEnum.FAIL.getCode(), null, message);
    }
}


2.5 添加自定义异常

package exception;


import lombok.Getter;
import lombok.Setter;

/**
 * 自定义异常
 * @author xiaoqiu
 */
@Setter
@Getter
public class XiaoQiuException extends RuntimeException{

    private String code;

    public XiaoQiuException(String code, String message) {
        super(message);
        this.code = code;
    }
}

2.6 全局异常处理

package exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import resp.R;

/**
 * 全局异常处理器
 * @author xiaoqiu
 */
@Slf4j
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    /**
     * 处理自定义的业务异常
     */
    @ExceptionHandler(value = XiaoQiuException.class)
    public R<String> bizExceptionHandler(XiaoQiuException e) {
        log.error("发生业务异常! msg: -> ", e);
        return R.failed(e.getMessage());
    }

    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(value = NullPointerException.class)
    public R<String> exceptionHandler(NullPointerException e) {
        log.error("发生空指针异常! msg: -> ", e);
        return R.failed("发生空指针异常!");
    }

    /**
     * 服务器异常
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<String> exception(Exception e) {
        log.error("服务器异常! msg: -> ", e);
        return R.failed("服务器异常!");
    }
}

2.7 在common包配置发送短信工具类

package utils;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import exception.XiaoQiuException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import static exception.ResultCode.SMS_SEND_EXCEPTION;

@Component
@Slf4j
public class SMSUtils {

    @Value("${sms.secretId:test}")
    private String secretId;
    @Value("${sms.secretKey:test}")
    private String secretKey;
    @Value("${sms.templateId:test}")
    private String templateId;
    @Value("${sms.sign.name:小秋}")
    private String signName;
    @Value("${sms.sdkAppId: 10000}")
    private String sdkAppId;
    @Value("${sms.test.switch:true}")
    private boolean smsTestSwitch;

    public void sendSMS(String phone, String code) {
        try {
            // 测试避免频发发送短信,关闭认证,直接成功
            if (smsTestSwitch) {
                return;
            }

            if (StringUtils.isBlank(phone) || StringUtils.isBlank(code)) {
                throw new XiaoQiuException(SMS_SEND_EXCEPTION, "手机号或验证码为空!");
            }
            
            // 必要步骤:CAM密匙查询获取: https://console.cloud.tencent.com/cam/capi
            SmsClient client = getSmsClient();

            // 实例化一个请求对象,每个接口都会对应一个request对象
            SendSmsRequest req = getSendSmsRequest(phone, code);

            // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
            SendSmsResponse resp = client.SendSms(req);
            // 输出json格式的字符串回包
            log.info("手机号:{}, code: {}, 短信发送结果:{}", phone, code, SendSmsResponse.toJsonString(resp));
//            System.out.println(SendSmsResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            log.error("发送短信失败!", e);
        }
    }

    private SmsClient getSmsClient() {
        Credential cred = new Credential(secretId, secretKey);

        // 实例化一个http选项,可选的,没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
//            httpProfile.setReqMethod("POST"); // 默认使用POST

        /* SDK会自动指定域名。通常是不需要特地指定域名的,但是如果你访问的是金融区的服务
         * 则必须手动指定域名,例如sms的上海金融区域名: sms.ap-shanghai-fsi.tencentcloudapi.com */
        httpProfile.setEndpoint("sms.tencentcloudapi.com");

        // 实例化一个client选项
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        return new SmsClient(cred, "ap-nanjing", clientProfile);
    }

    private SendSmsRequest getSendSmsRequest(String phone, String code) {
        SendSmsRequest req = new SendSmsRequest();
        String[] phoneNumberSet = {"+86" + phone};//电话号码
        req.setPhoneNumberSet(phoneNumberSet);
        // 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId
        req.setSmsSdkAppId(sdkAppId);
        // 签名
        req.setSignName(signName);
        // 模板id:必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看
        req.setTemplateId(templateId);

        /* 模板参数(自定义占位变量): 若无模板参数,则设置为空 */
        String[] templateParamSet1 = {code};
        req.setTemplateParamSet(templateParamSet1);
        return req;
    }

//    可以启动一个main函数测试
//    public static void main(String[] args) {
//        try {
//            new SMSUtils().sendSMS("18812348888", "8888");
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2220829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

回忆Web编程的岁月变迁

目录 引子 记忆的片断 CGI / ISAPI 何为 CGI / ISAPI ? 一个小插曲 ASP与我的ASP Builder ASP编程技术 何为 Windows DNA &#xff1f; 什么是 COM ? ASP.NET 什么是 ActiveX ? IntraBuilder与我的InterBuilder 结尾 引子 凌晨三点醒了&#xff0c;大多的时候是…

数据结构(JAVA)JDK17语法新增特性

目录 yield关键字var关键字空指针异常密封类接口中的私有方法instanceof其他 yield关键字 yield关键字用于case的代码块中返回值。 正常switch语句 public static void main(String[] args) {int result 0;String str "a";switch (str) {case "a" :resu…

根据发生异常的汇编指令以及函数调用堆栈,从内存的角度出发,估计出问题的可能原因,确定排查方向,快速定位C++软件问题

目录 1、前言 2、初步分析dump文件 3、加载更多模块的pdb文件&#xff0c;可能能看到更多行的函数调用堆栈 4、从内存的角度去看&#xff0c;估计是访问了野指针导致的&#xff0c;沿着这个怀疑的方向快速地定位了问题 5、最后 C软件异常排查从入门到精通系列教程&#xf…

【安当产品应用案例100集】024-BYOE及BYOK在IaaS场景中的应用

在云计算环境中&#xff0c;尤其是涉及到敏感数据时&#xff0c;企业用户可能会选择自带加密工具或密钥&#xff08;即BYOE或BYOK&#xff09;&#xff0c;以确保数据在传输和存储过程中的安全性。这种方式可以防止云服务提供商访问或泄露加密数据&#xff0c;增强数据保护。 …

离散数学 第二讲 特殊集合和集合间关系 笔记 [电子科大]王丽杰

1.2 特殊集合与集合间关系 空集 不含任何元素的集合叫做空集(empty set)&#xff0c;记作∅. 空集可以符号化为 ∅ { x ∣ x ≠ x } ∅ \{ x|x ≠ x\} ∅{x∣xx} . 空集是绝对唯一的。 全集 针对一个具体范围&#xff0c;我们考虑的所有对象的集合叫做全集(universal se…

基于springboot招聘信息管理系统设计与实现(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

视频美颜平台是如何搭建的?基于直播美颜SDK源码的开发技术详解

今天&#xff0c;笔者将详细讲解如何基于直播美颜SDK源码搭建视频美颜平台的技术路径。 一、理解视频美颜技术 视频美颜技术主要通过图像处理算法对视频流进行实时处理&#xff0c;包括肤色优化、瑕疵修复、面部特征增强等。实现这一目标需要高效的图像处理算法和稳定的实时渲…

5个最流行的图像嵌入模型对比

最近需要研究图像相似性搜索。我想知道基于架构训练方法的嵌入之间是否存在差异。但是&#xff0c;很少有博客比较几种模型之间的嵌入。因此&#xff0c;在这篇博客中&#xff0c;我将使用 Flickr 数据集 [6] 比较 EfficientNet [1]、ViT [2]、DINO-v2 [3]、CLIP [4] 和 BLIP-2…

Matlab软件进行金融时间序列数据的描述性统计代码

1、数据S&P500的收盘价格&#xff0c;return100*log(pt/pt-1) 方法1&#xff1a;用python代码 import numpy as np import pandas as pddef calculate_log_returns(prices):"""计算价格序列的对数收益率。参数:prices (numpy.array): 价格序列。返回:log_…

Mongodb基础用法【总结】

关系型数据库和非关系型数据库的区别 关系型数据库 1.在关系型数据库中&#xff0c;数据都是存储在表中的&#xff0c;对存储的内容有严格的要求 2.因为我们在创建表的时候久已经规定了表中的字段 存储的数据类型 是否为空 唯一标识等规则 3.由于操作的都是结构化的数据&#…

家政小程序搭建,数字化市场发展下的意义

家政服务行业作为当下社会生活中不可或缺的行业&#xff0c;需求量在逐渐增加&#xff0c;行业发展也趋向多样化。 随着数字化的浪潮&#xff0c;家政行业逐渐向数字化、智能化升级发展&#xff0c;推动行业高质量发展&#xff0c;迎合现代化发展趋势&#xff0c;这一转型为行…

83.【C语言】数据结构之顺序表的尾部插入和删除

目录 3.操作顺序表 2."伪"插入顺序表的元素 分析尾部插入函数SLPushBack 代码示例 SeqList.h main.c free(指针)出错的几种可能的原因 3."伪"删除顺序表元素 2.分析尾部删除函数SLPopBack 代码示例 错误检查 两种解决办法 1.判断size是否为负…

004-按照指定功能模块名称分组

按照指定功能模块名称分组 一、说明1.现在有一个需求&#xff1a;2.具体做法 二、代码案例三、效果展示 一、说明 1.现在有一个需求&#xff1a; 需要把一个功能模块的几个功能点放在同一个文档目录下&#xff0c;这几个功能点分布在不同的 Controller 2.具体做法 需要把他…

如何将markdown文件转换为pdf

最近笔者在用vscode写markdown&#xff0c;但是提交时往往需要交pdf。所以就涉及到如何将markdown转化为pdf格式。 首先&#xff0c;需要在vscode上安装插件 markdown Preview Enhanced 之后在vscode的右上角即可看到下述图标&#xff0c;点击&#xff0c;vscode右半面就会显示…

C++数据结构-图的存储及邻接矩阵的代码实现

1. 什么是图 图论&#xff08;graph theory&#xff09; 是数学的一个分支&#xff0c;它以 图 为研究的对象。 图论本身是应用数学的一部分&#xff0c;历史上图论曾经被很多数学家各自独立建立过。关于图论的最早文字记载最早出现在欧拉 1736 年的论著中&#xff0c;也就是…

2024年有哪些开放式耳机值得入手?开放式耳机排行榜10强

随着技术的不断进步与消费者需求的日益多样化&#xff0c;开放式耳机凭借其独特的优势——如保持对周围环境的感知、减少对耳道的压力等&#xff0c;逐渐成为市场上的一大热点。尤其是在健康意识不断提升的今天&#xff0c;开放式耳机不仅为音乐爱好者提供了全新的聆听体验&…

【C++语言】全面掌握const的用法

一、const 需要怎么理解&#xff1f;&#xff1f; const修饰的变量不能够再作为左值&#xff0c;初始化完成之后&#xff0c;值不能被修改 1.1 C语言的const const 修饰的量&#xff0c;可以不用初始化&#xff0c;不叫常量&#xff0c;叫做常变量。 void main() {const int…

Windows git 配置

需要在git-bash的目录下,配置.ssh 的配置文件 要 .ssh 目录下的配置无法使用

Modbus TCP报错:Response length is only 0 bytes

问题描述&#xff1a; 使用modbus_tk库&#xff0c;通过Modbus tcp连接PLC时&#xff0c;python中的一个报错信息&#xff1a; Response length is only 0 bytes报错原因&#xff1a; 与Modbus TCP 服务端建立连接后没有断开&#xff0c;继续作为长连接使用&#xff0c;客户端…

一文掌握Cephadm部署Ceph存储集群

&#x1f4da; 博客主页&#xff1a; StevenZeng学堂 &#x1f389; 本文专栏: 一文读懂Kubernetes一文读懂Harbor云原生安全实战指南云原生存储实践指南 ❤️ 摘要&#xff1a;随着企业数据量的增长和存储需求的复杂化&#xff0c;Ceph因其高可扩展性和灵活性&#xff0c;能…