前言
基于阿里云短信服务,支持单发、群发功能
注意:我申请的验证码签名
,业务逻辑部分需要根据自己的需求再进行修改,
平台准备
这个准备工作需要在阿里云平台-短信服务操作,必须得有实名等资质
,然后才能继续申请签名
、申请模板
。这个相对繁琐一点,直接去看文档流程。
【准备工作,官方文档】
公共代码
引入Maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.11</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>alibabacloud-dysmsapi20170525</artifactId> <version>2.0.24</version> </dependency>
|
工具类
model类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import lombok.Data;
@Data public class SmsModel {
private String name;
private String phone;
private String content;
private String verifyCode;
private String signName;
public SmsModel() {} public SmsModel(String phone) {this.phone = phone;} public SmsModel(String phone, String smsCode) { this.phone = phone; this.content = content; } public SmsModel(String phone, String smsCode, String name) { this.phone = phone; this.content = content; this.name = name; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import lombok.Data;
@Data public class SmsSendModel {
private String phone;
private String templateParam;
private String signName;
public SmsSendModel() {} public SmsSendModel(String phone) { this.phone = phone; } public SmsSendModel(String phone, String templateParam) { this.phone = phone; this.templateParam = templateParam; } }
|
Util工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
| import com.example.demo.entity.Sms; import com.example.demo.model.SmsModel; import com.example.demo.model.SmsSendModel;
import com.alibaba.fastjson.JSONArray; import com.google.gson.Gson; import com.aliyun.auth.credentials.Credential; import com.aliyun.auth.credentials.provider.StaticCredentialProvider; import com.aliyun.core.http.HttpClient; import com.aliyun.core.http.ProxyOptions; import com.aliyun.httpcomponent.httpclient.ApacheAsyncHttpClientBuilder; import com.aliyun.sdk.service.dysmsapi20170525.models.*; import com.aliyun.sdk.service.dysmsapi20170525.*; import darabonba.core.client.ClientOverrideConfiguration; import javax.net.ssl.KeyManager; import javax.net.ssl.X509TrustManager; import java.net.InetSocketAddress; import java.time.Duration; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture;
public class AliCloudSms { private static final String ACCESS_KEY_ID = "xxxxxx"; private static final String ACCESS_KEY_SECRET = "xxxxx"; private static final String SECURITY_TOKEN = ""; private static final String REGION_ID = "cn-hangzhou"; private static final String PRODUCT = "Dysmsapi"; private static final String DOMAIN = "dysmsapi.aliyuncs.com"; private static final String SING_NAME = "内涵猫"; private static final String TEMPLATE_CODE = "SMS_2000****"; private static final String PROXY_HOSTNAME = "代理地址"; private static final Integer PROXY_PORT = 9001; private static final String PROXY_USERNAME = "代理用户名"; private static final String PROXY_PASSWORD = "代理密码";
private static final Boolean isHttpClient = false;
public static void sendSmsOne(SmsSendModel sms){ HttpClient httpClient = null; if (isHttpClient == true){ httpClient = new ApacheAsyncHttpClientBuilder() .connectionTimeout(Duration.ofSeconds(10)) .responseTimeout(Duration.ofSeconds(10)) .maxConnections(128) .maxIdleTimeOut(Duration.ofSeconds(50)) .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT)).setCredentials(PROXY_USERNAME, PROXY_PASSWORD)) .x509TrustManagers(new X509TrustManager[]{}) .keyManagers(new KeyManager[]{}) .ignoreSSL(false) .build(); } StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder() .accessKeyId(ACCESS_KEY_ID).accessKeySecret(ACCESS_KEY_SECRET) .build()); AsyncClient client = AsyncClient.builder() .credentialsProvider(provider) .overrideConfiguration( ClientOverrideConfiguration.create() .setEndpointOverride(DOMAIN) .setConnectTimeout(Duration.ofSeconds(30)) ) .build(); SendSmsRequest sendSmsRequest = SendSmsRequest.builder() .phoneNumbers(sms.getPhone()) .signName(sms.getSignName()) .templateCode(TEMPLATE_CODE) .templateParam(sms.getTemplateParam())
.build(); CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest); try{ SendSmsResponse resp = response.get(); System.out.println(new Gson().toJson(resp)); response.thenAccept(res -> { System.out.println(new Gson().toJson(res)); }).exceptionally(throwable -> { System.out.println(throwable.getMessage()); return null; }); client.close(); }catch (Exception e){ e.printStackTrace(); } }
public static void sendSmsBatch(SmsSendModel params){ HttpClient httpClient = null; if (isHttpClient == true){ httpClient = new ApacheAsyncHttpClientBuilder() .connectionTimeout(Duration.ofSeconds(10)) .responseTimeout(Duration.ofSeconds(10)) .maxConnections(128) .maxIdleTimeOut(Duration.ofSeconds(50)) .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT)).setCredentials(PROXY_USERNAME, PROXY_PASSWORD)) .x509TrustManagers(new X509TrustManager[]{}) .keyManagers(new KeyManager[]{}) .ignoreSSL(false) .build(); } StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder() .accessKeyId(ACCESS_KEY_ID) .accessKeySecret(ACCESS_KEY_SECRET) .build()); AsyncClient client = AsyncClient.builder() .region(REGION_ID) .credentialsProvider(provider) .overrideConfiguration( ClientOverrideConfiguration.create() .setEndpointOverride(DOMAIN) .setConnectTimeout(Duration.ofSeconds(30)) ) .build(); SendBatchSmsRequest sendBatchSmsRequest = SendBatchSmsRequest.builder() .templateCode(TEMPLATE_CODE) .signNameJson(params.getSignName()) .phoneNumberJson(params.getPhone()) .templateParamJson(params.getTemplateParam()) .build(); CompletableFuture<SendBatchSmsResponse> response = client.sendBatchSms(sendBatchSmsRequest); try{ SendBatchSmsResponse resp = response.get(); response.thenAccept(res -> { System.out.println(new Gson().toJson(res)); }).exceptionally(throwable -> { System.out.println(throwable.getMessage()); return null; }); client.close(); }catch (Exception e){ e.printStackTrace(); } }
public static SmsSendModel batchParam(SmsModel params) { Map<String,Object> tpm = new HashMap<>(); if (params.getVerifyCode() != null && params.getContent() == null){ tpm.put("code", params.getVerifyCode()); }else { tpm.put("content", params.getContent()); } SmsSendModel result = new SmsSendModel(); result.setPhone(params.getPhone()); result.setTemplateParam(JSONArray.toJSONString(tpm)); result.setSignName(params.getSignName()); return result; }
public static SmsSendModel batchParams(List<SmsModel> list) { List<String> phoneList = new LinkedList<>(); List<String> signList = new LinkedList<>(); List<Map<String,Object>> paramsList = new LinkedList<>(); for (int i = 0; i < list.size(); i++) { phoneList.add(list.get(i).getPhone()); signList.add(SING_NAME); Map<String,Object> pm = new HashMap<>(); if (list.get(i).getVerifyCode() != null && list.get(i).getContent() == null){ pm.put("code", list.get(i).getVerifyCode()); }else { pm.put("content", list.get(i).getContent()); } paramsList.add(pm); } SmsSendModel result = new SmsSendModel(); result.setPhone(JSONArray.toJSONString(phoneList)); result.setTemplateParam(JSONArray.toJSONString(paramsList)); result.setSignName(JSONArray.toJSONString(signList)); return result; }
public static void main(String[] args) { SmsSendModel sms = new SmsSendModel("15762178818"); sendSmsOne(sms); }
}
|
请求层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import com.example.demo.common.Result; import com.example.demo.entity.Sms; import com.example.demo.model.SmsModel; import com.example.demo.model.SmsSendModel; import com.example.demo.utils.aliyun.AliCloudSms; import org.springframework.web.bind.annotation.*; import java.util.LinkedList; import java.util.List;
@RestController @RequestMapping("/sms/ali") public class SmsAliController {
@GetMapping("/sendSms") public Result sendSms() { String phone = "150*******"; SmsModel sm = new SmsModel(); sm.setPhone(phone); sm.setVerifyCode(String.valueOf((int)(Math.random() * 900000 + 100000))); sm.setSignName("内涵猫"); SmsSendModel m = AliCloudSms.batchParam(sm); AliCloudSms.sendSmsOne(m); return Result.success(m); }
@PostMapping("/batchSendSms") public Result batchSendSms() { List<SmsModel> list = new LinkedList<>(); SmsModel ssm1 = new SmsModel(); ssm1.setSignName("内涵猫"); ssm1.setPhone("150*******"); ssm1.setName("张三"); ssm1.setVerifyCode(String.valueOf((int)(Math.random() * 900000 + 100000))); list.add(ssm1);
SmsModel ssm2 = new SmsModel(); ssm2.setSignName("内涵猫"); ssm2.setPhone("133*******"); ssm2.setName("张三"); ssm2.setVerifyCode(String.valueOf((int)(Math.random() * 900000 + 100000))); list.add(ssm2); SmsModel ssm3 = new SmsModel(); ssm3.setSignName("内涵猫"); ssm3.setPhone("155*******"); ssm3.setName("王五"); ssm3.setVerifyCode(String.valueOf((int)(Math.random() * 900000 + 100000))); list.add(ssm3);
SmsSendModel m = AliCloudSms.batchParams(list); AliCloudSms.sendSmsBatch(m); return Result.success(); } }
|
单条发送信息(SendSms)
PhoneNumbers
- 国内短信,手机号码格式:+/+86/0086/86或无任何前缀的11位手机号码,例如:1390000**
- 国际/港澳台消息,手机号码格式:国际区号+号码,例如:852000012**
- 支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。上限为1000个手机号码。
- 批量调用相对于单条调用及时性稍有延迟。
- 验证码类型短信,建议使用单独发送的方式。
SignName
- 您可以登录短信服务控制台,选择国内消息或国际/港澳台消息,在签名管理页面获取。
- 必须是已添加、并通过审核的短信签名。更多短信签名规范,请参见短信签名规范。
TemplateCode
TemplateParam
- 支持传入多个参数
- 如果JSON中需要带换行符,请参照标准的JSON协议处理。模板变量规范,请参见短信模板规范。
SmsUpExtendCode
- 上行短信指发送给通信服务提供商的短信,用于定制某种服务、完成查询,或是办理某种业务等,需要收费,按运营商普通短信资费进行扣费。
- 扩展码是生成签名时系统自动默认生成的,不支持自行传入。
- 无特殊需要可忽略此字段。
OutId
字段名称 |
类型 |
字段详情 |
示例值 |
PhoneNumbers |
string |
接收短信的手机号码。 |
1390000**** |
SignName |
string |
短信签名名称 |
阿里云 |
TemplateCode |
string |
短信模板CODE |
SMS_15255**** |
- |
TemplateParam |
string |
短信模板变量对应的实际值 |
{"name":"张三","number":"1390000****"} |
SmsUpExtendCode |
string |
上行短信扩展码,JSON数组格式 |
90999 |
OutId |
string |
外部流水扩展字段 |
abcdefg |
字段名称 |
类型 |
字段详情 |
示例值 |
补充 |
Code |
string |
请求状态码 |
OK |
其他错误码,请参见错误码列表 |
Message |
string |
是否调用接口成功的描述 |
OK |
- |
BizId |
string |
发送回执ID |
9006197469364984400 |
- |
RequestId |
string |
请求ID |
F655A8D5-B967-440B-8683-DAD6FF8D230E |
- |
批量发送信息(SendBatchSms)
PhoneNumberJson
- 国内短信,手机号码格式:+/+86/0086/86或无任何前缀的11位手机号码,例如:1390000**
- 国际/港澳台消息,手机号码格式:国际区号+号码,例如:852000012**
- 支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。上限为1000个手机号码。
- 批量调用相对于单条调用及时性稍有延迟。
- 验证码类型短信,建议使用单独发送的方式。
SignNameJson
- 您可以登录短信服务控制台,选择国内消息或国际/港澳台消息,在签名管理页面获取。
- 必须是已添加、并通过审核的短信签名;且短信签名的个数必须与手机号码的个数相同、内容一一对应。
TemplateCode
TemplateParamJson
- 支持传入多个参数
- 如果JSON中需要带换行符,请参照标准的JSON协议处理。模板变量规范,请参见短信模板规范。
SmsUpExtendCodeJson
- JSON数组格式。
- 上行短信指发送给通信服务提供商的短信,用于定制某种服务、完成查询,或是办理某种业务等,需要收费,按运营商普通短信资费进行扣费。
- 扩展码是生成签名时系统自动默认生成的,不支持自行传入。
- 无特殊需要可忽略此字段。
OutId
- 长度小于256的字符串。
- 无特殊需要可忽略此字段。
字段名称 |
类型 |
字段详情 |
示例值 |
正则 |
PhoneNumberJson |
string |
接收短信的手机号码。 |
["1590000****","1350000****"] |
^\[\".*?\"(?:\,\".*?\")*\]$ |
SignNameJson |
string |
短信签名名称 |
["阿里云","阿里巴巴"] |
^\[\".*?\"(?:\,\".*?\")*\]$ |
TemplateCode |
string |
短信模板CODE |
SMS_15255**** |
- |
TemplateParamJson |
string |
短信模板变量对应的实际值 |
[{"name":"TemplateParamJson"},{"name":"TemplateParamJson"}] |
- |
SmsUpExtendCodeJson |
string |
上行短信扩展码,JSON数组格式 |
["90999","90998"] |
- |
OutId |
string |
外部流水扩展字段,长度小于256的字符串 |
abcdefg |
- |
字段名称 |
类型 |
字段详情 |
示例值 |
补充 |
Code |
string |
请求状态码 |
OK |
其他错误码,请参见错误码列表 |
Message |
string |
是否调用接口成功的描述 |
OK |
- |
BizId |
string |
发送回执ID |
9006197469364984400 |
- |
RequestId |
string |
请求ID |
F655A8D5-B967-440B-8683-DAD6FF8D230E |
- |