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

引言

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

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

这是唯一一个有点门槛的需求,如果你有个人博客并且自己的网站和域名也备案完成就可以使用了。(同样的条件阿里云没有给我通过审批,因为我的网站好久不用挂了,就临时用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次短信,当然短信平台不止这两家,还有很多可以使用,感兴趣可以自行搜索;

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

YXXYX

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

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

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

打赏作者

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

抵扣说明:

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

余额充值