java 短信服务
短信
短信服务文明一般都是使用云产品的SDK,例如阿里云中的短信服务
下面是短信服务的文档
短信云服务
依赖引入:
阿里云短信SDK的Maven依赖:
<dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>3.1.0</version></dependency>
nacos中的静态配置文件
在nacos或者yaml文件中编写静态配置文件
下面是nacos中的配置,业务中用@Value获取值
这些在阿里云你获取短信业务的时候提供的
AccessKeyID=
AccessKeySecret=
##阿里短信 配置
sms.aliyun.sign-name=
sms.aliyun.endpoint=
sms.type=
sms.aliyun.template.default.name = 验证码短信
sms.aliyun.template.default.code =
sms.aliyun.template.default.variable = code
sms.aliyun.template.invite.code =
accessKeyId 和 accessKeySecret 用于身份认证。
配置项解析
1. sms.aliyun.sign-name
含义:短信签名名称。
作用:
标识短信的发送方,需在阿里云控制台提前申请并通过审核。
接收方看到的短信开头会显示此签名(如:【华天云测】您的验证码是123456)。
注意:
签名需符合阿里云规范(如企业名、应用名、网站名等),不可包含无关内容。
未通过审核的签名会导致短信发送失败。
2. sms.aliyun.endpoint
含义:阿里云短信服务的API接入地址。
作用:
指定请求发送到阿里云的哪个服务器节点,通常使用默认值即可。
若需优化网络延迟,可根据地域选择特定节点(如dysmsapi.ap-southeast-1.aliyuncs.com)。
注意:
默认值适用于大多数场景,无需修改,除非阿里云文档特别说明。
3. sms.type
含义:短信服务商类型标识(通常为项目自定义配置)。
作用:
在多服务商支持的系统中,通过此字段切换短信服务商(例如:1=腾讯云,2=华为云,3=阿里云)。
注意:
此配置为项目自定义逻辑,需结合代码实现判断使用哪个服务商,与阿里云官方SDK无关。
4. sms.aliyun.template.default.name
含义:默认短信模板的名称(项目自定义标识)。
作用:
在代码中通过此名称引用模板,便于管理多个模板(如“验证码短信”“通知短信”等)。
实际发送短信时仍需依赖模板CODE(sms.aliyun.template.default.code)。
注意:
此名称仅用于代码可读性,与阿里云控制台的模板名称无关。
5. sms.aliyun.template.default.code
含义:默认短信模板的CODE。
作用:
指定发送短信时使用的模板(需与阿里云控制台中申请的模板CODE一致)。
例如,验证码短信模板内容可能是:“您的验证码为${code},5分钟内有效。”
注意:
模板需通过阿里云审核,且状态为“审核通过”才能使用。
6. sms.aliyun.template.default.variable
含义:默认短信模板中的变量名。
作用:
替换模板中的动态内容。例如,模板内容为“验证码:${code}”,此处配置变量名为code,发送时需传入code=123456。
代码中需按此变量名构建参数(如Map<String, String> params = Map.of(“code”, “123456”))。
注意:
变量名必须与模板中的占位符完全一致(区分大小写)。
7. sms.aliyun.template.invite.code
含义:邀请类短信模板的CODE。
作用:
区分不同业务场景的短信模板。例如:
default模板用于验证码。
invite模板用于邀请链接(如“您的好友邀请您加入,点击链接:${url}”)。
代码中可根据业务类型选择不同模板发送。
注意:
每个模板需单独申请,且变量名可能不同(如邀请模板的变量名可能是url)。
业务配置文件
一般是两块业务,发送短信验证码,以及邀约
@Resourceprivate AliSmsConfig aliSmsConfig;@Resourceprivate Client smsClient;
//发送短信验证@Overridepublic void sendVerifySms(SmsVerifyCmd smsVerifyCmd) {SmsVerifyParamDTO param =new SmsVerifyParamDTO(smsVerifyCmd.getCode());checkRedis(smsVerifyCmd.getPhone());sendSms(aliSmsConfig.getSignName(),aliSmsConfig.getVerifyTemplateCode(), smsVerifyCmd.getPhone(),JSON.toJSONString(param));}@Overridepublic void sendInviteSms(SmsInviteRpcCmd inviteRpcCmd) {sendSms(aliSmsConfig.getSignName(),aliSmsConfig.getInviteTemplateCode(), inviteRpcCmd.getPhone(),JSON.toJSONString(inviteRpcCmd.getParam()));}
利用手机号码来做分布式锁检查,后续发送完,例如登录的时候可以从redis中获取验证法还同时拥有了过期时间,一举两得
/*** 利用手机号码来做分布式锁检查* @param phone*/private void checkRedis(String phone) {boolean lock = redisTemplate.opsForValue().setIfAbsent(CacheEnum.SMS_VERIFY_CODE_REGISTER.getMsg(phone), SMS_REDIS_LOCK_VALUE, SMS_SEND_GAP, TimeUnit.SECONDS);if (!lock) {throw ExFactory.bizException(REDIS_LOCK_ERROR);}}
下面自定义阿里云短信服务的 Client 对象,初始化Client对象的值
@Configuration(enforceUniqueMethods=false)
@Data
public class AliSmsConfig {@Value("${AccessKeyID}")private String accessKeyId;@Value("${AccessKeySecret}")private String accessKeySecret;@Value("${sms.aliyun.endpoint}")private String endPoint;@Value("${sms.aliyun.sign-name}")private String signName;@Value("${sms.aliyun.template.default.code}")private String verifyTemplateCode;@Value("${sms.aliyun.template.invite.code}")private String inviteTemplateCode;@Beanpublic Client aliSmsClient() {Config config = new Config();config.setAccessKeyId(accessKeyId);config.setAccessKeySecret(accessKeySecret);config.setEndpoint(endPoint);try {return new Client(config);} catch (Exception e) {throw new RuntimeException(e);}}}
enforceUniqueMethods=false 这个参数是 Spring 特有的,用于控制配置类中方法名是否要唯一。此参数通常用于避免重复 Bean 定义问题,允许多个方法具有相同的名字。
业务代码
private void sendSms(String signName, String verifyTemplateCode, String phone, String param) {MsgSmsLog sl =new MsgSmsLog().setId(getLeafId()).setStatus(0).setContent(param).setPhone(phone).setCreateTime(new Date());SendSmsRequest sendSmsRequest = new SendSmsRequest().setPhoneNumbers(phone).setSignName(signName).setTemplateCode(verifyTemplateCode).setTemplateParam(param);SendSmsResponse smsResponse =null;try {smsResponse = smsClient.sendSms(sendSmsRequest);} catch (Exception e) {e.printStackTrace();sl.setStatus(2).setResult(ALIYUN_SMS_SEND_ERROR).setUpdateTime(new Date());smsLogMapper.insert(sl);throw ExFactory.bizException(SMS_SEND_ERROR);}log.info("sms 发送返回信息 :{}",JSON.toJSONString(smsResponse));if(smsResponse!=null &&smsResponse.getStatusCode()==200){if(smsResponse.getBody().getCode().equals(ALIYUN_SMS_SEND_OK)){//发送成功sl.setStatus(1).setResult(ALIYUN_SMS_SEND_OK).setUpdateTime(new Date());smsLogMapper.insert(sl);}else{//发送失败sl.setStatus(2).setResult(smsResponse.getBody().getMessage()).setUpdateTime(new Date());smsLogMapper.insert(sl);throw new BizException(SMS_SEND_ERROR.getKey(),smsResponse.getBody().getMessage());}}else{//请求失败sl.setStatus(2).setResult(ALIYUN_SMS_SEND_ERROR).setUpdateTime(new Date());smsLogMapper.insert(sl);throw new BizException(SMS_SEND_ERROR.getKey(),ALIYUN_SMS_SEND_ERROR);}}
总结
短信推荐方案:
直接调用阿里云、腾讯云等SDK,方便快捷