# 09-整合阿里云短信服务
在实际项目中经常有发送短信的功能,今天进说一下对接阿里云短信服务实现短信发送、查询功能。
# 1、准备工作
阿里云链接:https://www.aliyun.com/ 点击控制台-产品与服务-云通信-短信服务 需要创建AccessKey(云账号AccessKey是您访问阿里云API的密钥)如果有则不用创建 如下图所示:
然后需要创建短信签名与短信模板,可以根据阿里云短信服务介绍自己创建,这里不再描述。创建成功需要工作人员进行审核,时间大约在两个小时,请耐心等待
# 2、项目集成
# 2.1 添加依赖
创建SpringBoot项目,在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--阿里云的短信服务SDK start-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
<!--阿里云的短信服务SDK end-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2.2 配置文件
需要在application.properties配置文件中添加阿里云短信服务的参数信息
#--------阿里云短信配置参数 start--------------#
#阿里云 accessKeyId(安全信息管理下面)
aliyun.sms.accessKeyId=*******
#阿里云 accessKeySecret(安全信息管理下面)
aliyun.sms.accessKeySecret=********
#产品名称:云通信短信API产品,开发者无需替换
aliyun.sms.product=Dysmsapi
#产品域名,开发者无需替换
aliyun.sms.domain=dysmsapi.aliyuncs.com
aliyun.sms.regionId=cn-hangzhou
#短信签名名称(国内/国际/港澳台消息-签名管理下面)
aliyun.sms.signName=****
#发送日期 支持30天内记录查询,格式yyyyMMdd
aliyun.sms.dateFormat=yyyyMMdd
#服务结点
aliyun.sms.endpointName=cn-hangzhou
#--------阿里云短信配置参数 end--------------#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
创建阿里云短信服务配置类AliyunSMSConfig,代码如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Description: 阿里短信服务配置类
* @Author: Ryu
* @Date: 2019/4/18 15:26
* @Version: V1.0
*/
@Component
@Data
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "aliyun.sms")
public class AliyunSMSConfig {
/**
* 阿里云 accessKeyId(安全信息管理下面)
*/
private String accessKeyId;
/**
* 阿里云 accessKeySecret(安全信息管理下面)
*/
private String accessKeySecret;
/**
* 产品名称:云通信短信API产品,开发者无需替换
*/
private String product;
/**
* 产品域名,开发者无需替换
*/
private String domain;
private String regionId;
/**
* 短信签名名称(国内/国际/港澳台消息-签名管理下面)
*/
private String signName;
/**
* 发送日期 支持30天内记录查询,格式yyyyMMdd
*/
private String dateFormat;
/**
* 服务结点
*/
private String endpointName;
}
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
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
# 2.3 业务逻辑实现
创建发送短信实体Sms
import lombok.Data;
import lombok.ToString;
/**
* @Author: Ryu
* @Description: 发送短信实体
* @Date: 15:42 2019/4/18
* @Version: V1.0
*/
@Data
@ToString
public class Sms {
/**
* 手机号
*/
private String phoneNumbers;
private String outId;
/**
* 模板参数 格式:"{\"code\":\"123456\"}"
*/
private String templateParam;
/**
* 阿里云模板管理code
*/
private String templateCode;
}
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
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
创建短信查询实体SmsQuery
import lombok.Data;
import lombok.ToString;
import java.util.Date;
/**
* @Author: LX 17839193044@162.com
* @Description: 短信查询实体
* @Date: 15:51 2019/4/18
* @Version: V1.0
*/
@Data
@ToString
public class SmsQuery {
private String bizId;
private String phoneNumber;
private Date sendDate;
private Long pageSize;
private Long currentPage;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
发送短信service接口代码AliyunSmsSenderService如下:
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
/**
* @Author: LX 17839193044@162.com
* @Description: 阿里云短信发送service
* @Date: 17:31 2019/4/18
* @Version: V1.0
*/
public interface AliyunSmsSenderService {
/**
* @param phoneNumbers: 手机号
* @param templateParamJson: 模板参数json {"sellerName":"123456","orderSn":"123456"}
* @param templateCode: 阿里云短信模板code
* @Author: LX 17839193044@162.com
* @Description: 对接阿里云短信服务实现短信发送
* 发送验证码类的短信时,每个号码每分钟最多发送一次,每个小时最多发送5次。其它类短信频控请参考阿里云
* @Date: 2019/4/18 16:35
* @Version: V1.0
*/
SendSmsResponse sendSms(String phoneNumbers, String templateParamJson, String templateCode);
/**
* @param bizId: 短信对象的对应的bizId
* @param phoneNumber: 手机号
* @param pageSize: 分页大小
* @param currentPage: 当前页码
* @Author: LX 17839193044@162.com
* @Description: 查询发送短信的内容
* @Date: 2019/4/18 16:52
* @Version: V1.0
*/
QuerySendDetailsResponse querySendDetails(String bizId, String phoneNumber, Long pageSize, Long currentPage);
}
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
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
发送短信service实现类代码AliyunSmsSenderServiceImpl如下:
import cn.thislx.aliyunsms.config.AliyunSMSConfig;
import cn.thislx.aliyunsms.entry.Sms;
import cn.thislx.aliyunsms.entry.SmsQuery;
import cn.thislx.aliyunsms.service.AliyunSmsSenderService;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: LX 17839193044@162.com
* @Description: 发送短信封装服务实现类
* @Date: 2019/4/18 15:36
* @Version: V1.0
*/
@Slf4j
@Service
public class AliyunSmsSenderServiceImpl implements AliyunSmsSenderService {
@Resource
private AliyunSMSConfig smsConfig;
/**
* @param phoneNumbers: 手机号
* @param templateParamJson: 模板参数json {"sellerName":"123456","orderSn":"123456"}
* @param templateCode: 阿里云短信模板code
* @Author: LX 17839193044@162.com
* @Description: 对接阿里云短信服务实现短信发送
* 发送验证码类的短信时,每个号码每分钟最多发送一次,每个小时最多发送5次。其它类短信频控请参考阿里云
* @Date: 2019/4/18 16:35
* @Version: V1.0
*/
@Override
public SendSmsResponse sendSms(String phoneNumbers, String templateParamJson, String templateCode) {
// 封装短信发送对象
Sms sms = new Sms();
sms.setPhoneNumbers(phoneNumbers);
sms.setTemplateParam(templateParamJson);
sms.setTemplateCode(templateCode);
// 获取短信发送服务机
IAcsClient acsClient = getClient();
//获取短信请求
SendSmsRequest request = getSmsRequest(sms);
SendSmsResponse sendSmsResponse = new SendSmsResponse();
try {
sendSmsResponse = acsClient.getAcsResponse(request);
} catch (ClientException e) {
log.error("发送短信发生错误。错误代码是 [{}],错误消息是 [{}],错误请求ID是 [{}],错误Msg是 [{}],错误类型是 [{}]",
e.getErrCode(),
e.getMessage(),
e.getRequestId(),
e.getErrMsg(),
e.getErrorType());
}
return sendSmsResponse;
}
/**
* @param bizId: 短信对象的对应的bizId
* @param phoneNumber: 手机号
* @param pageSize: 分页大小
* @param currentPage: 当前页码
* @Author: LX 17839193044@162.com
* @Description: 查询发送短信的内容
* @Date: 2019/4/18 16:52
* @Version: V1.0
*/
@Override
public QuerySendDetailsResponse querySendDetails(String bizId, String phoneNumber, Long pageSize, Long currentPage) {
// 查询实体封装
SmsQuery smsQuery = new SmsQuery();
smsQuery.setBizId(bizId);
smsQuery.setPhoneNumber(phoneNumber);
smsQuery.setCurrentPage(currentPage);
smsQuery.setPageSize(pageSize);
smsQuery.setSendDate(new Date());
// 获取短信发送服务机
IAcsClient acsClient = getClient();
QuerySendDetailsRequest request = getSmsQueryRequest(smsQuery);
QuerySendDetailsResponse querySendDetailsResponse = null;
try {
querySendDetailsResponse = acsClient.getAcsResponse(request);
} catch (ClientException e) {
log.error("查询发送短信发生错误。错误代码是 [{}],错误消息是 [{}],错误请求ID是 [{}],错误Msg是 [{}],错误类型是 [{}]",
e.getErrCode(),
e.getMessage(),
e.getRequestId(),
e.getErrMsg(),
e.getErrorType());
}
return querySendDetailsResponse;
}
/**
* @param smsQuery:
* @Author: LX 17839193044@162.com
* @Description: 封装查询阿里云短信请求对象
* @Date: 2019/4/18 16:51
* @Version: V1.0
*/
private QuerySendDetailsRequest getSmsQueryRequest(SmsQuery smsQuery) {
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
request.setPhoneNumber(smsQuery.getPhoneNumber());
request.setBizId(smsQuery.getBizId());
SimpleDateFormat ft = new SimpleDateFormat(smsConfig.getDateFormat());
request.setSendDate(ft.format(smsQuery.getSendDate()));
request.setPageSize(smsQuery.getPageSize());
request.setCurrentPage(smsQuery.getCurrentPage());
return request;
}
/**
* @param sms: 短信发送实体
* @Author: LX 17839193044@162.com
* @Description: 获取短信请求
* @Date: 2019/4/18 16:40
* @Version: V1.0
*/
private SendSmsRequest getSmsRequest(Sms sms) {
SendSmsRequest request = new SendSmsRequest();
request.setPhoneNumbers(sms.getPhoneNumbers());
request.setSignName(smsConfig.getSignName());
request.setTemplateCode(sms.getTemplateCode());
request.setTemplateParam(sms.getTemplateParam());
request.setOutId(sms.getOutId());
return request;
}
/**
* @Author: LX 17839193044@162.com
* @Description: 获取短信发送服务机
* @Date: 2019/4/18 16:38
* @Version: V1.0
*/
private IAcsClient getClient() {
IClientProfile profile = DefaultProfile.getProfile(smsConfig.getRegionId(),
smsConfig.getAccessKeyId(),
smsConfig.getAccessKeySecret());
try {
DefaultProfile.addEndpoint(smsConfig.getEndpointName(),
smsConfig.getRegionId(),
smsConfig.getProduct(),
smsConfig.getDomain());
} catch (ClientException e) {
log.error("获取短信发送服务机发生错误。错误代码是 [{}],错误消息是 [{}],错误请求ID是 [{}],错误Msg是 [{}],错误类型是 [{}]",
e.getErrCode(),
e.getMessage(),
e.getRequestId(),
e.getErrMsg(),
e.getErrorType());
}
return new DefaultAcsClient(profile);
}
}
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
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
测试controller代码如下:
import cn.thislx.aliyunsms.service.impl.AliyunSmsSenderServiceImpl;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: LX 17839193044@162.com
* @Description: 测试发送短信controller
* @Date: 14:00 2019/4/18
* @Version: V1.0
*/
@RestController
public class TestController {
@Autowired
private AliyunSmsSenderServiceImpl aliyunSmsSenderServiceImpl;
/**
* @Author: LX 17839193044@162.com
* @Description: 短信发送
* @Date: 2019/4/18 16:08
* @Version: V1.0
*/
@GetMapping("/sms")
@ResponseBody
public String sms() {
Map<String, String> map = new HashMap<>();
map.put("sellerName", "平台自营");
map.put("orderSn", "P2019041895451");
SendSmsResponse sendSmsResponse = aliyunSmsSenderServiceImpl.sendSms("此处填写手机号",
JSON.toJSONString(map),
"此处填写短信模板code");
return JSON.toJSONString(sendSmsResponse);
}
/**
* @Author: LX 17839193044@162.com
* @Description: 短信查询
* @Date: 2019/4/18 16:08
* @Version: V1.0
*/
@GetMapping("/query")
@ResponseBody
public String query() {
QuerySendDetailsResponse querySendDetailsResponse = aliyunSmsSenderServiceImpl.querySendDetails("此处填写发送短信返回的bizId",
"此处填写手机号", 10L, 1L);
return JSON.toJSONString(querySendDetailsResponse);
}
}
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
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
启动项目访问 http://ip:端口/sms 即刻进行短信发送测试。
上述是使用配置文件配置的服务类,还可以封装为工具类,(推荐使用上面的方法)代码如下:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: LX 17839193044@162.com
* @Description: 短信发送工具类
* @Date: 2019/4/18 17:35
* @Version: V1.0
*/
public class SmsUtils {
//产品名称:云通信短信API产品,开发者无需替换
static final String product = "Dysmsapi";
//产品域名,开发者无需替换
static final String domain = "dysmsapi.aliyuncs.com";
static final String accessKeyId = "*****";
static final String accessKeySecret = "*****";
public static SendSmsResponse sendSms() throws ClientException {
//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers("*****");
//必填:短信签名-可在短信控制台中找到
request.setSignName("******");
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode("*****");
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"
request.setTemplateParam("{\"code\":\"123456\"}");
//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997");
//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
// request.setOutId("yourOutId");
//hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
return sendSmsResponse;
}
/**
* @param bizId: 短信对应的bizId
* @Author: LX 17839193044@162.com
* @Description: 查询短信详情
* @Date: 2019/4/18 17:35
* @Version: V1.0
*/
public static QuerySendDetailsResponse querySendDetails(String bizId) throws ClientException {
//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//组装请求对象
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
//必填-号码
request.setPhoneNumber("15197447018");
//可选-流水号
request.setBizId(bizId);
//必填-发送日期 支持30天内记录查询,格式yyyyMMdd
SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
request.setSendDate(ft.format(new Date()));
//必填-页大小
request.setPageSize(10L);
//必填-当前页码从1开始计数
request.setCurrentPage(1L);
//hint 此处可能会抛出异常,注意catch
QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);
return querySendDetailsResponse;
}
public static void main(String[] args) throws ClientException, InterruptedException {
//发短信
SendSmsResponse response = sendSms();
System.out.println("短信接口返回的数据----------------");
System.out.println("Code=" + response.getCode());
System.out.println("Message=" + response.getMessage());
System.out.println("RequestId=" + response.getRequestId());
System.out.println("BizId=" + response.getBizId());
// 对接上面的,如果这里不等待,直接查询,会查到一个空的结果
Thread.sleep(3000L);
//查明细
if (response.getCode() != null && response.getCode().equals("OK")) {
QuerySendDetailsResponse querySendDetailsResponse = querySendDetails(response.getBizId());
System.out.println("短信明细查询接口返回数据----------------");
System.out.println("Code=" + querySendDetailsResponse.getCode());
System.out.println("Message=" + querySendDetailsResponse.getMessage());
int i = 0;
for (QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : querySendDetailsResponse.getSmsSendDetailDTOs()) {
System.out.println("SmsSendDetailDTO[" + i + "]:");
System.out.println("Content=" + smsSendDetailDTO.getContent());
System.out.println("ErrCode=" + smsSendDetailDTO.getErrCode());
System.out.println("OutId=" + smsSendDetailDTO.getOutId());
System.out.println("PhoneNum=" + smsSendDetailDTO.getPhoneNum());
System.out.println("ReceiveDate=" + smsSendDetailDTO.getReceiveDate());
System.out.println("SendDate=" + smsSendDetailDTO.getSendDate());
System.out.println("SendStatus=" + smsSendDetailDTO.getSendStatus());
System.out.println("Template=" + smsSendDetailDTO.getTemplateCode());
}
System.out.println("TotalCount=" + querySendDetailsResponse.getTotalCount());
System.out.println("RequestId=" + querySendDetailsResponse.getRequestId());
}
}
}
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
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
到此项目已经完成集成阿里云短信服务。