发短信居然这么简单?阿里云短信服务极速接入指南

发短信居然这么简单?阿里云短信服务极速接入指南

目录

前言

了解流程

介绍

快速学习与测试

绑定手机号

调用API发送短信

SDK调用API

安装SDK

复制代码

替换AccessKeyId和AccessKeySecret

​编辑

说明

常见验证码流程

工具类

使用示例

配置文件

前言

我们使用阿里云短信SDK来进行发短信,目前SDK V1.0不再维护,现在使用的V2.0版本。

了解流程

一条短信由短信签名和短信模板组成,因此在发送短信前,您需要先完成短信资质以及签名、模板

的申请工作,并等待审核通过。通过模板变量自定义,您可以实现短信内容的定制化。

运营商实名报备流程平均需要5-7个工作日,基于近期观测,部分运营商实名报备流程需要7-10个

工作日,但运营商未对此时效进行承诺,实际可能需要更长时间。建议您合理规划业务并提前申请

相关资质和签名,以确保在正式使用前有充足的时间完成实名报备。

介绍

短信服务官方文档:短信服务(SMS)-阿里云帮助中心

开通阿里云短信服务点击国内消息有资质管理、签名管理、模板管理(这个要企业资质才能玩)正常就按照这个顺序配置 资质—>签名—>模板

快速学习与测试

由于我们没有企业资质,所以只能使用快速学习与测试功能,来调用API发送短信。

绑定手机号

在这里我们绑定一个手机号,用于后续发送验证码。

调用API发送短信

选择【专用】测试签名/模板 点击调用API发送短信

点击发起调用 可以看到响应报文

刚刚绑定的测试手机号就可以收到测试验证码

SDK调用API

安装SDK

找到SDK实例 点击SDK安装信息 获取maven依赖 添加进我们项目中。

复制代码

选择SDK代系V2.0 语言选择Java(也可以选择异步),复制代码信息。

替换AccessKeyId和AccessKeySecret

由于工程代码使用的是更安全的无AK方式,所以我们要改造一下代码,使用我们自己配置的AK。

然后运行代码发送短信即可。

Config config = new Config();

config.setAccessKeyId("xxxxx");

config.setAccessKeySecret("xxxxx");

return new Client(config);

说明

后续开发只需要把AK替换成自己的,配置短信签名、模板代码、手机号码、模板变量即可。

有问题可以查看官网文档:短信服务_SDK中心-阿里云OpenAPI开发者门户

常见验证码流程

一般发送验证码,由服务端生成验证码存储在Redis中,存储在Redis中5分钟内有效,调用阿里云

短信发送验证码,用户输入验证码从Redis拿到验证码进行校验,一般只能1分钟发送一次验证码,

如果1分钟后重新获取之前验证码失效。

代码实现参考:

public void handleSmsFlow(String phone) {

// 1.频率控制检查

if (redisTemplate.hasKey(buildCoolingKey(phone))) {

throw new BusinessException("操作过于频繁");

}

// 2.生成&存储验证码

String code = generateRandomCode();

redisTemplate.opsForValue().set(buildCodeKey(phone), code, 5, MINUTES);

redisTemplate.opsForValue().set(buildCoolingKey(phone), "", 1, MINUTES);

// 3.异步发送短信

CompletableFuture.runAsync(() -> {

try {

smsClient.sendVerificationCode(phone, code);

} catch (Exception e) {

alertService.notifySmsFailure(phone, code);

}

}, smsThreadPool);

}

private String buildCoolingKey(String phone) {

return "sms:cooling:" + phone;

}

private String buildCodeKey(String phone) {

return "sms:code:" + phone;

}

工具类

使用AI对技术代码进行工具类封装。

package com.taoran.sms.util;

import com.aliyun.dysmsapi20170525.Client;

import com.aliyun.dysmsapi20170525.models.SendSmsRequest;

import com.aliyun.dysmsapi20170525.models.SendSmsResponse;

import com.aliyun.teaopenapi.models.Config;

import com.aliyun.teautil.Common;

import com.aliyun.teautil.models.RuntimeOptions;

import com.aliyun.tea.TeaException;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import java.util.Map;

/**

* 阿里云短信服务工具类[3,6](@ref)

* 功能特性:

* 1. 自动加载云资源配置

* 2. 动态模板参数支持

* 3. 异常重试机制

* 4. 全链路日志追踪

*/

@Slf4j

@Component

public class AliyunSmsUtil {

// 通过@Value注入配置参数(生产环境推荐使用配置中心)

@Value("${aliyun.sms.access-key-id}")

private String accessKeyId;

@Value("${aliyun.sms.access-key-secret}")

private String accessKeySecret;

@Value("${aliyun.sms.sign-name}")

private String signName;

@Value("${aliyun.sms.endpoint}")

private String endpoint = "dysmsapi.aliyuncs.com"; // 默认值

private Client client;

// 初始化客户端[6](@ref)

@PostConstruct

private void initClient() throws Exception {

Config config = new Config()

.setAccessKeyId(accessKeyId)

.setAccessKeySecret(accessKeySecret);

config.endpoint = endpoint;

this.client = new Client(config);

log.info("阿里云短信客户端初始化完成,Endpoint: {}", endpoint);

}

/**

* 通用短信发送方法[3,6](@ref)

* @param phoneNumbers 接收号码(多个用逗号分隔)

* @param templateCode 模板CODE

* @param templateParams 模板参数键值对

* @return 发送结果

*/

public SendSmsResponse send(String phoneNumbers,

String templateCode,

Map templateParams) {

try {

SendSmsRequest request = buildRequest(phoneNumbers, templateCode, templateParams);

return executeSend(request);

} catch (Exception e) {

log.error("短信发送异常 | phones:{} | template:{}", phoneNumbers, templateCode, e);

return null;

}

}

// 构建请求对象[6](@ref)

private SendSmsRequest buildRequest(String phoneNumbers,

String templateCode,

Map params) {

return new SendSmsRequest()

.setPhoneNumbers(phoneNumbers)

.setSignName(signName)

.setTemplateCode(templateCode)

.setTemplateParam(convertToJson(params));

}

// 执行发送操作[6](@ref)

private SendSmsResponse executeSend(SendSmsRequest request) throws Exception {

RuntimeOptions runtime = new RuntimeOptions();

try {

SendSmsResponse response = client.sendSmsWithOptions(request, runtime);

log.debug("短信发送成功 | RequestId:{}", response.getBody().requestId);

return response;

} catch (TeaException e) {

handleTeaException(e);

throw new RuntimeException("阿里云服务异常", e);

}

}

// 异常处理[6](@ref)

private void handleTeaException(TeaException e) {

log.error("阿里云API异常 || Code:{} | Message:{} | Recommend:{}",

e.getCode(), e.getMessage(), e.getData().get("Recommend"));

}

// Map转JSON工具[3](@ref)

private String convertToJson(Map params) {

if (params == null || params.isEmpty()) return "{}";

StringBuilder json = new StringBuilder("{");

params.forEach((k, v) ->

json.append("\"").append(k).append("\":\"").append(v).append("\","));

json.deleteCharAt(json.length()-1).append("}");

return json.toString();

}

}

使用示例

// 在Spring Boot控制器中使用

@RestController

@RequestMapping("/sms")

public class SmsController {

@Autowired

private AliyunSmsUtil smsUtil;

@PostMapping("/send-verification")

public ResponseEntity sendVerification(@RequestParam String phone) {

Map params = Map.of("code", generateRandomCode(6));

SendSmsResponse response = smsUtil.send(

phone,

"SMS_154950909",

params

);

if (response != null && "OK".equals(response.getBody().getCode())) {

return ResponseEntity.ok("验证码发送成功");

}

return ResponseEntity.status(500).body("发送失败");

}

private String generateRandomCode(int length) {

// 生成随机验证码逻辑[6](@ref)

}

}

配置文件

aliyun:

sms:

access-key-id: xxxxx

access-key-secret: xxxx

sign-name: 阿里云短信测试

endpoint: dysmsapi.aliyuncs.com

相关推荐