mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	短信提交 2021-04-01,重构返回的结果
This commit is contained in:
		@@ -1,12 +1,13 @@
 | 
			
		||||
package cn.iocoder.dashboard.common.exception;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 错误码对象
 | 
			
		||||
 *
 | 
			
		||||
 * 全局错误码,占用 [0, 999],参见 {@link GlobalException}
 | 
			
		||||
 * 全局错误码,占用 [0, 999], 参见 {@link GlobalErrorCodeConstants}
 | 
			
		||||
 * 业务异常错误码,占用 [1 000 000 000, +∞),参见 {@link ServiceErrorCodeRange}
 | 
			
		||||
 *
 | 
			
		||||
 * TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
 | 
			
		||||
@@ -21,11 +22,11 @@ public class ErrorCode {
 | 
			
		||||
    /**
 | 
			
		||||
     * 错误提示
 | 
			
		||||
     */
 | 
			
		||||
    private final String message;
 | 
			
		||||
    private final String msg;
 | 
			
		||||
 | 
			
		||||
    public ErrorCode(Integer code, String message) {
 | 
			
		||||
        this.code = code;
 | 
			
		||||
        this.message = message;
 | 
			
		||||
        this.msg = message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public final class ServiceException extends RuntimeException {
 | 
			
		||||
 | 
			
		||||
    public ServiceException(ErrorCode errorCode) {
 | 
			
		||||
        this.code = errorCode.getCode();
 | 
			
		||||
        this.message = errorCode.getMessage();
 | 
			
		||||
        this.message = errorCode.getMsg();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ServiceException(Integer code, String message) {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,12 +47,12 @@ public class ServiceExceptionUtil {
 | 
			
		||||
    // ========== 和 ServiceException 的集成 ==========
 | 
			
		||||
 | 
			
		||||
    public static ServiceException exception(ErrorCode errorCode) {
 | 
			
		||||
        String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
 | 
			
		||||
        String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
 | 
			
		||||
        return exception0(errorCode.getCode(), messagePattern);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ServiceException exception(ErrorCode errorCode, Object... params) {
 | 
			
		||||
        String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
 | 
			
		||||
        String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
 | 
			
		||||
        return exception0(errorCode.getCode(), messagePattern, params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public class CommonResult<T> implements Serializable {
 | 
			
		||||
    /**
 | 
			
		||||
     * 错误提示,用户可阅读
 | 
			
		||||
     *
 | 
			
		||||
     * @see ErrorCode#getMessage() ()
 | 
			
		||||
     * @see ErrorCode#getMsg() ()
 | 
			
		||||
     */
 | 
			
		||||
    private String msg;
 | 
			
		||||
 | 
			
		||||
@@ -56,7 +56,7 @@ public class CommonResult<T> implements Serializable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> CommonResult<T> error(ErrorCode errorCode) {
 | 
			
		||||
        return error(errorCode.getCode(), errorCode.getMessage());
 | 
			
		||||
        return error(errorCode.getCode(), errorCode.getMsg());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> CommonResult<T> success(T data) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.ServletRequest;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
 | 
			
		||||
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 将 API 的错误码,转换为通用的错误码
 | 
			
		||||
 *
 | 
			
		||||
 * @see SmsCommonResult
 | 
			
		||||
 * @see SmsFrameworkErrorCodeConstants
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public interface SmsCodeMapping extends Function<String, ErrorCode> {
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.exceptions.ExceptionUtil;
 | 
			
		||||
import cn.hutool.core.lang.Assert;
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
 | 
			
		||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.ToString;
 | 
			
		||||
@@ -40,20 +42,27 @@ public class SmsCommonResult<T> extends CommonResult<T> {
 | 
			
		||||
    private SmsCommonResult() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static SmsCommonResult success(SmsSendFailureTypeEnum sendFailureType,
 | 
			
		||||
                                          String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) {
 | 
			
		||||
        SmsCommonResult result = new SmsCommonResult().setSuccess(true).setApiSendCode(apiSendCode).setApiSendMsg(apiSendMsg)
 | 
			
		||||
                .setApiRequestId(apiRequestId).setApiSerialNo(apiSerialNo);
 | 
			
		||||
        if (sendFailureType != null) {
 | 
			
		||||
            result.setSendFailureType(sendFailureType.getType()).setSendFailureMsg(sendFailureType.getMsg());
 | 
			
		||||
    public static <T> SmsCommonResult<T> build(String apiCode, String apiMsg, String apiRequestId,
 | 
			
		||||
                                               T data, SmsCodeMapping codeMapping) {
 | 
			
		||||
        Assert.notNull(codeMapping, "参数 codeMapping 不能为空");
 | 
			
		||||
        SmsCommonResult<T> result = new SmsCommonResult<T>().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId);
 | 
			
		||||
        result.setData(data);
 | 
			
		||||
        // 翻译错误码
 | 
			
		||||
        if (codeMapping != null) {
 | 
			
		||||
            ErrorCode errorCode = codeMapping.apply(apiCode);
 | 
			
		||||
            if (errorCode == null) {
 | 
			
		||||
                errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
 | 
			
		||||
            }
 | 
			
		||||
            result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg());
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static SmsCommonResult error(Throwable ex) {
 | 
			
		||||
        return new SmsCommonResult().setSuccess(false)
 | 
			
		||||
                .setSendFailureType(SmsSendFailureTypeEnum.SMS_SEND_EXCEPTION.getType())
 | 
			
		||||
                .setSendFailureMsg(ExceptionUtil.getRootCauseMessage(ex));
 | 
			
		||||
    public static <T> SmsCommonResult<T> error(Throwable ex) {
 | 
			
		||||
        SmsCommonResult<T> result = new SmsCommonResult<>();
 | 
			
		||||
        result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode());
 | 
			
		||||
        result.setMsg(ExceptionUtil.getRootCauseMessage(ex));
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core;
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信发送响应 DTO
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class SmsSendRespDTO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.impl;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
@@ -21,14 +22,19 @@ public abstract class AbstractSmsClient implements SmsClient {
 | 
			
		||||
     * 短信渠道配置
 | 
			
		||||
     */
 | 
			
		||||
    protected volatile SmsChannelProperties properties;
 | 
			
		||||
    /**
 | 
			
		||||
     * 错误码枚举类
 | 
			
		||||
     */
 | 
			
		||||
    protected final SmsCodeMapping codeMapping;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信客户端有参构造函数
 | 
			
		||||
     *
 | 
			
		||||
     * @param properties 短信配置
 | 
			
		||||
     */
 | 
			
		||||
    public AbstractSmsClient(SmsChannelProperties properties) {
 | 
			
		||||
    public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) {
 | 
			
		||||
        this.properties = properties;
 | 
			
		||||
        this.codeMapping = codeMapping;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollectionUtil;
 | 
			
		||||
import cn.hutool.core.date.DateUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
 | 
			
		||||
import cn.iocoder.dashboard.util.json.JsonUtils;
 | 
			
		||||
@@ -48,7 +48,7 @@ public class AliyunSmsClient extends AbstractSmsClient {
 | 
			
		||||
    private volatile IAcsClient acsClient;
 | 
			
		||||
 | 
			
		||||
    public AliyunSmsClient(SmsChannelProperties properties) {
 | 
			
		||||
        super(properties);
 | 
			
		||||
        super(properties, new AliyunSmsCodeMapping());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -59,7 +59,8 @@ public class AliyunSmsClient extends AbstractSmsClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected SmsCommonResult doSend(Long sendLogId, String mobile, String apiTemplateId, Map<String, Object> templateParams) throws Exception {
 | 
			
		||||
    protected SmsCommonResult<SmsSendRespDTO> doSend(Long sendLogId, String mobile,
 | 
			
		||||
                                                     String apiTemplateId, Map<String, Object> templateParams) throws Throwable {
 | 
			
		||||
        // 构建参数
 | 
			
		||||
        SendSmsRequest request = new SendSmsRequest();
 | 
			
		||||
        request.setSysMethod(MethodType.POST);
 | 
			
		||||
@@ -73,25 +74,16 @@ public class AliyunSmsClient extends AbstractSmsClient {
 | 
			
		||||
            // 执行发送
 | 
			
		||||
            SendSmsResponse sendResult = acsClient.getAcsResponse(request);
 | 
			
		||||
            // 解析结果
 | 
			
		||||
            return SmsCommonResult.success(parseSendFailureType(sendResult.getCode()), // 将 API 短信平台,解析成统一的错误码
 | 
			
		||||
                    sendResult.getCode(), sendResult.getMessage(), sendResult.getRequestId(), sendResult.getBizId());
 | 
			
		||||
            SmsSendRespDTO data = null;
 | 
			
		||||
            if (sendResult.getBizId() != null) {
 | 
			
		||||
                data = new SmsSendRespDTO().setSerialNo(sendResult.getBizId());
 | 
			
		||||
            }
 | 
			
		||||
            return SmsCommonResult.build(sendResult.getCode(), sendResult.getMessage(), sendResult.getRequestId(), data, codeMapping);
 | 
			
		||||
        } catch (ClientException ex) {
 | 
			
		||||
            return SmsCommonResult.success(parseSendFailureType(ex.getErrCode()), // 将 API 短信平台,解析成统一的错误码
 | 
			
		||||
                    ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null);
 | 
			
		||||
            return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static SmsSendFailureTypeEnum parseSendFailureType(String code) {
 | 
			
		||||
        switch (code) {
 | 
			
		||||
            case "OK": return null;
 | 
			
		||||
            case "MissingAccessKeyId": return SmsSendFailureTypeEnum.SMS_CHANNEL_API_KEY_MISSING;
 | 
			
		||||
            case "isp.RAM_PERMISSION_DENY": return SmsSendFailureTypeEnum.SMS_CHANNEL_PERMISSION_DENY;
 | 
			
		||||
            case "isv.INVALID_PARAMETERS": return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR;
 | 
			
		||||
            case "isv.BUSINESS_LIMIT_CONTROL": return SmsSendFailureTypeEnum.SMS_SEND_LIMIT_CONTROL;
 | 
			
		||||
        }
 | 
			
		||||
        return SmsSendFailureTypeEnum.SMS_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String formatResultMsg(ClientException ex) {
 | 
			
		||||
        if (StrUtil.isEmpty(ex.getErrorDescription())) {
 | 
			
		||||
            return ex.getMessage();
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 阿里云的 SmsCodeMapping 实现类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public class AliyunSmsCodeMapping implements SmsCodeMapping {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ErrorCode apply(String apiCode) {
 | 
			
		||||
        switch (apiCode) {
 | 
			
		||||
            case "OK": return null;
 | 
			
		||||
            case "MissingAccessKeyId": return SMS_CHANNEL_API_KEY_MISSING;
 | 
			
		||||
            case "isp.RAM_PERMISSION_DENY": return SMS_CHANNEL_PERMISSION_DENY;
 | 
			
		||||
            case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR;
 | 
			
		||||
            case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_LIMIT_CONTROL;
 | 
			
		||||
        }
 | 
			
		||||
        return SMS_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -6,11 +6,11 @@ import cn.hutool.core.date.DateUtil;
 | 
			
		||||
import cn.hutool.core.util.CharsetUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.hutool.core.util.URLUtil;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.SmsConstants;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsConstants;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
 | 
			
		||||
import cn.iocoder.dashboard.util.json.JsonUtils;
 | 
			
		||||
@@ -29,8 +29,6 @@ import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.StringJoiner;
 | 
			
		||||
 | 
			
		||||
import static com.yunpian.sdk.constant.Code.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 云片短信客户端的实现类
 | 
			
		||||
 *
 | 
			
		||||
@@ -49,7 +47,7 @@ public class YunpianSmsClient extends AbstractSmsClient {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public YunpianSmsClient(SmsChannelProperties properties) {
 | 
			
		||||
        super(properties);
 | 
			
		||||
        super(properties, new YunpianSmsCodeMapping());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -66,7 +64,8 @@ public class YunpianSmsClient extends AbstractSmsClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected SmsCommonResult doSend(Long sendLogId, String mobile, String apiTemplateId, Map<String, Object> templateParams) throws Throwable {
 | 
			
		||||
    protected SmsCommonResult<SmsSendRespDTO> doSend(Long sendLogId, String mobile,
 | 
			
		||||
                                                     String apiTemplateId, Map<String, Object> templateParams) throws Throwable {
 | 
			
		||||
        // 构建参数
 | 
			
		||||
        Map<String, String> request = new HashMap<>();
 | 
			
		||||
        request.put(YunpianConstant.APIKEY, properties.getApiKey());
 | 
			
		||||
@@ -82,8 +81,12 @@ public class YunpianSmsClient extends AbstractSmsClient {
 | 
			
		||||
            throw sendResult.getThrowable();
 | 
			
		||||
        }
 | 
			
		||||
        // 解析结果
 | 
			
		||||
        return SmsCommonResult.success(parseSendFailureType(sendResult), // 将 API 短信平台,解析成统一的错误码
 | 
			
		||||
                String.valueOf(sendResult.getCode()), formatResultMsg(sendResult), null, getApiSerialNo(sendResult));
 | 
			
		||||
        SmsSendRespDTO data = null;
 | 
			
		||||
        if (sendResult.getData() != null) {
 | 
			
		||||
            data = new SmsSendRespDTO().setSerialNo(String.valueOf(sendResult.getData().getSid()));
 | 
			
		||||
        }
 | 
			
		||||
        return SmsCommonResult.build(String.valueOf(sendResult.getCode()), formatResultMsg(sendResult), null,
 | 
			
		||||
                data, codeMapping);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String formatTplValue(Map<String, Object> templateParams) {
 | 
			
		||||
@@ -103,25 +106,6 @@ public class YunpianSmsClient extends AbstractSmsClient {
 | 
			
		||||
        return sendResult.getMsg() + " => " + sendResult.getDetail();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static SmsSendFailureTypeEnum parseSendFailureType(Result<SmsSingleSend> sendResult) {
 | 
			
		||||
        Integer code = sendResult.getCode();
 | 
			
		||||
        switch (code) {
 | 
			
		||||
            case OK: return null;
 | 
			
		||||
            case ARGUMENT_MISSING: return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR;
 | 
			
		||||
            case BAD_ARGUMENT_FORMAT: return SmsSendFailureTypeEnum.SMS_TEMPLATE_PARAM_ERROR;
 | 
			
		||||
            case TPL_NOT_FOUND: return SmsSendFailureTypeEnum.SMS_TEMPLATE_NOT_EXISTS;
 | 
			
		||||
            case TPL_NOT_VALID: return SmsSendFailureTypeEnum.SMS_TEMPLATE_INVALID;
 | 
			
		||||
        }
 | 
			
		||||
        return SmsSendFailureTypeEnum.SMS_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String getApiSerialNo(Result<SmsSingleSend> sendResult) {
 | 
			
		||||
        if (sendResult.getData() == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return String.valueOf(sendResult.getData().getSid());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 云片的比较复杂,又是加密又是套娃的
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.SUCCESS;
 | 
			
		||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*;
 | 
			
		||||
import static com.yunpian.sdk.constant.Code.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 云片的 SmsCodeMapping 实现类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public class YunpianSmsCodeMapping implements SmsCodeMapping {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ErrorCode apply(String apiCode) {
 | 
			
		||||
        int code = Integer.parseInt(apiCode);
 | 
			
		||||
        switch (code) {
 | 
			
		||||
            case OK: return SUCCESS;
 | 
			
		||||
            case ARGUMENT_MISSING: return SMS_API_PARAM_ERROR;
 | 
			
		||||
            case BAD_ARGUMENT_FORMAT: return SMS_TEMPLATE_PARAM_ERROR;
 | 
			
		||||
            case TPL_NOT_FOUND: return SMS_TEMPLATE_NOT_EXISTS;
 | 
			
		||||
            case TPL_NOT_VALID: return SMS_TEMPLATE_INVALID;
 | 
			
		||||
        }
 | 
			
		||||
        return SMS_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core;
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.enums;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信相关常量类
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.enums;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信框架的错误码枚举
 | 
			
		||||
 *
 | 
			
		||||
 * 短信框架,使用 2-001-000-000 段
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public interface SmsFrameworkErrorCodeConstants {
 | 
			
		||||
 | 
			
		||||
    // ========== 渠道相关 2001000100 ==========
 | 
			
		||||
    ErrorCode SMS_CHANNEL_CLIENT_NOT_EXISTS = new ErrorCode(2001000100, "短信渠道的客户端不存在");
 | 
			
		||||
    ErrorCode SMS_CHANNEL_API_KEY_MISSING = new ErrorCode(2001000101, "API Key 不存在");
 | 
			
		||||
    ErrorCode SMS_CHANNEL_PERMISSION_DENY = new ErrorCode(2001000102, "没有发送短信的权限");
 | 
			
		||||
 | 
			
		||||
    // ========== 模板相关(200 开头) ==========
 | 
			
		||||
    ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(200, "短信模板不存在");
 | 
			
		||||
    ErrorCode SMS_TEMPLATE_DISABLE = new ErrorCode(201, "短信模板被禁用"); // 例如说,我们在管理后台禁用了
 | 
			
		||||
    ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(202, "短信模板不可用"); // 例如说,短信模板正在审核中
 | 
			
		||||
    ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(203, "模板参数不正确");
 | 
			
		||||
 | 
			
		||||
    // ========== 其它相关(900 开头) ==========
 | 
			
		||||
    ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(900, "请求参数缺失");
 | 
			
		||||
 | 
			
		||||
    ErrorCode SMS_SEND_LIMIT_CONTROL = new ErrorCode(997, "业务限流"); // 将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。
 | 
			
		||||
    ErrorCode EXCEPTION = new ErrorCode(998, "调用异常");
 | 
			
		||||
    ErrorCode SMS_UNKNOWN = new ErrorCode(999, "未知错误,需要解析");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.enums;
 | 
			
		||||
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信的发送失败类型的枚举
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Getter
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public enum SmsSendFailureTypeEnum {
 | 
			
		||||
 | 
			
		||||
    // ========== 渠道相关(100 开头) ==========
 | 
			
		||||
    SMS_CHANNEL_CLIENT_NOT_EXISTS(100, "短信渠道的客户端不存在"),
 | 
			
		||||
    SMS_CHANNEL_API_KEY_MISSING(101, "API Key 不存在"),
 | 
			
		||||
    SMS_CHANNEL_PERMISSION_DENY(102, "没有发送短信的权限"),
 | 
			
		||||
 | 
			
		||||
    // ========== 模板相关(200 开头) ==========
 | 
			
		||||
    SMS_TEMPLATE_NOT_EXISTS(200, "短信模板不存在"),
 | 
			
		||||
    SMS_TEMPLATE_DISABLE(201, "短信模板被禁用"), // 例如说,我们在管理后台禁用了
 | 
			
		||||
    SMS_TEMPLATE_INVALID(202, "短信模板不可用"), // 例如说,短信模板正在审核中
 | 
			
		||||
    SMS_TEMPLATE_PARAM_ERROR(203, "模板参数不正确"),
 | 
			
		||||
 | 
			
		||||
    // ========== 其它相关(900 开头) ==========
 | 
			
		||||
    SMS_API_PARAM_ERROR(900, "请求参数缺失"),
 | 
			
		||||
 | 
			
		||||
    SMS_SEND_LIMIT_CONTROL(997, "业务限流"), // 将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。
 | 
			
		||||
    SMS_SEND_EXCEPTION(998, "发送异常"),
 | 
			
		||||
    SMS_UNKNOWN(999, "未知错误,需要解析")
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 失败类型
 | 
			
		||||
     */
 | 
			
		||||
    private final int type;
 | 
			
		||||
    /**
 | 
			
		||||
     * 失败提示
 | 
			
		||||
     */
 | 
			
		||||
    private final String msg;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,6 @@ package cn.iocoder.dashboard.framework.web.core.handler;
 | 
			
		||||
import cn.hutool.core.exceptions.ExceptionUtil;
 | 
			
		||||
import cn.hutool.core.map.MapUtil;
 | 
			
		||||
import cn.hutool.extra.servlet.ServletUtil;
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.GlobalException;
 | 
			
		||||
import cn.iocoder.dashboard.common.exception.ServiceException;
 | 
			
		||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService;
 | 
			
		||||
@@ -96,9 +95,6 @@ public class GlobalExceptionHandler {
 | 
			
		||||
        if (ex instanceof AccessDeniedException) {
 | 
			
		||||
            return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
 | 
			
		||||
        }
 | 
			
		||||
        if (ex instanceof GlobalException) {
 | 
			
		||||
            return globalExceptionHandler(request, (GlobalException) ex);
 | 
			
		||||
        }
 | 
			
		||||
        return defaultExceptionHandler(request, ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -222,25 +218,6 @@ public class GlobalExceptionHandler {
 | 
			
		||||
        return CommonResult.error(ex.getCode(), ex.getMessage());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理全局异常 ServiceException
 | 
			
		||||
     *
 | 
			
		||||
     * 例如说,Dubbo 请求超时,调用的 Dubbo 服务系统异常
 | 
			
		||||
     */
 | 
			
		||||
    @ExceptionHandler(value = GlobalException.class)
 | 
			
		||||
    public CommonResult<?> globalExceptionHandler(HttpServletRequest req, GlobalException ex) {
 | 
			
		||||
        // 系统异常时,才打印异常日志
 | 
			
		||||
        if (INTERNAL_SERVER_ERROR.getCode().equals(ex.getCode())) {
 | 
			
		||||
            // 插入异常日志
 | 
			
		||||
            this.createExceptionLog(req, ex);
 | 
			
		||||
        // 普通全局异常,打印 info 日志即可
 | 
			
		||||
        } else {
 | 
			
		||||
            log.info("[globalExceptionHandler]", ex);
 | 
			
		||||
        }
 | 
			
		||||
        // 返回 ERROR CommonResult
 | 
			
		||||
        return CommonResult.error(ex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理系统异常,兜底处理所有的一切
 | 
			
		||||
     */
 | 
			
		||||
@@ -250,7 +227,7 @@ public class GlobalExceptionHandler {
 | 
			
		||||
        // 插入异常日志
 | 
			
		||||
        this.createExceptionLog(req, ex);
 | 
			
		||||
        // 返回 ERROR CommonResult
 | 
			
		||||
        return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMessage());
 | 
			
		||||
        return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void createExceptionLog(HttpServletRequest req, Throwable e) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
package cn.iocoder.dashboard.modules.system.service.sms;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
 | 
			
		||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 
 | 
			
		||||
@@ -358,7 +358,7 @@ public class SysUserServiceImpl implements SysUserService {
 | 
			
		||||
            }
 | 
			
		||||
            // 如果存在,判断是否允许更新
 | 
			
		||||
            if (!isUpdateSupport) {
 | 
			
		||||
                respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMessage());
 | 
			
		||||
                respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            SysUserDO updateUser = SysUserConvert.INSTANCE.convert(importUser);
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ public class AssertUtils {
 | 
			
		||||
        ServiceException serviceException = assertThrows(ServiceException.class, executable);
 | 
			
		||||
        // 校验错误码
 | 
			
		||||
        Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配");
 | 
			
		||||
        String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMessage(), messageParams);
 | 
			
		||||
        String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams);
 | 
			
		||||
        Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user