阿里云短信服务 实现发送短信功能(代码示例)
1.首先进入阿里云官网,开通短信服务
官网地址:阿里云官网
注册阿里云账号并登录,打开控制台
进入控制台后,点击左上角
开通短信服务
2.进入子用户页面,为短信服务设置子用户AccessKey
点击右上角的主账号,选择AccessKey管理
选择使用子用户
点击用户,创建用户,并添加权限
最后就是创建成功后,一定要马上保存你的 AccessKey ID 和 AccessKey Secret,下次进来就不会显示了。切记!!!!!这个很重要,没有保存到就只有重新创建啦。
3.申请签名和模版
这里根据个人需求进行申请,一般审核在1到2个小时左右。
3.购买短信套餐,新用户可以选择0元试用
套餐赠送100条短信,测试使用已经足够了。
4.测试短信发送
首先进入 Open API 开发者门户,简单测试一下,检查是否能够正常获取短信
输入手机号,选择短信签名和短信模版,就可以进行测试了,结果返回OK,证明测试成功。
这里可以看到我们的手机已经收到了短信验证码,但是这里需要注意的是 如果你选择的签名是测试或学习,只能给绑定的手机号发送短信才能成功。
绑定测试的手机号
到这里基本上,我们就已经成功了一半啦。下面就是手撕代码了。
5.调用SDK实现短信发送功能(代码示例)
首先看一下目录结构
pom.xml文件需要导入的依赖包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-openapi</artifactId>
<version>0.2.8</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-console</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-util</artifactId>
<version>0.2.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea</artifactId>
<version>1.1.14</version>
</dependency>
<!-- 配置文件处理器 -->
<!--让自定义的配置在application.yaml进行自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
controller层
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/20 22:30
*/
@Slf4j
@CrossOrigin //跨域
@Api(tags = "短信管理")
@RestController
@RequestMapping("/api")
public class ApiSmsController {
@Resource
private ISmsService smsService;
@Resource
private RedisTemplate redisTemplate;
@ApiOperation("获取短信验证码")
@GetMapping("/sendSms/{mobile}")
public R send(@ApiParam(value = "手机号", required = true) @PathVariable String mobile) {
try {
//判断手机号是否为空 - MOBILE_NULL_ERROR(-202, "手机号不能为空"),
Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);
//判断手机号是否正确 - MOBILE_ERROR(-203, "手机号不正确"),
Assert.isTrue(SmsUtils.checkPhoneNum(mobile), ResponseEnum.MOBILE_ERROR);
//生成验证码
String smsCode = RandomUtils.getSixBitRandom();
//组装短信模板参数
Map<String, Object> param = new HashMap<>();
param.put("code", smsCode);
String templateParam = new Gson().toJson(param);
//发送短信
smsService.send(mobile, templateParam);
//将验证码存入redis,设置5分钟过期
redisTemplate.opsForValue().set(RedisSmsConstant.SMS_CODE_KEY_PREFIX+mobile,smsCode,5, TimeUnit.MINUTES);
log.info("验证码:{}",smsCode);
return R.ok().message("短信发送成功,请注意接收");
} catch (Exception e) {
e.printStackTrace();
log.error("获取短信验证码失败:" + ExceptionUtils.getStackTrace(e));
return R.error().message(e.getMessage());
}
}
}
service层
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/20 22:49
*/
public interface ISmsService {
void send(String mobile, String templateParam);
}
service实现类
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/20 22:50
*/
@Slf4j
@Service
public class SmsServiceImpl implements ISmsService {
@Override
public void send(String mobile, String templateParam) {
try {
//使用工具类发送手机短信
SmsResponseResult result = SmsRemoteApi.sendSms(mobile, templateParam);
log.info("阿里云短信发送SDK调用成功:{}", result);
//ALIYUN_RESPONSE_FAIL(-501, "阿里云响应失败"),
Assert.isTrue(result.getStatusCode() == 200, ResponseEnum.ALIYUN_RESPONSE_FAIL);
//ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
Assert.notEquals("isv.BUSINESS_LIMIT_CONTROL", result.getBody().get("code").toString(), ResponseEnum.ALIYUN_SMS_LIMIT_CONTROL_ERROR);
//ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败
Assert.equals("OK", result.getBody().get("code").toString(), ResponseEnum.ALIYUN_SMS_ERROR);
} catch (ServerException e) {
log.error("阿里云短信发送SDK调用失败:" + ExceptionUtils.getStackTrace(e));
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR, e);
} catch (ClientException e) {
log.error("阿里云短信发送SDK调用失败:" + ExceptionUtils.getStackTrace(e));
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR, e);
} catch (Exception e) {
log.error("短信发送失败:" + ExceptionUtils.getStackTrace(e));
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR, e);
}
}
}
手机校验工具类
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/21 0:18
* 手机号校验工具类
*/
public class SmsUtils {
public static final String PHONE_RULES = "^(\\+|00){0,2}(9[976]\\d|8[987530]\\d|6[987]\\d|5[90]\\d|42\\d|3[875]\\d|2[98654321]\\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\\d{1,14}$";
/**
* 校验手机号
*
* @param phoneNum
* @return
*/
public static boolean checkPhoneNum(String phoneNum) {
return !StringUtils.isEmpty(phoneNum) && phoneNum.matches(PHONE_RULES) && checkMobileNum(phoneNum);
}
/**
* 校验手机号
*
* @param mobileNum
* @return
*/
public static boolean checkMobileNum(String mobileNum) {
if (mobileNum.startsWith("1") && mobileNum.length() == 11) {
return true;
} else {
return false;
}
}
}
读取yml配置文件的配置类
package com.atguigu.srb.sms.util;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Setter
@Getter //idea2020.2.3版配置文件自动提示需要这个
@Component
//注意prefix要写到最后一个 "." 符号之前
//调用setter为成员赋值
@ConfigurationProperties(prefix = "aliyun.sms")
public class SmsProperties implements InitializingBean {
// private String regionId;
private String keyId;
private String keySecret;
private String templateCode;
private String signName;
// public static String REGION_Id;
public static String KEY_ID;
public static String KEY_SECRET;
public static String TEMPLATE_CODE;
public static String SIGN_NAME;
//当私有成员被赋值后,此方法自动被调用,从而初始化常量
@Override
public void afterPropertiesSet() throws Exception {
// this.REGION_Id = this.regionId;
this.KEY_ID = this.keyId;
this.KEY_SECRET = this.keySecret;
this.TEMPLATE_CODE = this.templateCode;
this.SIGN_NAME = this.signName;
}
}
application.yml文件配置我们阿里云短信的相关参数
#阿里云短信
aliyun:
sms:
key-id: 你的keyid
key-secret: 你的keysecret
template-code: 你的短信模板code
sign-name: 你的短信模板签名
远程调用阿里云短信服务API
package com.atguigu.srb.sms.remote;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.atguigu.common.exception.BusinessException;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.sms.result.SmsResponseResult;
import com.atguigu.srb.sms.util.SmsProperties;
import com.atguigu.srb.sms.util.SmsUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/21 16:22
* 短信发送远程调用
*/
public class SmsRemoteApi {
/**
* 使用AK&SK初始化账号Client
*
* @param accessKeyId
* @param accessKeySecret
* @return Client
* @throws Exception
*/
public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,您的 AccessKey ID
.setAccessKeyId(accessKeyId)
// 必填,您的 AccessKey Secret
.setAccessKeySecret(accessKeySecret);
// 访问的域名
config.endpoint = "dysmsapi.aliyuncs.com";
return new com.aliyun.dysmsapi20170525.Client(config);
}
public static SmsResponseResult sendSms(String mobile, String templateParam) throws Exception {
com.aliyun.dysmsapi20170525.Client client = SmsRemoteApi.createClient(SmsProperties.KEY_ID, SmsProperties.KEY_SECRET);
com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
.setPhoneNumbers(mobile)
.setSignName(SmsProperties.SIGN_NAME)
.setTemplateCode(SmsProperties.TEMPLATE_CODE)
.setTemplateParam(templateParam);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
SmsResponseResult responseResult = encapsulationResults(sendSmsResponse);
return responseResult;
} catch (Exception error) {
error.printStackTrace();
throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR);
}
}
private static SmsResponseResult encapsulationResults(SendSmsResponse response) {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.convertValue(response.getBody(), Map.class);
SmsResponseResult responseResult = SmsResponseResult.builder()
.headers(response.getHeaders())
.statusCode(response.getStatusCode())
.body(map)
.build();
// System.out.println(responseResult.getHeaders());
// System.out.println(responseResult.getStatusCode());
// System.out.println(responseResult.getBody());
return responseResult;
}
}
接收调用返回结果的实体类
package com.atguigu.srb.sms.result;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import lombok.Builder;
import lombok.Data;
import java.util.Map;
/**
* @author pgx
* @version V1.0.0
* @date 2023/7/21 14:15
*/
@Data
@Builder
public class SmsResponseResult {
public Map<String,String> headers;
public Integer statusCode;
public Map<String,Object> body;
/*public SmsResponseResult setHeaders(Map<String,String> headers){
this.headers = headers;
return this;
}
public SmsResponseResult setStatusCode(Integer statusCode){
this.statusCode = statusCode;
return this;
}
public SmsResponseResult setBody(Map<String,Object> body){
this.body = body;
return this;
}*/
}
写到这里,基本上我们的短信服务就已经实现了。下面我们通过swagger简单的测试一下,是否可以调用成功。
IDEA控制台
手机收到的验证码
到此就差不多已经结束了,感谢你的观看!如有不理解的地方,可私信交流学习。