前言:
獲取AccessKeyID ,AccessKey Secret我就說個大概,大家可以看官方的幫助文檔,進行獲取,後面的代碼部分並沒有給出全部的代碼,只是爲了提供給大家思路,如果有需要,歡迎留言,我私發給他。
一、前期準備
首先註冊一個阿里雲賬號
然後登錄,產品分類,選擇短信服務
點擊管理控制檯
進入到下面的界面就可以通過新手引導,和開發者指南進行操作了
國內消息,進去之後可以添加簽名和模板
輸入網址:https://ram.console.aliyun.com/users
創建用戶
授權
點擊你創建好的用戶,如下圖
進入之後創建AccessKey,就會找到AccessKeyID和AccessKeySecret
我們的目的就是得到下面的四個值:
AccessKeyID不要給別人看
AccessKeyID:你自己的accessKeyId
AccessKeySecret:你自己的AccessKeySecret
模板code:模板CODE
簽名:簽名名稱
二、demo
背景:一個用戶的微服務user-service,一個手機短信驗證微服務sms-service,此時用戶輸入自己的手機號,會發送過來一個驗證碼,由於是兩個服務我們採取將驗證碼存在redis裏。由於短信接收具有時長不定性,爲了提高程序的響應速度,短信發送採用異步的方式,就是說收到消息後發送短信,我們的用戶微服務(user-service)我們通過RabbitMq通知短信微服務(sms-service)發送短信。
1、創建一個短信服務
2、屬性抽取
將上面的四個常量抽取到你的yml文件中
application.yml
server:
port: 8086
spring:
application:
name: sms-service
rabbitmq:
host: 152.136.203.163
username: leyou
password: 你自己的密碼
virtual-host: /v_leyou
leyou:
sms:
accessKeyId: # 你自己的accessKeyId
accessKeySecret: # 你自己的AccessKeySecret
signName: # 簽名名稱
verifyCodeTemplate: # 模板名稱CODE
3、注入到屬性類中
@ConfigurationProperties(prefix = "leyou.sms")
public class SmsProperties {
String accessKeyId;
String accessKeySecret;
String signName;
String verifyCodeTemplate;
// getter和setter省略
}
prefix的值要和yml中一致
4、smsUtils (這個官網有模板,複製黏貼就好,然後簡單改改)
@Component
@EnableConfigurationProperties(SmsProperties.class) //使屬性類生效
public class SmsUtils {
@Autowired
private SmsProperties prop;
//產品名稱:雲通信短信API產品,開發者無需替換
static final String product = "Dysmsapi";
//產品域名,開發者無需替換
static final String domain = "dysmsapi.aliyuncs.com";
static final Logger logger = LoggerFactory.getLogger(SmsUtils.class);
public SendSmsResponse sendSms(String phone, String code, String signName, String template) throws ClientException {
//可自助調整超時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暫不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou",
prop.getAccessKeyId(), prop.getAccessKeySecret());
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//組裝請求對象-具體描述見控制檯-文檔部分內容
SendSmsRequest request = new SendSmsRequest();
request.setMethod(MethodType.POST);
//必填:待發送手機號
request.setPhoneNumbers(phone);
//必填:短信簽名-可在短信控制檯中找到
request.setSignName(signName);
//必填:短信模板-可在短信控制檯中找到
request.setTemplateCode(template);
//可選:模板中的變量替換JSON串,如模板內容爲"親愛的${name},您的驗證碼爲${code}"時,此處的值爲
request.setTemplateParam("{\"code\":\"" + code + "\"}");
//選填-上行短信擴展碼(無特殊需求用戶請忽略此字段)
//request.setSmsUpExtendCode("90997");
//可選:outId爲提供給業務方擴展字段,最終在短信回執消息中將此值帶回給調用者
request.setOutId("123456");
//hint 此處可能會拋出異常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
logger.info("發送短信狀態:{}", sendSmsResponse.getCode());
logger.info("發送短信消息:{}", sendSmsResponse.getMessage());
return sendSmsResponse;
}
}
5、SmsListener
@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SmsListener {
@Autowired
private SmsUtils smsUtils;
@Autowired
private SmsProperties prop;
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "LEYOU.SMS.QUEUE", durable = "true"),
exchange = @Exchange(value = "LEYOU.SMS.EXCHANGE", ignoreDeclarationExceptions = "true"),
key={"sms.verify.code"}))
public void listenSms(Map<String, String> msg) throws ClientException {
if(CollectionUtils.isEmpty(msg))
{
//放棄處理
return;
}
String phone=msg.get("phone");
String code=msg.get("code");
if (StringUtils.isBlank(phone)||StringUtils.isBlank(code)){
return;
}
SendSmsResponse resp =this.smsUtils.sendSms(phone,code,prop.getSignName(),prop.getVerifyCodeTemplate());
}
}
6、創建一個用戶微服務
7、UserController代碼
/**
* 生成短信驗證碼
* @param phone
* @return
*/
@PostMapping("code")
public ResponseEntity<Void> sendVerifyCode(String phone){
Boolean aBoolean = this.userService.sendVerifyCode(phone);
if (!aBoolean){
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(HttpStatus.CREATED);
}
8、UserService
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 驗證碼前綴,這個是註冊,的以後可能還會有訂單
static final String KEY_PREFIX = "user:code:phone:";
static final Logger logger = LoggerFactory.getLogger(UserService.class);
public Boolean sendVerifyCode(String phone) {
String code= NumberUtils.generateCode(6);
try {
HashMap<String, String> msg = new HashMap<>();
msg.put("phone",phone);
msg.put("code",code);
this.amqpTemplate.convertAndSend("LEYOU.SMS.EXCHANGE","sms.verify.code",msg);
// 將code存入redis 5分鐘失效
this.stringRedisTemplate.opsForValue().set(KEY_PREFIX+phone,code,5, TimeUnit.MINUTES);
return true;
} catch (AmqpException e) {
logger.error("發送短信失敗。phone:{},code:{}",phone,code);
return false;
}
}
9、UserMapper
public interface UserMapper extends Mapper<User> {
}
這裏需要引用通用mapper 座標
<!-- 通用Mapper啓動器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
10啓動服務,通過postman測試
收到短信