Commit 8ab29d2a257e7fbbdbae4230137a83ea64a7f5a6
1 parent
c91833a5
短信回调的解析重构
Showing
13 changed files
with
251 additions
and
212 deletions
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java
| ... | ... | @@ -39,6 +39,6 @@ public interface SmsClient { |
| 39 | 39 | * @return 结果内容 |
| 40 | 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 | 1 | package cn.iocoder.dashboard.framework.sms.core.client.dto; |
| 2 | 2 | |
| 3 | -import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; | |
| 4 | 3 | import lombok.Data; |
| 5 | 4 | |
| 6 | -import java.io.Serializable; | |
| 7 | 5 | import java.util.Date; |
| 8 | 6 | |
| 9 | 7 | /** |
| ... | ... | @@ -12,35 +10,39 @@ import java.util.Date; |
| 12 | 10 | * @author 芋道源码 |
| 13 | 11 | */ |
| 14 | 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 | 90 | throws Throwable; |
| 91 | 91 | |
| 92 | 92 | @Override |
| 93 | - public SmsCommonResult<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable { | |
| 93 | + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable { | |
| 94 | 94 | try { |
| 95 | 95 | return doParseSmsReceiveStatus(text); |
| 96 | 96 | } catch (Throwable ex) { |
| ... | ... | @@ -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 | 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 | 3 | import cn.hutool.core.util.StrUtil; |
| 6 | 4 | import cn.iocoder.dashboard.common.core.KeyValue; |
| 7 | 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 | import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; |
| 10 | 8 | import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; |
| 11 | 9 | import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; |
| 12 | -import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; | |
| 13 | 10 | import cn.iocoder.dashboard.util.collection.MapUtils; |
| 14 | 11 | import cn.iocoder.dashboard.util.json.JsonUtils; |
| 15 | 12 | import com.aliyuncs.DefaultAcsClient; |
| ... | ... | @@ -20,16 +17,17 @@ import com.aliyuncs.exceptions.ClientException; |
| 20 | 17 | import com.aliyuncs.http.MethodType; |
| 21 | 18 | import com.aliyuncs.profile.DefaultProfile; |
| 22 | 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 | 23 | import lombok.extern.slf4j.Slf4j; |
| 25 | 24 | |
| 26 | -import javax.servlet.ServletRequest; | |
| 27 | -import java.io.BufferedReader; | |
| 28 | -import java.io.InputStreamReader; | |
| 29 | 25 | import java.util.Date; |
| 30 | -import java.util.HashMap; | |
| 31 | 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 | 38 | @Slf4j |
| 41 | 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 | 44 | private static final String ENDPOINT = "cn-hangzhou"; |
| 46 | 45 | |
| 47 | 46 | /** |
| ... | ... | @@ -56,7 +55,6 @@ public class AliyunSmsClient extends AbstractSmsClient { |
| 56 | 55 | @Override |
| 57 | 56 | protected void doInit() { |
| 58 | 57 | IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); |
| 59 | - DefaultProfile.addEndpoint(ENDPOINT, PRODUCT, DOMAIN); | |
| 60 | 58 | acsClient = new DefaultAcsClient(profile); |
| 61 | 59 | } |
| 62 | 60 | |
| ... | ... | @@ -93,133 +91,80 @@ public class AliyunSmsClient extends AbstractSmsClient { |
| 93 | 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 | 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 | 1 | package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.collection.CollectionUtil; | |
| 5 | -import cn.hutool.core.util.CharsetUtil; | |
| 6 | 4 | import cn.hutool.core.util.StrUtil; |
| 7 | 5 | import cn.hutool.core.util.URLUtil; |
| 8 | 6 | import cn.iocoder.dashboard.common.core.KeyValue; |
| ... | ... | @@ -11,11 +9,9 @@ import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 11 | 9 | import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; |
| 12 | 10 | import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; |
| 13 | 11 | import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; |
| 14 | -import cn.iocoder.dashboard.util.date.DateUtils; | |
| 15 | 12 | import cn.iocoder.dashboard.util.json.JsonUtils; |
| 16 | 13 | import com.fasterxml.jackson.annotation.JsonFormat; |
| 17 | 14 | import com.fasterxml.jackson.annotation.JsonProperty; |
| 18 | -import com.fasterxml.jackson.core.type.TypeReference; | |
| 19 | 15 | import com.yunpian.sdk.YunpianClient; |
| 20 | 16 | import com.yunpian.sdk.constant.YunpianConstant; |
| 21 | 17 | import com.yunpian.sdk.model.Result; |
| ... | ... | @@ -23,10 +19,11 @@ import com.yunpian.sdk.model.SmsSingleSend; |
| 23 | 19 | import lombok.Data; |
| 24 | 20 | import lombok.extern.slf4j.Slf4j; |
| 25 | 21 | |
| 26 | -import javax.servlet.ServletRequest; | |
| 27 | -import java.io.UnsupportedEncodingException; | |
| 28 | -import java.net.URLEncoder; | |
| 29 | 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 | 39 | */ |
| 43 | 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 | 42 | public YunpianSmsClient(SmsChannelProperties properties) { |
| 49 | 43 | super(properties, new YunpianSmsCodeMapping()); |
| 50 | 44 | } |
| ... | ... | @@ -105,28 +99,17 @@ public class YunpianSmsClient extends AbstractSmsClient { |
| 105 | 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 | 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 | 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 | 161 | * 用户接收时间 |
| 161 | 162 | */ |
| 162 | 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 | 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 | 152 | SmsClient smsClient = smsClientFactory.getSmsClient(channelCode); |
| 153 | 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 | 9 | */ |
| 10 | 10 | public class DateUtils { |
| 11 | 11 | |
| 12 | + /** | |
| 13 | + * 时区 - 默认 | |
| 14 | + */ | |
| 15 | + public static final String TIME_ZONE_DEFAULT = "GMT+8"; | |
| 16 | + | |
| 12 | 17 | public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; |
| 13 | 18 | |
| 14 | 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 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient; | |
| 6 | 5 | import com.fasterxml.jackson.core.JsonProcessingException; |
| 7 | 6 | import com.fasterxml.jackson.core.type.TypeReference; |
| 8 | 7 | import com.fasterxml.jackson.databind.ObjectMapper; |
| ... | ... | @@ -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
src/test-integration/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsServiceIntegrationTest.java
| ... | ... | @@ -34,7 +34,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest |
| 34 | 34 | private SysUserService userService; |
| 35 | 35 | |
| 36 | 36 | @Test |
| 37 | - public void testSendSingleSms_云片发送成功() { | |
| 37 | + public void testSendSingleSms_yunpianSuccess() { | |
| 38 | 38 | // 参数准备 |
| 39 | 39 | String mobile = "15601691399"; |
| 40 | 40 | Long userId = 1L; |
| ... | ... | @@ -50,7 +50,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | @Test |
| 53 | - public void testSendSingleSms_阿里云发送成功() { | |
| 53 | + public void testSendSingleSms_aliyunSuccess() { | |
| 54 | 54 | // 参数准备 |
| 55 | 55 | String mobile = "15601691399"; |
| 56 | 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 | +} | ... | ... |