消息-短信

1. 短信平台

2. 购买短信

个人开发或者测试可以接入第三方厂商,费用很低,不需要审核

https://market.aliyun.com/products/57000002/cmapi00046920.html

购买3元75条和0元5条测试

购买成功后,打开地址,查看订单和开发需要用到的AppKey,AppSecret,AppCode

3. 代码接入

3.1 配置文件

1
2
3
4
#短信配置
sms:
app-code: 订单中的AppCode
template-id: M72CB42894

3.2 短信配置类

1
2
3
4
5
6
7
8
9
10
@ConfigurationProperties(prefix = "sms")
@Configuration
@Data
public class SmsConfig {

private String appCode;

private String templateId;

}

3.3 HTTP发送配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}

@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(3000);
factory.setConnectTimeout(3000);
return factory;
}
}

3.4 发送短信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
@Slf4j
public class SmsComponent {

@Autowired
private RestTemplate restTemplate;
@Autowired
private SmsConfig smsConfig;

private static final String URL_TEMPLATE = "https://jmsms.market.alicloudapi.com/sms/send?mobile=%s&templateId=%s&value=%s";

public void send(String to, String value) {
String url = String.format(URL_TEMPLATE, to, smsConfig.getTemplateId(), value);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "APPCODE " + smsConfig.getAppCode());
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
if (response.getStatusCode() == HttpStatus.OK) {
log.info("发送短信成功,响应信息:{}", response.getBody());
} else {
log.error("发送短信失败,响应信息:{}:{}", response.getStatusCode(), response.getBody());
}
}
}

3.5 单元测试

1
2
3
4
5
6
7
8
9
10
11
@SpringBootTest
public class AccountTest {

@Autowired
private SmsComponent smsComponent;

@Test
void sendTest() {
smsComponent.send("18566668888", "666888");
}
}

3.6 短信验证码失效时间

开发中短信验证码,一般有两个过期时间,一个是60秒防止重复发送,一个验证码10分钟有效,通过一个redis的key来判断,可以通过过期时间差来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static final Long CODE_EXPIRE_SECONDS = 600L;

public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {
String cacheKey = String.format(RedisKey.CHECK_CODE_KEY, sendCodeEnum.name(), to);
Long expireSeconds = stringRedisTemplate.getExpire(cacheKey, TimeUnit.SECONDS);
//判断是否是60秒内重复发送
if(CODE_EXPIRE_SECONDS - expireSeconds < 60) {
return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
}
String code = CommonUtil.getRandomCode(6);
stringRedisTemplate.opsForValue().set(cacheKey, code, CODE_EXPIRE_SECONDS, TimeUnit.SECONDS);
if(CheckUtil.isEmail(to)) {
//发送邮箱验证码
} else if(CheckUtil.isPhone(to)) {
//发送短信验证码
smsComponent.send(to, smsConfig.getTemplateId(), code);
}
return JsonData.buildSuccess();
}