提交 | 用户 | 时间
|
97edd7
|
1 |
package com.iailab.module.shasteel.framework.sms.core.client.impl; |
H |
2 |
|
|
3 |
import cn.hutool.core.lang.Assert; |
|
4 |
import com.aliyuncs.DefaultAcsClient; |
|
5 |
import com.aliyuncs.IAcsClient; |
|
6 |
import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; |
|
7 |
import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; |
|
8 |
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; |
|
9 |
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; |
|
10 |
import com.aliyuncs.profile.DefaultProfile; |
|
11 |
import com.aliyuncs.profile.IClientProfile; |
|
12 |
import com.fasterxml.jackson.annotation.JsonFormat; |
|
13 |
import com.fasterxml.jackson.annotation.JsonProperty; |
|
14 |
import com.google.common.annotations.VisibleForTesting; |
|
15 |
import com.iailab.framework.common.core.KeyValue; |
|
16 |
import com.iailab.framework.common.util.collection.MapUtils; |
|
17 |
import com.iailab.framework.common.util.json.JsonUtils; |
|
18 |
import com.iailab.module.shasteel.framework.sms.core.client.dto.SmsReceiveRespDTO; |
|
19 |
import com.iailab.module.shasteel.framework.sms.core.client.dto.SmsSendRespDTO; |
|
20 |
import com.iailab.module.shasteel.framework.sms.core.client.dto.SmsTemplateRespDTO; |
|
21 |
import com.iailab.module.shasteel.framework.sms.core.enums.SmsTemplateAuditStatusEnum; |
|
22 |
import com.iailab.module.shasteel.framework.sms.core.property.SmsChannelProperties; |
|
23 |
import lombok.Data; |
|
24 |
import lombok.extern.slf4j.Slf4j; |
|
25 |
|
|
26 |
import java.time.LocalDateTime; |
|
27 |
import java.util.List; |
|
28 |
import java.util.Objects; |
|
29 |
|
|
30 |
import static com.iailab.framework.common.util.collection.CollectionUtils.convertList; |
|
31 |
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
|
32 |
import static com.iailab.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; |
|
33 |
|
|
34 |
/** |
|
35 |
* 阿里短信客户端的实现类 |
|
36 |
* |
|
37 |
* @author zzf |
|
38 |
* @since 2021/1/25 14:17 |
|
39 |
*/ |
|
40 |
@Slf4j |
|
41 |
public class AliyunSmsClient extends AbstractSmsClient { |
|
42 |
|
|
43 |
/** |
|
44 |
* 调用成功 code |
|
45 |
*/ |
|
46 |
public static final String API_CODE_SUCCESS = "OK"; |
|
47 |
|
|
48 |
/** |
|
49 |
* REGION, 使用杭州 |
|
50 |
*/ |
|
51 |
private static final String ENDPOINT = "cn-hangzhou"; |
|
52 |
|
|
53 |
/** |
|
54 |
* 阿里云客户端 |
|
55 |
*/ |
|
56 |
private volatile IAcsClient client; |
|
57 |
|
|
58 |
public AliyunSmsClient(SmsChannelProperties properties) { |
|
59 |
super(properties); |
|
60 |
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); |
|
61 |
Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); |
|
62 |
} |
|
63 |
|
|
64 |
@Override |
|
65 |
protected void doInit() { |
|
66 |
IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); |
|
67 |
client = new DefaultAcsClient(profile); |
|
68 |
} |
|
69 |
|
|
70 |
@Override |
|
71 |
public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, |
|
72 |
List<KeyValue<String, Object>> templateParams) throws Throwable { |
|
73 |
// 构建请求 |
|
74 |
SendSmsRequest request = new SendSmsRequest(); |
|
75 |
request.setPhoneNumbers(mobile); |
|
76 |
request.setSignName(properties.getSignature()); |
|
77 |
request.setTemplateCode(apiTemplateId); |
|
78 |
request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); |
|
79 |
request.setOutId(String.valueOf(sendLogId)); |
|
80 |
// 执行请求 |
|
81 |
SendSmsResponse response = client.getAcsResponse(request); |
|
82 |
return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId()) |
|
83 |
.setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()); |
|
84 |
} |
|
85 |
|
|
86 |
@Override |
|
87 |
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { |
|
88 |
List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); |
|
89 |
return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess()) |
|
90 |
.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()) |
|
91 |
.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()) |
|
92 |
.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()))); |
|
93 |
} |
|
94 |
|
|
95 |
@Override |
|
96 |
public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { |
|
97 |
// 构建请求 |
|
98 |
QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); |
|
99 |
request.setTemplateCode(apiTemplateId); |
|
100 |
// 执行请求 |
|
101 |
QuerySmsTemplateResponse response = client.getAcsResponse(request); |
|
102 |
if (response.getTemplateStatus() == null) { |
|
103 |
return null; |
|
104 |
} |
|
105 |
return new SmsTemplateRespDTO().setId(response.getTemplateCode()).setContent(response.getTemplateContent()) |
|
106 |
.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); |
|
107 |
} |
|
108 |
|
|
109 |
@VisibleForTesting |
|
110 |
Integer convertSmsTemplateAuditStatus(Integer templateStatus) { |
|
111 |
switch (templateStatus) { |
|
112 |
case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); |
|
113 |
case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); |
|
114 |
case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); |
|
115 |
default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); |
|
116 |
} |
|
117 |
} |
|
118 |
|
|
119 |
/** |
|
120 |
* 短信接收状态 |
|
121 |
* |
|
122 |
* 参见 <a href="https://help.aliyun.com/document_detail/101867.html">文档</a> |
|
123 |
* |
|
124 |
* @author iailab |
|
125 |
*/ |
|
126 |
@Data |
|
127 |
public static class SmsReceiveStatus { |
|
128 |
|
|
129 |
/** |
|
130 |
* 手机号 |
|
131 |
*/ |
|
132 |
@JsonProperty("phone_number") |
|
133 |
private String phoneNumber; |
|
134 |
/** |
|
135 |
* 发送时间 |
|
136 |
*/ |
|
137 |
@JsonProperty("send_time") |
|
138 |
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) |
|
139 |
private LocalDateTime sendTime; |
|
140 |
/** |
|
141 |
* 状态报告时间 |
|
142 |
*/ |
|
143 |
@JsonProperty("report_time") |
|
144 |
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) |
|
145 |
private LocalDateTime reportTime; |
|
146 |
/** |
|
147 |
* 是否接收成功 |
|
148 |
*/ |
|
149 |
private Boolean success; |
|
150 |
/** |
|
151 |
* 状态报告说明 |
|
152 |
*/ |
|
153 |
@JsonProperty("err_msg") |
|
154 |
private String errMsg; |
|
155 |
/** |
|
156 |
* 状态报告编码 |
|
157 |
*/ |
|
158 |
@JsonProperty("err_code") |
|
159 |
private String errCode; |
|
160 |
/** |
|
161 |
* 发送序列号 |
|
162 |
*/ |
|
163 |
@JsonProperty("biz_id") |
|
164 |
private String bizId; |
|
165 |
/** |
|
166 |
* 用户序列号 |
|
167 |
* |
|
168 |
* 这里我们传递的是 SysSmsLogDO 的日志编号 |
|
169 |
*/ |
|
170 |
@JsonProperty("out_id") |
|
171 |
private String outId; |
|
172 |
/** |
|
173 |
* 短信长度,例如说 1、2、3 |
|
174 |
* |
|
175 |
* 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送 |
|
176 |
*/ |
|
177 |
@JsonProperty("sms_size") |
|
178 |
private Integer smsSize; |
|
179 |
|
|
180 |
} |
|
181 |
|
|
182 |
} |