Commit 8ab29d2a257e7fbbdbae4230137a83ea64a7f5a6

Authored by YunaiV
1 parent c91833a5

短信回调的解析重构

src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java
@@ -39,6 +39,6 @@ public interface SmsClient { @@ -39,6 +39,6 @@ public interface SmsClient {
39 * @return 结果内容 39 * @return 结果内容
40 * @throws Throwable 当解析 text 发生异常时,则会抛出异常 40 * @throws Throwable 当解析 text 发生异常时,则会抛出异常
41 */ 41 */
42 - SmsCommonResult<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable; 42 + List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
43 43
44 } 44 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java
1 package cn.iocoder.dashboard.framework.sms.core.client.dto; 1 package cn.iocoder.dashboard.framework.sms.core.client.dto;
2 2
3 -import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;  
4 import lombok.Data; 3 import lombok.Data;
5 4
6 -import java.io.Serializable;  
7 import java.util.Date; 5 import java.util.Date;
8 6
9 /** 7 /**
@@ -12,35 +10,39 @@ import java.util.Date; @@ -12,35 +10,39 @@ import java.util.Date;
12 * @author 芋道源码 10 * @author 芋道源码
13 */ 11 */
14 @Data 12 @Data
15 -public class SmsReceiveRespDTO implements Serializable { 13 +public class SmsReceiveRespDTO {
16 14
17 /** 15 /**
18 - * 唯一标识 16 + * 是否接收成功
19 */ 17 */
20 - private String apiId;  
21 - 18 + private Boolean success;
22 /** 19 /**
23 - * 短信发送状态 {@link SysSmsSendStatusEnum} 20 + * API 接收结果编码
24 */ 21 */
25 - private Integer sendStatus;  
26 - 22 + private String errorCode;
27 /** 23 /**
28 - * 接收手机号 24 + * API 接收结果说明
29 */ 25 */
30 - private String phone; 26 + private String errorMsg;
31 27
32 /** 28 /**
33 - * 提示 29 + * 手机号
34 */ 30 */
35 - private String message;  
36 - 31 + private String mobile;
37 /** 32 /**
38 - * 时间 33 + * 用户接收时间
39 */ 34 */
40 - private Date sendTime; 35 + private Date receiveTime;
41 36
42 /** 37 /**
43 - * 接口返回值 38 + * 短信 API 发送返回的序号
44 */ 39 */
45 - private Object callbackResponseBody; 40 + private String serialNo;
  41 + /**
  42 + * 短信日志编号
  43 + *
  44 + * 对应 SysSmsLogDO 的编号
  45 + */
  46 + private Long logId;
  47 +
46 } 48 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java
@@ -90,7 +90,7 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -90,7 +90,7 @@ public abstract class AbstractSmsClient implements SmsClient {
90 throws Throwable; 90 throws Throwable;
91 91
92 @Override 92 @Override
93 - public SmsCommonResult<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable { 93 + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable {
94 try { 94 try {
95 return doParseSmsReceiveStatus(text); 95 return doParseSmsReceiveStatus(text);
96 } catch (Throwable ex) { 96 } catch (Throwable ex) {
@@ -99,6 +99,6 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -99,6 +99,6 @@ public abstract class AbstractSmsClient implements SmsClient {
99 } 99 }
100 } 100 }
101 101
102 - protected abstract SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable; 102 + protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
103 103
104 } 104 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java
1 package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; 1 package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
2 2
3 -import cn.hutool.core.collection.CollectionUtil;  
4 -import cn.hutool.core.date.DateUtil;  
5 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.dashboard.common.core.KeyValue; 4 import cn.iocoder.dashboard.common.core.KeyValue;
7 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; 5 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
@@ -9,7 +7,6 @@ import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -9,7 +7,6 @@ import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
9 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 7 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
10 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; 8 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
11 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 9 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
12 -import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;  
13 import cn.iocoder.dashboard.util.collection.MapUtils; 10 import cn.iocoder.dashboard.util.collection.MapUtils;
14 import cn.iocoder.dashboard.util.json.JsonUtils; 11 import cn.iocoder.dashboard.util.json.JsonUtils;
15 import com.aliyuncs.DefaultAcsClient; 12 import com.aliyuncs.DefaultAcsClient;
@@ -20,16 +17,17 @@ import com.aliyuncs.exceptions.ClientException; @@ -20,16 +17,17 @@ import com.aliyuncs.exceptions.ClientException;
20 import com.aliyuncs.http.MethodType; 17 import com.aliyuncs.http.MethodType;
21 import com.aliyuncs.profile.DefaultProfile; 18 import com.aliyuncs.profile.DefaultProfile;
22 import com.aliyuncs.profile.IClientProfile; 19 import com.aliyuncs.profile.IClientProfile;
23 -import com.fasterxml.jackson.core.type.TypeReference; 20 +import com.fasterxml.jackson.annotation.JsonFormat;
  21 +import com.fasterxml.jackson.annotation.JsonProperty;
  22 +import lombok.Data;
24 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
25 24
26 -import javax.servlet.ServletRequest;  
27 -import java.io.BufferedReader;  
28 -import java.io.InputStreamReader;  
29 import java.util.Date; 25 import java.util.Date;
30 -import java.util.HashMap;  
31 import java.util.List; 26 import java.util.List;
32 -import java.util.Map; 27 +import java.util.stream.Collectors;
  28 +
  29 +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  30 +import static cn.iocoder.dashboard.util.date.DateUtils.TIME_ZONE_DEFAULT;
33 31
34 /** 32 /**
35 * 阿里短信客户端的实现类 33 * 阿里短信客户端的实现类
@@ -40,8 +38,9 @@ import java.util.Map; @@ -40,8 +38,9 @@ import java.util.Map;
40 @Slf4j 38 @Slf4j
41 public class AliyunSmsClient extends AbstractSmsClient { 39 public class AliyunSmsClient extends AbstractSmsClient {
42 40
43 - private static final String PRODUCT = "Dystopi";  
44 - private static final String DOMAIN = "dysmsapi.aliyuncs.com"; 41 + /**
  42 + * REGION, 使用杭州
  43 + */
45 private static final String ENDPOINT = "cn-hangzhou"; 44 private static final String ENDPOINT = "cn-hangzhou";
46 45
47 /** 46 /**
@@ -56,7 +55,6 @@ public class AliyunSmsClient extends AbstractSmsClient { @@ -56,7 +55,6 @@ public class AliyunSmsClient extends AbstractSmsClient {
56 @Override 55 @Override
57 protected void doInit() { 56 protected void doInit() {
58 IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); 57 IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret());
59 - DefaultProfile.addEndpoint(ENDPOINT, PRODUCT, DOMAIN);  
60 acsClient = new DefaultAcsClient(profile); 58 acsClient = new DefaultAcsClient(profile);
61 } 59 }
62 60
@@ -93,133 +91,80 @@ public class AliyunSmsClient extends AbstractSmsClient { @@ -93,133 +91,80 @@ public class AliyunSmsClient extends AbstractSmsClient {
93 return ex.getErrMsg() + " => " + ex.getErrorDescription(); 91 return ex.getErrMsg() + " => " + ex.getErrorDescription();
94 } 92 }
95 93
96 - /**  
97 - * [{  
98 - * "send_time" : "2017-08-30 00:00:00",  
99 - * "report_time" : "2017-08-30 00:00:00",  
100 - * "success" : true,  
101 - * "err_msg" : "用户接收成功",  
102 - * "err_code" : "DELIVERED",  
103 - * "phone_number" : "18612345678",  
104 - * "sms_size" : "1",  
105 - * "biz_id" : "932702304080415357^0",  
106 - * "out_id" : "1184585343"  
107 - * }]  
108 - *  
109 - * @param request 请求  
110 - * @return  
111 - * @throws Exception  
112 - */  
113 - public SmsReceiveRespDTO smsSendCallbackHandle(ServletRequest request) throws Exception {  
114 - BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));  
115 - String paramStr = reader.readLine();  
116 - List<Map<String, Object>> params = JsonUtils.parseObject(paramStr, new TypeReference<List<Map<String, Object>>>() {  
117 - });  
118 - if (CollectionUtil.isNotEmpty(params)) {  
119 - Map<String, Object> sendResultParamMap = params.get(0);  
120 - return CallbackHelper.of(sendResultParamMap).toResultDetail();  
121 - }  
122 - return null;  
123 - }  
124 -  
125 @Override 94 @Override
126 - protected SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {  
127 - return null; 95 + protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
  96 + List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
  97 + return statuses.stream().map(status -> {
  98 + SmsReceiveRespDTO resp = new SmsReceiveRespDTO();
  99 + resp.setSuccess(status.getSuccess());
  100 + resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg());
  101 + resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime());
  102 + resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()));
  103 + return resp;
  104 + }).collect(Collectors.toList());
128 } 105 }
129 106
130 /** 107 /**
131 - * 短信发送回调辅助类 108 + * 短信接收状态
  109 + *
  110 + * 参见 https://help.aliyun.com/document_detail/101867.html 文档
  111 + *
  112 + * @author 芋道源码
132 */ 113 */
133 - private static class CallbackHelper {  
134 -  
135 - private final Map<String, Object> sendResultParamMap;  
136 -  
137 - private CallbackHelper(Map<String, Object> sendResultParamMap) {  
138 - this.sendResultParamMap = sendResultParamMap;  
139 - }  
140 -  
141 - public static CallbackHelper of(Map<String, Object> sendResultParamMap) {  
142 - return new CallbackHelper(sendResultParamMap);  
143 - }  
144 -  
145 - public Integer getSendStatus() {  
146 - return ((Boolean) sendResultParamMap.get(CallbackField.SUCCESS))  
147 - ? SysSmsSendStatusEnum.SUCCESS.getStatus()  
148 - : SysSmsSendStatusEnum.FAILURE.getStatus();  
149 - }  
150 -  
151 - public String getBizId() {  
152 - return sendResultParamMap.get(CallbackField.BIZ_ID).toString();  
153 - }  
154 -  
155 - public String getErrMsg() {  
156 - return sendResultParamMap.get(CallbackField.ERR_MSG).toString();  
157 - }  
158 -  
159 - public String getErrCode() {  
160 - return sendResultParamMap.get(CallbackField.ERR_CODE).toString();  
161 - }  
162 -  
163 - public Date getSendTime() {  
164 - return DateUtil.parseTime(sendResultParamMap.get(CallbackField.SEND_TIME).toString());  
165 - }  
166 -  
167 - public String getPhoneNumber() {  
168 - return sendResultParamMap.get(CallbackField.PHONE_NUMBER).toString();  
169 - }  
170 -  
171 - public String getOutId() {  
172 - return sendResultParamMap.get(CallbackField.OUT_ID).toString();  
173 - }  
174 -  
175 - public SmsReceiveRespDTO toResultDetail() {  
176 - SmsReceiveRespDTO resultDetail = new SmsReceiveRespDTO();  
177 - resultDetail.setSendStatus(getSendStatus());  
178 - resultDetail.setApiId(getBizId());  
179 - resultDetail.setSendTime(getSendTime());  
180 - resultDetail.setPhone(getPhoneNumber());  
181 - resultDetail.setMessage(getErrMsg());  
182 -  
183 - resultDetail.setCallbackResponseBody(generateSuccessResponseBody());  
184 - return resultDetail;  
185 - } 114 + @Data
  115 + public static class SmsReceiveStatus {
186 116
187 /** 117 /**
188 - * 生成回调成功的返回对象 118 + * 手机号
189 */ 119 */
190 - private Map<String, Object> generateSuccessResponseBody() {  
191 - Map<String, Object> result = new HashMap<>();  
192 - result.put("code", 0);  
193 - result.put("msg", "成功");  
194 - return result;  
195 - }  
196 -  
197 - }  
198 -  
199 - /**  
200 - * 回调接口字段定义  
201 - */  
202 - private interface CallbackField {  
203 - //是否成功 boolean  
204 - String SUCCESS = "success";  
205 -  
206 - //发送时间  
207 - String SEND_TIME = "send_time";  
208 -  
209 - //错误信息  
210 - String ERR_MSG = "err_msg";  
211 -  
212 - //错误编码  
213 - String ERR_CODE = "err_code";  
214 -  
215 - //手机号  
216 - String PHONE_NUMBER = "phone_number";  
217 -  
218 - //用户序列号 out_id  
219 - String OUT_ID = "out_id"; 120 + @JsonProperty("phone_number")
  121 + private String phoneNumber;
  122 + /**
  123 + * 发送时间
  124 + */
  125 + @JsonProperty("send_time")
  126 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  127 + private Date sendTime;
  128 + /**
  129 + * 状态报告时间
  130 + */
  131 + @JsonProperty("report_time")
  132 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  133 + private Date reportTime;
  134 + /**
  135 + * 是否接收成功
  136 + */
  137 + private Boolean success;
  138 + /**
  139 + * 状态报告说明
  140 + */
  141 + @JsonProperty("err_msg")
  142 + private String errMsg;
  143 + /**
  144 + * 状态报告编码
  145 + */
  146 + @JsonProperty("err_code")
  147 + private String errCode;
  148 + /**
  149 + * 发送序列号
  150 + */
  151 + @JsonProperty("biz_id")
  152 + private String bizId;
  153 + /**
  154 + * 用户序列号
  155 + *
  156 + * 这里我们传递的是 SysSmsLogDO 的日志编号
  157 + */
  158 + @JsonProperty("out_id")
  159 + private String outId;
  160 + /**
  161 + * 短信长度,例如说 1、2、3
  162 + *
  163 + * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送
  164 + */
  165 + @JsonProperty("sms_size")
  166 + private Integer smsSize;
220 167
221 - //biz_id 即 apiId 唯一标识  
222 - String BIZ_ID = "biz_id";  
223 } 168 }
224 169
225 } 170 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java
1 package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; 1 package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.collection.CollectionUtil;  
5 -import cn.hutool.core.util.CharsetUtil;  
6 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
7 import cn.hutool.core.util.URLUtil; 5 import cn.hutool.core.util.URLUtil;
8 import cn.iocoder.dashboard.common.core.KeyValue; 6 import cn.iocoder.dashboard.common.core.KeyValue;
@@ -11,11 +9,9 @@ import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -11,11 +9,9 @@ import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
11 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 9 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
12 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; 10 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
13 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 11 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
14 -import cn.iocoder.dashboard.util.date.DateUtils;  
15 import cn.iocoder.dashboard.util.json.JsonUtils; 12 import cn.iocoder.dashboard.util.json.JsonUtils;
16 import com.fasterxml.jackson.annotation.JsonFormat; 13 import com.fasterxml.jackson.annotation.JsonFormat;
17 import com.fasterxml.jackson.annotation.JsonProperty; 14 import com.fasterxml.jackson.annotation.JsonProperty;
18 -import com.fasterxml.jackson.core.type.TypeReference;  
19 import com.yunpian.sdk.YunpianClient; 15 import com.yunpian.sdk.YunpianClient;
20 import com.yunpian.sdk.constant.YunpianConstant; 16 import com.yunpian.sdk.constant.YunpianConstant;
21 import com.yunpian.sdk.model.Result; 17 import com.yunpian.sdk.model.Result;
@@ -23,10 +19,11 @@ import com.yunpian.sdk.model.SmsSingleSend; @@ -23,10 +19,11 @@ import com.yunpian.sdk.model.SmsSingleSend;
23 import lombok.Data; 19 import lombok.Data;
24 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
25 21
26 -import javax.servlet.ServletRequest;  
27 -import java.io.UnsupportedEncodingException;  
28 -import java.net.URLEncoder;  
29 import java.util.*; 22 import java.util.*;
  23 +import java.util.stream.Collectors;
  24 +
  25 +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  26 +import static cn.iocoder.dashboard.util.date.DateUtils.TIME_ZONE_DEFAULT;
30 27
31 /** 28 /**
32 * 云片短信客户端的实现类 29 * 云片短信客户端的实现类
@@ -42,9 +39,6 @@ public class YunpianSmsClient extends AbstractSmsClient { @@ -42,9 +39,6 @@ public class YunpianSmsClient extends AbstractSmsClient {
42 */ 39 */
43 private volatile YunpianClient client; 40 private volatile YunpianClient client;
44 41
45 - private final TypeReference<List<Map<String, String>>> callbackType = new TypeReference<List<Map<String, String>>>() {  
46 - };  
47 -  
48 public YunpianSmsClient(SmsChannelProperties properties) { 42 public YunpianSmsClient(SmsChannelProperties properties) {
49 super(properties, new YunpianSmsCodeMapping()); 43 super(properties, new YunpianSmsCodeMapping());
50 } 44 }
@@ -105,28 +99,17 @@ public class YunpianSmsClient extends AbstractSmsClient { @@ -105,28 +99,17 @@ public class YunpianSmsClient extends AbstractSmsClient {
105 return sendResult.getMsg() + " => " + sendResult.getDetail(); 99 return sendResult.getMsg() + " => " + sendResult.getDetail();
106 } 100 }
107 101
108 - /**  
109 - * 从 request 中获取请求中传入的短信发送结果信息  
110 - *  
111 - * @param request 回调请求  
112 - * @return 短信发送结果信息  
113 - * @throws UnsupportedEncodingException 解码异常  
114 - */  
115 - private Map<String, String> getRequestParams(ServletRequest request) throws UnsupportedEncodingException {  
116 - Map<String, String[]> parameterMap = request.getParameterMap();  
117 - String[] smsStatuses = parameterMap.get(YunpianConstant.SMS_STATUS);  
118 - String encode = URLEncoder.encode(smsStatuses[0], CharsetUtil.UTF_8);  
119 - List<Map<String, String>> paramList = JsonUtils.parseObject(encode, callbackType);  
120 - if (CollectionUtil.isNotEmpty(paramList)) {  
121 - return paramList.get(0);  
122 - }  
123 - throw new IllegalArgumentException("YunpianSmsClient getRequestParams fail! can't format RequestParam: "  
124 - + JsonUtils.toJsonString(request.getParameterMap()));  
125 - }  
126 -  
127 @Override 102 @Override
128 - protected SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {  
129 - return null; 103 + protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
  104 + List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
  105 + return statuses.stream().map(status -> {
  106 + SmsReceiveRespDTO resp = new SmsReceiveRespDTO();
  107 + resp.setSuccess(Objects.equals(status.getReportStatus(), "SUCCESS"));
  108 + resp.setErrorCode(status.getErrorMsg()).setErrorMsg(status.getErrorDetail());
  109 + resp.setMobile(status.getMobile()).setReceiveTime(status.getUserReceiveTime());
  110 + resp.setSerialNo(String.valueOf(status.getSid())).setLogId(status.getUid());
  111 + return resp;
  112 + }).collect(Collectors.toList());
130 } 113 }
131 114
132 /** 115 /**
@@ -140,6 +123,24 @@ public class YunpianSmsClient extends AbstractSmsClient { @@ -140,6 +123,24 @@ public class YunpianSmsClient extends AbstractSmsClient {
140 public static class SmsReceiveStatus { 123 public static class SmsReceiveStatus {
141 124
142 /** 125 /**
  126 + * 接收状态
  127 + *
  128 + * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收
  129 + */
  130 + @JsonProperty("report_status")
  131 + private String reportStatus;
  132 + /**
  133 + * 接收手机号
  134 + */
  135 + private String mobile;
  136 + /**
  137 + * 运营商返回的代码,如:"DB:0103"
  138 + *
  139 + * 由于不同运营商信息不同,此字段仅供参考;
  140 + */
  141 + @JsonProperty("error_msg")
  142 + private String errorMsg;
  143 + /**
143 * 运营商反馈代码的中文解释 144 * 运营商反馈代码的中文解释
144 * 145 *
145 * 默认不推送此字段,如需推送,请联系客服 146 * 默认不推送此字段,如需推送,请联系客服
@@ -160,26 +161,8 @@ public class YunpianSmsClient extends AbstractSmsClient { @@ -160,26 +161,8 @@ public class YunpianSmsClient extends AbstractSmsClient {
160 * 用户接收时间 161 * 用户接收时间
161 */ 162 */
162 @JsonProperty("user_receive_time") 163 @JsonProperty("user_receive_time")
163 - @JsonFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 164 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
164 private Date userReceiveTime; 165 private Date userReceiveTime;
165 - /**  
166 - * 运营商返回的代码,如:"DB:0103"  
167 - *  
168 - * 由于不同运营商信息不同,此字段仅供参考;  
169 - */  
170 - @JsonProperty("error_msg")  
171 - private String errorMsg;  
172 - /**  
173 - * 接收手机号  
174 - */  
175 - private String mobile;  
176 - /**  
177 - * 接收状态  
178 - *  
179 - * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收  
180 - */  
181 - @JsonProperty("report_status")  
182 - private String reportStatus;  
183 166
184 } 167 }
185 168
src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java
@@ -152,7 +152,7 @@ public class SysSmsServiceImpl implements SysSmsService { @@ -152,7 +152,7 @@ public class SysSmsServiceImpl implements SysSmsService {
152 SmsClient smsClient = smsClientFactory.getSmsClient(channelCode); 152 SmsClient smsClient = smsClientFactory.getSmsClient(channelCode);
153 Assert.notNull(smsClient, String.format("短信客户端(%s) 不存在", channelCode)); 153 Assert.notNull(smsClient, String.format("短信客户端(%s) 不存在", channelCode));
154 // 解析内容 154 // 解析内容
155 - SmsCommonResult<SmsReceiveRespDTO> receiveResult = smsClient.parseSmsReceiveStatus(text); 155 + List<SmsReceiveRespDTO> receiveResults = smsClient.parseSmsReceiveStatus(text);
156 } 156 }
157 157
158 } 158 }
src/main/java/cn/iocoder/dashboard/util/date/DateUtils.java
@@ -9,6 +9,11 @@ import java.util.Date; @@ -9,6 +9,11 @@ import java.util.Date;
9 */ 9 */
10 public class DateUtils { 10 public class DateUtils {
11 11
  12 + /**
  13 + * 时区 - 默认
  14 + */
  15 + public static final String TIME_ZONE_DEFAULT = "GMT+8";
  16 +
12 public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; 17 public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
13 18
14 public static Date addTime(Duration duration) { 19 public static Date addTime(Duration duration) {
src/main/java/cn/iocoder/dashboard/util/json/JsonUtils.java
@@ -2,7 +2,6 @@ package cn.iocoder.dashboard.util.json; @@ -2,7 +2,6 @@ package cn.iocoder.dashboard.util.json;
2 2
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 -import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient;  
6 import com.fasterxml.jackson.core.JsonProcessingException; 5 import com.fasterxml.jackson.core.JsonProcessingException;
7 import com.fasterxml.jackson.core.type.TypeReference; 6 import com.fasterxml.jackson.core.type.TypeReference;
8 import com.fasterxml.jackson.databind.ObjectMapper; 7 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -80,10 +79,4 @@ public class JsonUtils { @@ -80,10 +79,4 @@ public class JsonUtils {
80 } 79 }
81 } 80 }
82 81
83 - public static void main(String[] args) {  
84 - String text = "[{\"sid\":9527,\"uid\":null,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"},{\"sid\":9528,\"uid\":null,\"user_receive_time\":\"2014-03-17 22:55:23\",\"error_msg\":\"\",\"mobile\":\"15212341234\",\"report_status\":\"SUCCESS\"}]";  
85 - List<YunpianSmsClient.SmsReceiveStatus> result = parseArray(text, YunpianSmsClient.SmsReceiveStatus.class);  
86 - System.out.println(result);  
87 - }  
88 -  
89 } 82 }
src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java renamed to src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java
@@ -13,7 +13,7 @@ import java.util.List; @@ -13,7 +13,7 @@ import java.util.List;
13 /** 13 /**
14 * {@link AliyunSmsClient} 的集成测试 14 * {@link AliyunSmsClient} 的集成测试
15 */ 15 */
16 -public class AliyunSmsClientTest { 16 +public class AliyunSmsClientIntegrationTest {
17 17
18 @Test 18 @Test
19 public void testSend() { 19 public void testSend() {
src/test-integration/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsServiceIntegrationTest.java
@@ -34,7 +34,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest @@ -34,7 +34,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest
34 private SysUserService userService; 34 private SysUserService userService;
35 35
36 @Test 36 @Test
37 - public void testSendSingleSms_云片发送成功() { 37 + public void testSendSingleSms_yunpianSuccess() {
38 // 参数准备 38 // 参数准备
39 String mobile = "15601691399"; 39 String mobile = "15601691399";
40 Long userId = 1L; 40 Long userId = 1L;
@@ -50,7 +50,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest @@ -50,7 +50,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest
50 } 50 }
51 51
52 @Test 52 @Test
53 - public void testSendSingleSms_阿里云发送成功() { 53 + public void testSendSingleSms_aliyunSuccess() {
54 // 参数准备 54 // 参数准备
55 String mobile = "15601691399"; 55 String mobile = "15601691399";
56 Long userId = 1L; 56 Long userId = 1L;
src/test/java/cn/iocoder/dashboard/framework/package-info.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework;
src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
  2 +
  3 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
  4 +import cn.iocoder.dashboard.util.date.DateUtils;
  5 +import org.junit.jupiter.api.Test;
  6 +import org.mockito.InjectMocks;
  7 +
  8 +import java.util.List;
  9 +
  10 +import static org.junit.jupiter.api.Assertions.assertEquals;
  11 +import static org.junit.jupiter.api.Assertions.assertTrue;
  12 +
  13 +/**
  14 + * {@link AliyunSmsClient} 的单元测试
  15 + */
  16 +public class AliyunSmsClientTest {
  17 +
  18 + @InjectMocks
  19 + private final AliyunSmsClient smsClient = new AliyunSmsClient(null);
  20 +
  21 + @Test
  22 + void doInit() {
  23 + }
  24 +
  25 + @Test
  26 + void doSendSms() {
  27 + }
  28 +
  29 + @Test
  30 + public void testDoTParseSmsReceiveStatus() throws Throwable {
  31 + // 准备参数
  32 + String text = "[\n" +
  33 + " {\n" +
  34 + " \"phone_number\" : \"13900000001\",\n" +
  35 + " \"send_time\" : \"2017-01-01 11:12:13\",\n" +
  36 + " \"report_time\" : \"2017-02-02 22:23:24\",\n" +
  37 + " \"success\" : true,\n" +
  38 + " \"err_code\" : \"DELIVERED\",\n" +
  39 + " \"err_msg\" : \"用户接收成功\",\n" +
  40 + " \"sms_size\" : \"1\",\n" +
  41 + " \"biz_id\" : \"12345\",\n" +
  42 + " \"out_id\" : \"67890\"\n" +
  43 + " }\n" +
  44 + "]";
  45 + // mock 方法
  46 +
  47 + // 调用
  48 + List<SmsReceiveRespDTO> statuses = smsClient.doParseSmsReceiveStatus(text);
  49 + // 断言
  50 + assertEquals(1, statuses.size());
  51 + assertTrue(statuses.get(0).getSuccess());
  52 + assertEquals("DELIVERED", statuses.get(0).getErrorCode());
  53 + assertEquals("用户接收成功", statuses.get(0).getErrorMsg());
  54 + assertEquals("13900000001", statuses.get(0).getMobile());
  55 + assertEquals(DateUtils.buildTime(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime());
  56 + assertEquals("12345", statuses.get(0).getSerialNo());
  57 + assertEquals(67890L, statuses.get(0).getLogId());
  58 + }
  59 +
  60 +}
src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
  2 +
  3 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
  4 +import cn.iocoder.dashboard.util.date.DateUtils;
  5 +import org.junit.jupiter.api.Test;
  6 +import org.mockito.InjectMocks;
  7 +
  8 +import java.util.List;
  9 +
  10 +import static org.junit.jupiter.api.Assertions.*;
  11 +
  12 +/**
  13 + * 对 {@link YunpianSmsClient} 的单元测试
  14 + */
  15 +public class YunpianSmsClientTest {
  16 +
  17 + @InjectMocks
  18 + private final YunpianSmsClient smsClient = new YunpianSmsClient(null);
  19 +
  20 + @Test
  21 + void doInit() {
  22 + }
  23 +
  24 + @Test
  25 + void doSendSms() {
  26 + }
  27 +
  28 + @Test
  29 + void testDoParseSmsReceiveStatus() throws Throwable {
  30 + // 准备参数
  31 + String text = "[{\"sid\":9527,\"uid\":1024,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"}]";
  32 + // mock 方法
  33 +
  34 + // 调用
  35 +
  36 + // 断言
  37 + // 调用
  38 + List<SmsReceiveRespDTO> statuses = smsClient.doParseSmsReceiveStatus(text);
  39 + // 断言
  40 + assertEquals(1, statuses.size());
  41 + assertTrue(statuses.get(0).getSuccess());
  42 + assertEquals("", statuses.get(0).getErrorCode());
  43 + assertNull(statuses.get(0).getErrorMsg());
  44 + assertEquals("15205201314", statuses.get(0).getMobile());
  45 + assertEquals(DateUtils.buildTime(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime());
  46 + assertEquals("9527", statuses.get(0).getSerialNo());
  47 + assertEquals(1024L, statuses.get(0).getLogId());
  48 + }
  49 +
  50 +}