feat:阿里云短信模块开发

This commit is contained in:
xiang
2025-09-06 22:17:58 +08:00
parent 681eb30ef5
commit 97704a5a4a
8 changed files with 246 additions and 0 deletions

View File

@@ -44,6 +44,17 @@
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.11</version> <version>1.11</version>
</dependency> </dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibabacloud-dysmsapi20170525</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,47 @@
package com.xiang.xservice.basic.xservice.aliyun.common;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.teaopenapi.models.Config;
import com.xiang.xservice.basic.xservice.aliyun.config.AliyunProperties;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.Setter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@EnableConfigurationProperties({AliyunProperties.class})
public class ClientUtils {
@Setter
private static AliyunProperties aliyunProperties;
private static final String ENDPOINT = "dysmsapi.aliyuncs.com";
public static com.aliyun.dysmsapi20170525.Client initClients() throws Exception {
AliyunProperties properties = new AliyunProperties();
Config config = new Config()
// 配置 AccessKey ID请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(aliyunProperties.getAccessKeyId())
// 配置 AccessKey Secret请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(aliyunProperties.getAccessKeySecret());
config.endpoint = ENDPOINT;
return new com.aliyun.dysmsapi20170525.Client(config);
}
public static AsyncClient initAsyncClient() {
StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
.accessKeyId(System.getenv(aliyunProperties.getAccessKeyId()))
.accessKeySecret(System.getenv(aliyunProperties.getAccessKeySecret()))
.build());
return AsyncClient.builder()
.region("cn-hangzhou") // Region ID
.credentialsProvider(provider)
.overrideConfiguration(
ClientOverrideConfiguration.create()
.setEndpointOverride(ENDPOINT)
)
.build();
}
}

View File

@@ -0,0 +1,20 @@
package com.xiang.xservice.basic.xservice.aliyun.config;
import org.springframework.stereotype.Component;
import com.xiang.xservice.basic.xservice.aliyun.common.ClientUtils;
import javax.annotation.PostConstruct;
@Component
public class AliyunConfigHolder {
private final AliyunProperties aliyunProperties;
public AliyunConfigHolder(AliyunProperties aliyunProperties) {
this.aliyunProperties = aliyunProperties;
}
@PostConstruct
public void init() {
ClientUtils.setAliyunProperties(aliyunProperties);
}
}

View File

@@ -0,0 +1,16 @@
package com.xiang.xservice.basic.xservice.aliyun.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@Data
@AllArgsConstructor
@NoArgsConstructor
@RefreshScope
public class AliyunProperties {
private String accessKeyId;
private String accessKeySecret;
}

View File

@@ -0,0 +1,6 @@
package com.xiang.xservice.basic.xservice.aliyun.smscode;
public interface ISmsCodeService {
Boolean asyncSendPhoneValidCode4DaXiangNet(String phoneNumber, String smsCode);
}

View File

@@ -0,0 +1,22 @@
package com.xiang.xservice.basic.xservice.aliyun.smscode;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class SmsCodeServiceImpl implements ISmsCodeService {
@Override
public Boolean asyncSendPhoneValidCode4DaXiangNet(String phoneNumber, String smsCode) {
Map<String, String> param = Maps.newHashMap();
param.put("code", smsCode);
try {
SmsCodeUtils.asyncSmsCode(phoneNumber, "大象网", "SMS_259435198", param, null);
return Boolean.TRUE;
} catch (Exception e) {
return Boolean.FALSE;
}
}
}

View File

@@ -0,0 +1,122 @@
package com.xiang.xservice.basic.xservice.aliyun.smscode;
import com.alibaba.fastjson.JSON;
import com.xiang.xservice.basic.exception.BusinessException;
import com.xiang.xservice.basic.xservice.aliyun.common.ClientUtils;
import lombok.extern.slf4j.Slf4j;
import com.aliyun.sdk.service.dysmsapi20170525.*;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.Map;
@Slf4j
public class SmsCodeUtils {
/**
* 向多个个手机号发送短信
* @param phoneNumber 手机号
* @param signName 签名
* @param templateCode 模板编号
* @param templateParam 模板参数
*/
public static void getBasicSmsCode(String phoneNumber, String signName, String templateCode,
Map<String, String> templateParam) {
getBasicSmsCode(Collections.singletonList(phoneNumber), signName, templateCode, templateParam);
}
/**
* 向单个个手机号发送短信
* @param phoneNumber 手机号
* @param signName 签名
* @param templateCode 模板编号
* @param templateParam 模板参数
*/
public static void getBasicSmsCode(List<String> phoneNumber, String signName, String templateCode,
Map<String, String> templateParam) {
com.aliyun.dysmsapi20170525.Client client;
// 初始化请求客户端
try {
client = ClientUtils.initClients();
} catch (Exception e) {
log.error("初始化Aliyun客户端失败", e);
throw new BusinessException("初始化Aliyun客户端失败");
}
// 构造API请求对象请替换请求参数值
com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
.setPhoneNumbers(getPhoneNumbers(phoneNumber))
.setSignName(signName)
.setTemplateCode(templateCode)
.setTemplateParam(JSON.toJSONString(templateParam));
// 获取响应对象
try {
com.aliyun.dysmsapi20170525.models.SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
log.info("发送短信验证码,请求:{}, 响应:{}", JSON.toJSONString(sendSmsResponse), JSON.toJSONString(sendSmsResponse));
} catch (Exception e) {
log.error("发送短信验证码失败,发送请求:{}", JSON.toJSONString(sendSmsRequest), e);
throw new BusinessException("发送短信验证码失败");
}
}
/**
* 单个手机号异步发送短信
* @param phoneNumber 手机号
* @param signName 签名
* @param templateCode 模板编号
* @param templateParam 模板参数
* @param externParam 外部流水扩展字段
*/
public static void asyncSmsCode(String phoneNumber, String signName, String templateCode,
Map<String, String> templateParam, String externParam) {
asyncSmsCode(Collections.singletonList(phoneNumber), signName, templateCode, templateParam, externParam);
}
/**
* 多个手机号异步发送短信
* @param phoneNumber 手机号集合(多个手机号)
* @param signName 签名
* @param templateCode 模板编号
* @param templateParam 模板参数
* @param externParam 外部流水扩展字段
*/
public static void asyncSmsCode(List<String> phoneNumber, String signName, String templateCode,
Map<String, String> templateParam, String externParam) {
AsyncClient client = ClientUtils.initAsyncClient();
com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest sendSmsRequest =
com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest.builder()
.templateCode(templateCode)
.phoneNumbers(getPhoneNumbers(phoneNumber))
.signName(signName)
.outId(externParam)
.templateParam(JSON.toJSONString(templateParam))
.build();
log.info("异步发送短信,请求:{}", JSON.toJSONString(sendSmsRequest));
try {
CompletableFuture<com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse> future = client.sendSms(sendSmsRequest);
com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse response = future.get();
log.info("异步发送短信, 响应:{}", JSON.toJSONString(response));
} catch (Exception e) {
log.error("异步发送短信失败", e);
throw new BusinessException("异步发送短信失败");
} finally {
client.close();
}
}
private static String getPhoneNumbers(List<String> phoneNumberList) {
StringBuilder phoneNumbers = new StringBuilder();
for (String phone : phoneNumberList) {
phoneNumbers.append(phone).append(",");
}
phoneNumbers.deleteCharAt(phoneNumbers.length() - 1);
return phoneNumbers.toString();
}
}

View File

@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xiang.xservice.basic.xservice.aliyun.config.AliyunProperties