简介
- 短信服务(Short Message Service、SMS)是指通过调用短信发送API,将指定短信内容发送给指定手机用户。
阿里云短信服务
发送短信(发送验证码)
- 需要以下配置
- 在阿里云管理后台右上角,账号 - AccessKey管理中查看
accessKeyId
、accessKeySecret
- 自己配置的短信模板ID(如:SMS_45680123)
- 模板变量(如果模板中存在变量,如${code})
- 使用maven
<!-- aliyun短信 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.1</version>
</dependency>
@Slf4j
public class SmsU {
public static void main(String[] args) {
SmsU.sendMessage("15812345678");
}
/********************************************* 需要修改的部分start *************************************************/
/**
* 需要替换为自己的ACCESS_KEY_ID
*/
private static final String ACCESS_KEY_ID = "";
/**
* 需要替换为自己的ACCESS_KEY_SECRET
*/
private static final String ACCESS_KEY_SECRET = "";
/**
* 这里要修改为自己的短信签名
*/
private static final String SIGN_NAME = "";
/**
* 修改为自己的模板CODE
*/
private static final String TEMPLATE_CODE = "";
/**
* 模板中的变量名称,例如模板中为${code},此处就填写code
*/
private static final String TEMPLATE_PARAM = "code";
/********************************************* 需要修改的部分end *************************************************/
private static final Pattern PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
/**
* 下面是一些默认的配置,无需修改
* REGION_ID 服务器大区 不建议修改
* SYS_DOMAIN API地址 不可修改
* SYS_VERSION 系统版本 不可修改
* SYS_ACTION API接口名必须为SendSms 不可修改
*/
private static final String REGION_ID = "cn-hangzhou";
private static final String SYS_DOMAIN = "dysmsapi.aliyuncs.com";
private static final String SYS_VERSION = "2017-05-25";
private static final String SYS_ACTION = "SendSms";
private static IAcsClient client = null;
private static CommonRequest request = null;
static {
DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
client = new DefaultAcsClient(profile);
request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain(SYS_DOMAIN);
request.setSysVersion(SYS_VERSION);
request.setSysAction(SYS_ACTION);
request.putQueryParameter("RegionId", REGION_ID);
request.putQueryParameter("SignName", SIGN_NAME);
request.putQueryParameter("TemplateCode", TEMPLATE_CODE);
}
private SmsU() {}
/**
* 发送短信
* @param phoneNumber 手机号码
* @return code
*/
public static Result sendMessage(String phoneNumber) {
if (!isPhoneNumber(phoneNumber)) {
return Result.failure("手机号格式不正确");
}
// 获取六位随机数. 基于Hutool
String code = RandomUtil.randomString("0123456789", 6);
// 初始化用户自定义参数
request.putQueryParameter("PhoneNumbers", phoneNumber);
// 在短信内容中嵌入随机数
request.putQueryParameter("TemplateParam", "{\"" + TEMPLATE_PARAM + "\":\"" + code + "\"}");
// 发送的业务逻辑
try {
// {"Message":"账户余额不足","RequestId":"415E9BF0-6904-5920-933A-F27B920E2644","Code":"isv.AMOUNT_NOT_ENOUGH"}
// {"Message":"触发分钟级流控Permits:1","RequestId":"9D7F3798-1CA1-5110-9056-1ECB14A91097","Code":"isv.BUSINESS_LIMIT_CONTROL"}
// {"Message":"OK","RequestId":"2E6BD8A4-D1A3-5A25-A237-2AB702893632","Code":"OK","BizId":"303700784907161870^0"}
CommonResponse response = client.getCommonResponse(request);
if(response.getHttpStatus() != 200 || !"OK".equals(JSONUtil.parseObj(response.getData()).get("Message"))) {
log.error("发送短信失败 {} {} {}", phoneNumber, response.getHttpStatus(), response.getData());
return Result.failure("发送短信失败");
}
} catch (Exception e) {
log.error("发送短信出错 {}", phoneNumber, e);
return Result.failure("发送短信出错");
}
return Result.success(code);
}
public static boolean isPhoneNumber(String phoneNumber) {
Matcher m = PATTERN.matcher(phoneNumber);
return m.matches();
}
}
@Slf4j
public class SmsU {
private static volatile SmsU INSTANCE;
private static final Pattern PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
/**
* 下面是一些默认的配置,无需修改
* REGION_ID 服务器大区 不建议修改
* SYS_DOMAIN API地址 不可修改
* SYS_VERSION 系统版本 不可修改
* SYS_ACTION API接口名必须为SendSms 不可修改
*/
private static final String REGION_ID = "cn-hangzhou";
private static final String SYS_DOMAIN = "dysmsapi.aliyuncs.com";
private static final String SYS_VERSION = "2017-05-25";
private static final String SYS_ACTION = "SendSms";
private IAcsClient client = null;
private CommonRequest request = null;
private SmsU() {
}
public static SmsU getInstance() {
if (INSTANCE == null) {
synchronized (SmsU.class) {
if(INSTANCE == null) {
Environment environment = SpringU.getBean(Environment.class);
String accessKeyId = environment.getProperty("aezo-app-common.sms.aliyun.access-key-id");
String accessKeySecret = environment.getProperty("aezo-app-common.sms.aliyun.access-key-secret");
DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, accessKeyId, accessKeySecret);
INSTANCE = new SmsU();
INSTANCE.client = new DefaultAcsClient(profile);
INSTANCE.request = new CommonRequest();
INSTANCE.request.setSysMethod(MethodType.POST);
INSTANCE.request.setSysDomain(SYS_DOMAIN);
INSTANCE.request.setSysVersion(SYS_VERSION);
INSTANCE.request.setSysAction(SYS_ACTION);
INSTANCE.request.putQueryParameter("RegionId", REGION_ID);
}
}
}
return INSTANCE;
}
/**
* 发送短信
* @param phoneNumber 手机号码
* @return code
*/
public static String sendMessage(String phoneNumber) {
// 获取六位随机数
String randomCode = RandomUtil.randomString("0123456789", 6);
return sendMessage(phoneNumber, randomCode);
}
/**
* 发送短信
* @param phoneNumber 手机号码
* @param randomCode 验证码
* @return code
*/
public static String sendMessage(String phoneNumber, String randomCode) {
Environment environment = SpringU.getBean(Environment.class);
String signName = environment.getProperty("aezo-app-common.sms.aliyun.sign-name");
String templateCode = environment.getProperty("aezo-app-common.sms.aliyun.template-code");
String templateParam = environment.getProperty("aezo-app-common.sms.aliyun.template-param");
return sendMessage(phoneNumber, randomCode, signName, templateCode, templateParam);
}
/**
* 发送短信
* @param phoneNumber 手机号码
* @param randomCode 验证码
* @param signName 短信签名
* @param templateCode 模板CODE
* @param templateParam 模板中的变量名称,例如模板中为${code},此处就填写code
* @return code
*/
public static String sendMessage(String phoneNumber, String randomCode, String signName, String templateCode, String templateParam) {
if (!isPhoneNumber(phoneNumber)) {
throw new BizException("手机号格式不正确");
}
SmsU instance = getInstance();
instance.request.putQueryParameter("PhoneNumbers", phoneNumber);
instance.request.putQueryParameter("SignName", signName);
instance.request.putQueryParameter("TemplateCode", templateCode);
instance.request.putQueryParameter("TemplateParam", "{\"" + templateParam + "\":\"" + randomCode + "\"}");
// 发送的业务逻辑
try {
// {"Message":"账户余额不足","RequestId":"415E9BF0-6904-5920-933A-F27B920E2644","Code":"isv.AMOUNT_NOT_ENOUGH"}
// {"Message":"触发分钟级流控Permits:1","RequestId":"9D7F3798-1CA1-5110-9056-1ECB14A91097","Code":"isv.BUSINESS_LIMIT_CONTROL"}
// {"Message":"OK","RequestId":"2E6BD8A4-D1A3-5A25-A237-2AB702893632","Code":"OK","BizId":"303700784907161870^0"}
CommonResponse response = instance.client.getCommonResponse(instance.request);
if(response.getHttpStatus() != 200 || !"OK".equals(JSONUtil.parseObj(response.getData()).get("Message"))) {
log.error("发送短信失败 {} {} {}", phoneNumber, response.getHttpStatus(), response.getData());
throw new BizException("发送短信失败");
}
log.info("发送短信成功 {} {}", phoneNumber, randomCode);
} catch (Exception e) {
log.error("发送短信出错 {}", phoneNumber, e);
throw new BizException("发送短信出错", e);
}
return randomCode;
}
public static boolean isPhoneNumber(String phoneNumber) {
Matcher m = PATTERN.matcher(phoneNumber);
return m.matches();
}
}
- 其中模板中的
${code}
即为随机生成的验证码,将此验证码发送到用户手机,并将此验证码和其过期时间一起保存到session中供业务验证