Java整合腾讯云短信发送实例代码

网友投稿 493 2022-09-05


Java整合腾讯云短信发送实例代码

目录1. 引入相关maven依赖2. 编写短信发送工具类3. 业务层3. 相关工具类

1. 引入相关maven依赖

com.github.qcloudsms

qcloudsms

1.0.6

com.qcloud

qcloud-java-sdk

2.0.1

com.tencentcloudapi

tencentcloud-sdk-java

3.1.270

cn.hutool

hutool-all

5.4.2

2. 编写短信发送工具类

package com.cloud.system.common.utils;

import ch.qos.logback.core.net.server.Client;

import cn.hutool.core.util.RandomUtil;

import com.cloud.system.api.enums.SmsLengthEnum;

import com.cloud.system.api.enums.SmsTypeEnum;

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 com.tencentcloudapi.sms.v20210111.models.SendStatus;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;

import java.io.FileInputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.Properties;

/**

* @program: server-master

* @description:

* @author: hjq

* @create: 2021/12/17

*/

@Component

@Slf4j

public class SmsUtil {

/** 腾讯云账户密钥对secretId(在访问管理中配置) */

private static String secretId;

/** 腾讯云账户密钥对secretKey(在访问管理中配置) */

private static String secretKey;

/** 短信应用appId */

private static String appId;

/** 短信应用appKey */

private static String appKey;

/** 签名 */

private static String smsSign;

/** 过期时间 */

private static String expireTime;

/** 登录验证模板 */

private static String loginTemplateId;

/** 修改密码验证模板 */

private static String pwdTemplateId;

static {

try {

Properties prop=new Properties();

prop.load(new InputStreamReader(

Client.class.getClassLoader().getResourceAsStream("sms.properties"), "gbk"));

secretId = prop.get("secretId").toString();

secretKey = prop.get("secretKey").toString();

appId = prop.get("appId").toString();

appKey = prop.get("appKey").toString();

smsSign = prop.get("smsSign").toString();

expireTime = prop.get("expireTime").toString();

loginTemplateId = prop.get("loginTemplateId").toString();

pwdTemplateId = prop.get("pwdTemplateId").toString();

} catch(Exception e) {

e.printStackTrace();

}

}

/**

* 短信发送工具类

* @param phoneNumbers 下发手机号码

* @param templateParamSet 模板参数

*/

public static SendStatus sendMessage(String[] phoneNumbers, String[] templateParamSet,Integer type) throws TencentCloudSDKException {

// 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey

Credential cred = new Credential(secretId, secretKey);

// 实例化一个http选项

HttpProfile httpProfile = new HttpProfile();

httpProfile.setReqMethod("POST");

httpProfile.setConnTimeout(60);

//实例化一个客户端配置对象,指定超时时间等配置

ClientProfile clientProfile = new ClientProfile();

/* SDK默认用TC3-HMAC-SHA256进行签名

* 非必要请不要修改这个字段 */

clientProfile.setSignMethod("HmacSHA256");

clientProfile.setHttpProfile(httpProfile);

SmsClient client = new SmsClient(cred, "ap-guangzhou",clientProfile);

SendSmsRequest req = new SendSmsRequest();

//短信应用ID

req.setSmsSdkAppId(appId);

//短信签名内容

req.setSignName(smsSign);

/* 模板 ID: 必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看 */

//根据不同业务使用不同的模板

switch (type){

case 1:

req.setTemplateId(pwdTemplateId);

break;

case 2:

req.setTemplateId(loginTemplateId);

break;

}

//下发手机号码

req.setPhoneNumberSet(phoneNumbers);

/* 模板参数: 若无模板参数,则设置为空 */

req.setTemplateParamSet(templateParamSet);

SendSmsResponse res = client.SendSms(req);

return res.getSendStatusSet()[0];

}

/**

* 随机生成指定长度的短信的验证码

*

* @param smsLengthEnum 短信验证码长度枚举

* @return 随机验证码

*/

public static String createSmsRandomCode(SmsLengthEnum smsLengthEnum) {

return RandomUtil.randomNumbers(smsLengthEnum.getLength());

}

/**

* 创建短信验证码,缓存键策略

* 策略:前缀_业务名_手机号

*

* @param prefix 前缀

* @param phone 手机号

* @param businessStr 业务名

* @return 短信验证码,缓存键策略

*/

public static String createSmsCacheKey(String prefix, String phone, String businessStr) {

return prefix + "_" + businessStr + "_" + phone;

}

}

3. 业务层

使用redis存储随机生成的验证码,并在使用后销毁

package com.cloud.system.api.service.impl;

import com.cloud.system.api.bean.SmsPwdBean;

import com.cloud.system.api.bean.SmsResult;

import com.cloud.system.api.entity.HumanInfo;

import com.cloud.system.api.entity.SmsRecord;

import com.cloud.system.api.enums.SmsLengthEnum;

import com.cloud.system.api.enums.SmsTypeEnum;

import com.cloud.system.api.mapper.HumanInfoMapper;

import com.cloud.system.api.mapper.SmsRecordMapper;

import com.cloud.system.api.service.SmsRecordService;

import com.cloud.system.common.utils.RedisUtil;

import com.cloud.system.common.utils.RegUtils;

import com.cloud.system.common.utils.SmsUtil;

import com.tencentcloudapi.common.exception.TencentCloudSDKException;

import com.tencentcloudapi.sms.v20210111.models.SendStatus;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.commons.collections.CollectionUtils;

import org.apache.commons.lang.StringUtils;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;

import java.util.Date;

import java.util.List;

import java.util.Objects;

/**

* @program: server-master

* @description:

* @author: hjq

* @create: 2021/12/20

*/

@Service("smsRecordService")

@Transactional

@Slf4j

public class SmsRecordServiceImpl implements SmsRecordService {

@Resource

private SmsRecordMapper smsRecordMapper;

@Resource

private HumanInfoMapper humanInfoMapper;

@Resource

private RedisUtil redisUtil;

@Override

public SmsResult getModPwdVcode(String humanName, String phoneNumber) {

//首先校验手机号码

if (!RegUtils.isMoblie(phoneNumber)) return new SmsResult(500,"手机号格式不正确!",null);

//然后校验输入手机号是否和该用户名绑定

if (humanInfoMapper.existByNameAndPhone(humanName, phoneNumber) <= 0){

return new SmsResult(500,"该用户不存在,请联系管理员注册!",null);

}

//生成六位的随机验证码

return sendSms(phoneNumber, SmsTypeEnum.SMS_TYPE_1, humanName);

}

/**

* 修改密码

*/

@Override

public SmsResult updatePwdByHuman(SmsPwdBean bean) {

//创建相同的缓存键

String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(bean.getUsername().hashCode()),bean.getPhoneNumber(),

SmsTypeEnum.SMS_TYPE_1.getTypeName());

//验证码校验,若返回500,则直接返回

SmsResult result = vCodeCheck(cacheKey, bean.getCaptcha());

if (500 == result.getCode()){

return result;

}

//获取人员id与密码进行加密,然后修改密码

Long humanId = humanInfoMapper.existByNameAndPhone(bean.getUsername(),bean.getPhoneNumber());

String code = DigestUtils.md5Hex(bean.getRepassword().concat(String.valueOf(humanId))).toUpperCase();

humanInfoMapper.modifyPwdByNameAndPhone(bean.getUsername(),bean.getPhoneNumber(),code);

//清除已使用的验证码

redisUtil.del(cacheKey);

return new SmsResult(200,"密码已重置!",null);

}

/**

* 用户登录获取验证码

* @param humanName 用户名

* @return

*/

@Override

public SmsResult getLoginCode(String humanName){

//获取用户信息

Example example = new Example(HumanInfo.class);

Example.Criteria criteria = example.createCriteria();

criteria.andEqualTo("deleteFlag", 0);

criteria.andEqualTo("userName", humanName);

List humanInfoList = humanInfoMapper.selectByExample(example);

//校验用户手机号

if (CollectionUtils.isEmpty(humanInfoList) || humanInfoList.size() != 1

|| StringUtils.isBlank(humanInfoList.get(0).getTelephone())

|| !RegUtils.isMoblie(humanInfoList.get(0).getTelephone())) {

return new SmsResult(500,"手机号格式不正确!",null);

}

return sendSms(humanInfoList.get(0).getTelephone(), SmsTypeEnum.SMS_TYPE_2, humanInfoList.get(0).getHumanName());

}

/**

* 校验用户登录验证码

* @return

*/

@Override

public SmsResult checkLoginCode(HumanInfo info,String captCha){

//创建相同的缓存键

String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(info.getHumanName().hashCode()),info.getTelephone(),

SmsTypeEnum.SMS_TYPE_2.getTypeName());

//验证码校验,若返回500,则直接返回

SmsResult result = vCodeCheck(cacheKey, captCha);

if (200 == result.getCode()){

//清除已使用的验证码

redisUtil.del(cacheKey);

}

return result;

}

/**

* 发送短信

* @param telephone 手机号

* @param smsType2 短信类型

* @param humanName 用户名

* @return

*/

private SmsResult sendSms(String telephone, SmsTypeEnum smsType2, String humanName) {

//生成六位的随机验证码

String randomCode = SmsUtil.createSmsRandomCode(SmsLengthEnum.SMS_LENGTH_6);

//构建参数,发送短信

SendStatus sendStatus = null;

try {

sendStatus = SmsUtil.sendMessage(new String[]{telephone}, new String[]{randomCode}, smsType2.getType());

} catch (TencentCloudSDKException e) {

log.error("********短信发送失败" + e.getMessage() + "*********");

e.printStackTrace();

}

if (Objects.nonNull(sendStatus) && "Ok".equals(sendStatus.getCode())) {

//发送成功后往记录表插值同时将验证码存储至redis,300s过期

insertSmsRecord(telephone,smsType2.getType());

//创建缓存键

String cacheKey = SmsUtil.createSmsCacheKey(String.valueOf(humanName.hashCode()), telephone, smsType2.getTypeName());

redisUtil.set(cacheKey, randomCode, 300);

return new SmsResult(200, "验证码发送成功!", null);

} else {

return new SmsResult(500, "验证码发送失败!", null);

}

}

/**

* 插入短信发送记录

* @param phoneNumber

*/

private void insertSmsRecord(String phoneNumber, int type) {

SmsRecord smsRecord = new SmsRecord();

smsRecord.setRecipient(phoneNumber);

smsRecord.setSendTime(new Date());

smsRecord.setSmsType(type);

smsRecordMapper.insert(smsRecord);

}

/**

* 验证码校验

*/

private SmsResult vCodeCheck(String cacheKey,String captcha){

if (!redisUtil.hasKey(cacheKey)){

return new SmsResult(500,"验证码已过期,请重新获取!",null);

}

if (!captcha.equals(redisUtil.get(cacheKey))){

return new SmsResult(500,"验证码错误!",null);

}

return new SmsResult(200,"验证码正确!",null);

}

}

3. 相关工具类

package com.cloud.system.common.utils;

/**

* @author: hjq

* @create: 2021-01-07 09:54

**/

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

/**

* 正则表达式工具类

*

*/

public class RegUtils {

/**

* 邮箱

*/

public static final String EMAIL = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";

/**

* 手机号码

*/

public static final String PHONE = "^(1[3-9]([0-9]{9}))$";

/**

* 仅中文

*/

public static final String CHINESE = "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$";

/**

* 整数

*/

public static final String INTEGER = "^-?[1-9]\\d*$";

/**

* 数字

*/

public static final String NUMBER = "^([+-]?)\\d*\\.?\\d+$";

/**

* 正整数

*/

public static final String INTEGER_POS = "^[1-9]\\d*$";

/**

* 浮点数

*/

public static final String FLOAT = "^([+-]?)\\d*\\.\\d+$";

/**

* 正浮点数

*/

public static final String FLOAT_POS = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$";

/**

* 是否为正整数数字,包括0(00,01非数字)

*/

public static final String INTEGER_WITH_ZERO_POS = "^(([0-9])|([1-9]([0-9]+)))$";

/**

* 是否为整数数字,包括正、负整数,包括0(00,01非数字)

*/

public static final String NUMBER_WITH_ZERO = "^((-)?(([0-9])|([1-9]([0-9]+))))$";

/**

* 是否为数字字符串

*/

public static final String NUMBER_TEXT = "^([0-9]+)$";

/**

* 数字(整数、0、浮点数),可以判断是否金额,也可以是负数

*/

public static final String NUMBER_ALL = "^((-)?(([0-9])|([1-9][0-9]+))(\\.([0-9]+))?)$";

/**

* QQ,5-14位

*/

public static final String QQ = "^[1-9][0-9]{4,13}$";

/**

* IP地址

*/

public static final String IP = "((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))";

/**

* 邮编

*/

public static final String POST_CODE = "[1-9]\\d{5}(?!\\d)";

/**

* 普通日期

*/

public static final String DATE = "^[1-9]\\d{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))$";

/**

* 复杂日期,不区分闰年的2月

* 日期格式:2017-10-19

* 或2017/10/19

* 或2017.10.19

* 或2017年10月19日

* 最大31天的月份:(((01|03|05|07|08|10|12))-((0[1-9])|([1-2][0-9])|(3[0-1])))

* 最大30天的月份:(((04|06|11))-((0[1-9])|([1-2][0-9])|(30)))

* 最大29天的月份:(02-((0[1-9])|([1-2][0-9])))

*/

public static final String DATE_COMPLEX = "^(([1-2]\\d{3})(-|/|.|年)((((01|03|05|07|08|10|12))(-|/|.|月)((0[1-9])|([1-2][0-9])|(3[0-1])))|(((04|06|11))(-|/|.|月)((0[1-9])|([1-2][0-9])|(30)))|(02-((0[1-9])|([1-2][0-9]))))(日)?)$";

/**

* 复杂的日期,区分闰年的2月

* 这个日期校验能区分闰年的2月,格式如下:2017-10-19

* (见://jb51.net/article/50905.htm)

* ^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$

*/

public static final String DATE_COMPLEX_LEAP_YEAR = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";

/**

* 正则表达式校验,符合返回True

* @param regex 正则表达式

* @param content 校验的内容

* @return

*/

public static boolean isMatch(String regex, CharSequence content){

return Pattern.matches(regex, content);

}

/**

* 校验手机号码

* @param mobile

* @return

*/

public static final boolean isMoblie(String mobile){

boolean flag = false;

if (null != mobile && !mobile.trim().equals("") && mobile.trim().length() == 11) {

Pattern pattern = Pattern.compile(PHONE);

Matcher matcher = pattern.matcher(mobile.trim());

flag = matcher.matches();

}

return flag;

}

/**

* 校验邮箱

* @param value

* @return

*/

public static final boolean isEmail(String value){

boolean flag = false;

if (null != value && !value.trim().equals("")) {

Pattern pattern = Pattern.compile(EMAIL);

Matcher matcher = pattern.matcher(value.trim());

flag = matcher.matches();

}

return flag;

}

/**

* 校验密码

* @param password

* @return 长度符合返回true,否则为false

*/

public static final boolean isPassword(String password){

boolean flag = false;

if (null != password && !password.trim().equals("")) {

password = password.trim();

if(password.length() >= 6 && password.length() <= 30){

return true;

}

}

return flag;

}

/**

* 校验手机验证码

* @param value

* @return 符合正则表达式返回true,否则返回false

*/

public static final boolean isPhoneValidateCode(String value){

boolean flag = false;

if (null != value && !value.trim().equals("")) {

Pattern pattern = Pattern.compile("^8\\d{5}$");

Matcher matcher = pattern.matcher(value.trim());

flag = matcher.matches();

}

return flag;

}

/**

* 判断是否全部大写字母

* @param str

* @return

*/

public static boolean isUpperCase(String str){

if(StringUtils.isEmpty(str)){

return false;

}

String reg = "^[A-Z]$";

return isMatch(reg,str);

}

/**

* 判断是否全部小写字母

* @param str

* @return

*/

public static boolean isLowercase(String str){

if(StringUtils.isEmpty(str)){

return false;

}

String reg = "^[a-z]$";

return isMatch(reg,str);

}

/**

* 是否ip地址

* @param str

* @return

*/

public static boolean isIP(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(IP, str);

}

/**

* 符合返回true,区分30、31天和闰年的2月份(最严格的校验),格式为2017-10-19

* @param str

* @return

*/

public static boolean isDate(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(DATE_COMPLEX_LEAP_YEAR, str);

}

/**

* 简单日期校验,不那么严格

* @param str

* @return

*/

public static boolean isDateSimple(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(DATE, str);

}

/**

* 区分30、31天,但没有区分闰年的2月份

* @param str

* @return

*/

public static boolean isDateComplex(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(DATE_COMPLEX, str);

}

/**

* 判断是否为数字字符串,如0011,10101,01

* @param str

* @return

*/

public static boolean isNumberText(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(NUMBER_TEXT, str);

}

/**

* 判断所有类型的数字,数字(整数、0、浮点数),可以判断是否金额,也可以是负数

* @param str

* @return

*/

public static boolean isNumberAll(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(NUMBER_ALL, str);

}

/**

* 是否为正整数数字,包括0(00,01非数字)

* @param str

* @return

*/

public static boolean isIntegerWithZeroPos(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(INTEGER_WITH_ZERO_POS, str);

}

/**

* 是否为整数,包括正、负整数,包括0(00,01非数字)

* @param str

* @return

*/

public static boolean isIntegerWithZero(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(NUMBER_WITH_ZERO, str);

}

/**

* 符合返回true,QQ,5-14位

* @param str

* @return

*/

public static boolean isQQ(String str){

if(StringUtils.isEmpty(str)){

return false;

}

return isMatch(QQ, str);

}

public static void main(String[] args) {

System.out.println(isMoblie("13430800244"));

System.out.println(isMoblie("17730800244"));

System.out.println(isMoblie("17630800244"));

System.out.println(isMoblie("14730800244"));

System.out.println(isMoblie("18330800244"));

System.out.println(isMoblie("19330800244"));

System.out.println(isMoblie("1333000244"));

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:#yyds干货盘点#python常用模块
下一篇:# yyds干货盘点 # 厉害了,Python也能使用动态链接库
相关文章

 发表评论

暂时没有评论,来抢沙发吧~