腾讯云短信服务——获取验证码

news2025/1/17 14:05:31

引言

之前介绍过阿里云短信服务,传送门:阿里云短信服务——短信发送验证码,但是由于阿里云现在短信调用门槛较高,申请有很多限制(我申请好几次都没有通过),所以只能使用测试账号给固定的手机号发送验证码,自己写项目用起来很难受,于是转向了腾讯云的短信服务,当然腾讯云通用也有门槛,你需要符合以下要求:

有自己的网站(该网站在腾讯云已显示备案,一般个人博客即可),如图:
在这里插入图片描述

这是唯一一个有点门槛的需求,如果你有个人博客并且自己的网站和域名也备案完成就可以使用了。(同样的条件阿里云没有给我通过审批,因为我的网站好久不用挂了,就临时用wordpress搭了一个特别简单的博客,阿里云取消审批的原因就是因为网站没有对应需求);

如果这些你符合的话推荐使用腾讯云,申请门槛相对较低,但是如果都不符合那还是使用阿里云测试账号学习吧。

配置步骤

腾讯云步骤写的其实比较清楚了,如图:

image-20230113120804544

所以一步一步来就行了;

创建签名:

在这里插入图片描述

image-20230113121233441

这里注意签名类型一定是备案网站的名称,不然审批不通过;

然后创建模板就很简单了,用腾讯云默认模板审批会快一点:

image-20230113121140828

审核通过后就可以使用腾讯云短信sdk发送短信了;

腾讯云短信java sdk

这里推荐先看一下腾讯云文档,写的挺清楚的:

腾讯云短信java sdk官方文档

配置完成还可以在云api上进行测试,这和阿里云的测试一样非常友好:

image-20230113121745993

云 api传送门

文档写的确实很详细,其实到这你就可以把对应的代码复制下来直接使用了,下面我演示一下我的使用方法;

实现获取验证码接口

先引入sdk依赖:

<dependency>
    <groupId>com.tencentcloudapi</groupId>
    <artifactId>tencentcloud-sdk-java-common</artifactId>
    <version>LATEST</version>
</dependency>
<dependency>
    <groupId>com.tencentcloudapi</groupId>
    <artifactId>tencentcloud-sdk-java-sms</artifactId>
    <version>LATEST</version>
</dependency>

然后在application.yml文件中配置所需要的参数:

image-20230113144341167

  • region我这里可选南京和广州;

  • sercretId和secretKey获取:https://console.cloud.tencent.com/cam/capi

  • endpoint:指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com(用默认就可以)

  • smsSdkAppId获取:https://console.cloud.tencent.com/smsv2/app-manage

  • signName获取:https://console.cloud.tencent.com/smsv2/csms-sign

  • templateId获取:https://console.cloud.tencent.com/smsv2/csms-template

  • expiredTime是我自定义的第二个模板参数


创建TencentSmsConstant实体类读取配置文件信息:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 腾讯云短信验证码服务常量
 */
@Component
public class TencentSmsConstant implements InitializingBean {
    @Value("${tencent.sms.region}")
    private String region;
    
    @Value("${tencent.sms.secret_id}")
    private String secretId;

    @Value("${tencent.sms.secret_key}")
    private String secretKey;

    @Value("${tencent.sms.endpoint}")
    private String endpoint;

    @Value("${tencent.sms.sms_sdk_app_id}")
    private String smsSdkAppId;

    @Value("${tencent.sms.sign_name}")
    private String signName;

    @Value("${tencent.sms.template_id}")
    private String templateId;

    @Value("${tencent.sms.expired_time}")
    private String expiredTime;

    public static String REGION;
    public static String SECRET_ID;
    public static String SECRET_KEY;
    public static String ENDPOINT;
    public static String SMS_SDK_APP_ID;
    public static String SIGN_NAME;
    public static String TEMPLATE_ID;
    public static String EXPIRED_TIME;

    @Override
    public void afterPropertiesSet() throws Exception {
        REGION = region;
        SECRET_ID = secretId;
        SECRET_KEY = secretKey;
        ENDPOINT = endpoint;
        SMS_SDK_APP_ID = smsSdkAppId;
        SIGN_NAME = signName;
        TEMPLATE_ID = templateId;
        EXPIRED_TIME = expiredTime;
    }
}

编写controller:

@PostMapping("/tencent/code/{phone}")
public BaseResponse<String> tencentSendMessageToPhone(@PathVariable String phone) {
    // 校验信息
    this.verifyPhoneInfo(phone);
    // 如果redis没有该手机号验证码,则获取验证码并发送短信
    String verifyCode = RandomUtils.getSixBitRandom(); // 获取六位验证码
    Boolean isSend = smsService.tencentSendMessageToPhone(verifyCode, phone); // 调用tencent短信发送sdk
    // 判断发送结果并处理(存入redis)
    this.afterMessageSending(isSend, phone, verifyCode);
    return ResultUtils.success("短信发送成功");
}

/**
 * 校验发送验证码手机号信息
 * @param phone 手机号
 */
private void verifyPhoneInfo(String phone) {
    if (StringUtils.isAnyBlank(phone)) {
        throw new BusinessException(StatusCode.NULL_ERROR, "手机号为空");
    }
    // 校验手机号
    RegExpUtil.regExpVerify(RegExpUtil.phoneRegExp, phone, "手机号格式错误");
    // 从redis中查看有没有该手机号的验证码
    String verifyCode = (String) redisTemplate.opsForValue().get(RedisKey.SMS_LOGIN_CODE + phone);
    if (!StringUtils.isAnyBlank(verifyCode)) {
        throw new BusinessException(StatusCode.SUCCESS, "验证码已发送=>" + verifyCode);
    }
}

/**
 * 判断发送结果并处理
 * @param isSend 发送结果
 * @param phone 发送手机号
 * @param verifyCode 验证码
 */
private void afterMessageSending(Boolean isSend, String phone, String verifyCode) {
    if (isSend) { // 如果发送成功,则将对应手机号验证码存入redis中,设置规定时间内有效
        redisTemplate.opsForValue().set(
                RedisKey.SMS_LOGIN_CODE + phone,
                verifyCode,
                MESSAGE_EXPIRED_TIME,
                TimeUnit.MINUTES);
    } else {
        throw new BusinessException(StatusCode.SYSTEM_ERROR, "短信发送失败");
    }
}

controller逻辑可以参考阿里云短信的那篇文章,这里都一样,当然这里省略了60秒内可以重复发送、发送频率限制等操作,这些网上都可以搜到,一般也是用redis实现的;


✨service层具体调用sdk方法:

这里才是调用sdk的关键逻辑代码

public Boolean tencentSendMessageToPhone(String verifyCode, String phone) {
    try{
        // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
        Credential cred = new Credential(TencentSmsConstant.SECRET_ID, TencentSmsConstant.SECRET_KEY);
        // 实例化一个http选项
        HttpProfile httpProfile = new HttpProfile();
        // 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com
        httpProfile.setEndpoint(TencentSmsConstant.ENDPOINT);
        // 实例化一个client选项
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        SmsClient client = new SmsClient(cred, TencentSmsConstant.REGION, clientProfile);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        com.tencentcloudapi.sms.v20210111.models.SendSmsRequest req =
                new com.tencentcloudapi.sms.v20210111.models.SendSmsRequest();
        // 设置发送短信的手机号(可以一次多个:{"18539344270", "13073775668"})
        String[] phoneNumberSet1 = {phone};
        req.setPhoneNumberSet(phoneNumberSet1);

        // 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId
        req.setSmsSdkAppId(TencentSmsConstant.SMS_SDK_APP_ID);
        // 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名
        req.setSignName(TencentSmsConstant.SIGN_NAME);
        // 模板 ID: 必须填写已审核通过的模板 ID
        req.setTemplateId(TencentSmsConstant.TEMPLATE_ID);

        // 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空
        // 我这里设置第一个参数为验证码,第二个为验证码超时时间
        String[] templateParamSet1 = {verifyCode, TencentSmsConstant.EXPIRED_TIME};
        req.setTemplateParamSet(templateParamSet1);

        // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
        com.tencentcloudapi.sms.v20210111.models.SendSmsResponse resp = client.SendSms(req);
        // 输出json格式的字符串回包
        log.info(com.tencentcloudapi.sms.v20210111.models.SendSmsResponse.toJsonString(resp));
        // 因为该需求是给一个手机号发送,发送结果是每个手机号的信息发送响应封装类(SendStatus)的数组,所以只需要该数组第一个参数即可
        return resp.getSendStatusSet()[0].getCode().equals(TENCENT_SMS_SUCCESS_CODE);
    } catch (TencentCloudSDKException e) {
        log.info(e.toString());
    }
    return false;
}

注释比较清楚了,就不多说了。

测试一下:

调用接口
在这里插入图片描述

redis中存储:

image-20230113145914895

发送的短信:

image-20230113150023832

测试功能完成。

总结

最近做验证码登录时又重新回顾了一下这些内容,也发现了之前我忽略的一些细节,比如频率限制等,后期如果有机会再补上;

对于腾讯云和阿里云两个短信平台的测试都需要充点钱才能发短信,几块钱就行,腾讯云能免费领100次短信,当然短信平台不止这两家,还有很多可以使用,感兴趣可以自行搜索;

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

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

相关文章

2023速卖通开店入驻流程及费用,新店运营思路

开店前准备 从卖家开始注册账户起&#xff0c;需速卖通平台的销售政策和全球速卖通平台规则。平台要求卖家在速卖通经营需遵循公平、诚实的行事原则&#xff0c;以确保安全的购买及销售体验。 1.注册账号 注册账户前&#xff0c;以下所有资料都是必须提供的资料。若资料不完…

AtCoder Beginner Contest 044(4/4)

Tak and Hotels (ABC Edit)前k晚花费x&#xff0c;k1晚以后花费yAC代码&#xff1a;import java.util.*; import java.io.*; public class Main {public static void main(String[] args) {InputStream inputStream System.in;OutputStream outputStream System.out;InputRea…

喜报 | 迅镭激光荣获2022年度江苏省科学技术奖

1月6日&#xff0c;江苏省科技厅发布了2022年度江苏省科学技术奖综合评审结果公示名单&#xff0c;迅镭激光与江苏师范大学等单位合作的“高功率2微米激光器关键技术及应用”项目&#xff0c;荣获2022年度江苏省科学技术二等奖。 江苏省科学技术奖是省内科技领域最高级别的奖项…

Java 23种设计模式(1.设计模式概念和UML)

1. 设计模式概念 软件设计模式&#xff08;Software Design Pattern&#xff09;&#xff0c;又称设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结 1.1 设计模式学习必要性理由 设计模式的本质是面向对象设计原则的实际运用&#xff0c;是对类的…

2022边缘计算开源项目

在边缘计算社区&#xff0c;统计边缘计算开源项目发展情况&#xff0c;开源软件生态蓬勃发展&#xff0c;边缘计算开源项目又是开源软件生态中不可忽视的重要力量。 2022 年边缘计算领域较为活跃和热门的十个开源项目&#xff1a;KubeEdge、EdgeXFoundry、Akraino、OpenYurt、B…

【UE4 第一人称射击游戏】47-修改AI为僵尸样貌

上一篇&#xff1a;【UE4 第一人称射击游戏】46-蹲高调整本篇效果&#xff1a;将AI修改成了僵尸的模样步骤&#xff1a;可以先从Mixamo网站下载 僵尸 资源&#xff0c;相关教程可以参考这篇文章&#xff1a;UE4 利用Mixamo自动绑骨并导入虚幻4我下载的是这个僵尸资源下载的时候…

【Qt】富文本处理简单介绍

文章目录Qt富文本处理富文本文档结构文本块QTextBlock表格、列表、图片查找功能语法高亮与HTML参考《Qt Creator快速入门(第三版)》。 Qt富文本处理 富文本Rich Text&#xff0c;简单说就是在文档中可以使用多种格式&#xff0c;比如字体颜色、图片和表格等&#xff0c;是与纯…

给定一个有序数组arr,代表坐落在X轴上的点 给定一个正数K,代表绳子的长度 返回绳子最多压中几个点? 即使绳子边缘处盖住点也算盖住

目录暴力求解贪心二分法滑动窗口对数器测试题目&#xff1a; 给定一个有序数组arr&#xff0c;代表坐落在X轴上的点 给定一个正数K&#xff0c;代表绳子的长度 返回绳子最多压中几个点&#xff1f; 即使绳子边缘处盖住点也算盖住 这道题有三个解决方案 暴力求解 //暴力求解O(N…

Docker容器MySQL数据库的备份与还原,以及每天定时自动备份.

1.快速启动mysql容器 1&#xff1a;拉取mysql镜像&#xff1a; 根据自己需要&#xff0c;我这个是5.7版本的镜像。 docker pull nanlist/mysql:5.72&#xff1a;宿主机建立挂载目录&#xff1a; mkdir三个文件夹&#xff0c;方便持久化。 /home/mysql/conf /home/mysql/log…

java面试资料(二)

这里写目录标题Spring什么是 Spring Framework&#xff1f;列举 Spring Framework 的优点。Spring Framework 有哪些不同的功能&#xff1f;Spring Framework 中有多少个模块&#xff0c;它们分别是什么&#xff1f;什么是 Spring 配置文件&#xff1f;Spring 应用程序有哪些不…

MySQL数据同步ES的4种方法,你能想到几种?

大家好&#xff0c;我是老三&#xff0c;这期给大家分享一个电商中常见的场景——MySQL数据同步Elasticsearch。 大家应该都在各种电商网站检索过商品&#xff0c;那么检索商品一般都是通过什么实现呢&#xff1f;搜索引擎Elasticsearch。 那么问题来了&#xff0c;商品上架&a…

【布隆过滤器】如何防止缓存穿透、海量邮箱的垃圾邮件过滤等问题?

目录 一、布隆过滤器是什么&#xff1f; 二、布隆过滤器的模拟实现 2.1、模拟实现 2.2、布隆过滤器的优点和缺点 优点&#xff1a; 缺点&#xff1a; 2.3、布隆过滤器的删除功能 2.4、布隆过滤器的使用场景 一、布隆过滤器是什么&#xff1f; 它是一种概率型数据结构&am…

敏捷.概念辨析

第一部分 1. 最小可行产品MVP&#xff08;Minimum Viable Product&#xff09; 在很多同学的脑海里&#xff0c;MVP就是你想传达给用户的功能的最小集合。 错&#xff0c;完全错。 问题不在于“你觉得应该……”&#xff0c;关键是“用户目前感觉……”。我们预设了立场&am…

Android Glide 4.9 常见方法总结

转载请标明出处&#xff1a;http://blog.csdn.net/zhaoyanjun6/article/details/128665358 本文出自【赵彦军的博客】 文章目录依赖submit 下载图片DrawableImageViewTargetRequestListener 加载圆角图片回调圆形 CircleCrop圆角 RoundedCornersFitCenterCenterCropCenterInsid…

RK3399平台开发系列讲解(中断篇)ARM64异常处理详解

🚀返回专栏总目录 文章目录 一、异常级别二、异常分类三、异常向量表四、异常处理沉淀、分享、成长,让自己和他人都能有所收获!😄 一、异常级别 📢ARM64的处理器支持多个异常等级(exception level),其中EL0是用户模式,EL1是内核模式,也称为特权模式;EL2 是虚拟化…

算力狂热时代的冷静之道:宁畅总裁秦晓宁分享企业的算力最优解

算力是数字化时代的生产力之源&#xff0c;近年来已经成为共识。所以&#xff0c;我们能看到各个层面对算力的追逐&#xff0c;无论是国家层面的政策利好&#xff0c;算力基础设施建设的加速&#xff0c;还是诸多行业和企业积极地增加算力部署&#xff0c;呈现出一片如火如荼的…

958. 二叉树的完全性检验

958. 二叉树的完全性检验 难度中等 给定一个二叉树的 root &#xff0c;确定它是否是一个 完全二叉树 。 在一个 完全二叉树 中&#xff0c;除了最后一个关卡外&#xff0c;所有关卡都是完全被填满的&#xff0c;并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 …

AWVS扫描Web应用程序

AWVS扫描Web应用程序 系列文章 AWVS安装与激活 1.账户密码登录扫描 我们准备了一个靶场用来做测试扫描&#xff1a; 1.点击【Targets】&#xff0c;点击【add Target】 2.输入扫描地址和扫描描述,点击【save】 3.点击【Site Login】 4.选择【try to auto-login into the si…

降本增效,软件质量是要降还是要升?

最近一年&#xff0c;裁员潮席卷而来&#xff0c;意味着许多企业经营遇到了很大困难&#xff0c;“降本增效”自然成了企业的主旋律&#xff1a;内部研发和运营要努力降低成本&#xff0c;外部市场想突出重围、开拓新局面&#xff0c;创造新营收&#xff0c;企业才能渡过难关&a…

DeViSE: A Deep Visual-Semantic Embedding Model

摘要 现代视觉识别系统受限于其能力为&#xff1a;扩大大规模数量的目标类别。 scale to large numbers of object categoriestext data :文本数据这篇文章我们提出一个a new deep visual-semantic embedding model从unannotated text 中收集的语义信息和有标签的图像数据。o…