mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	1. 阿里云 sms client 增加查询模板的封装
2. 重构阿里云 sms client 客户端,增加 invoke 基础方法
This commit is contained in:
		@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client;
 | 
			
		||||
import cn.iocoder.dashboard.common.core.KeyValue;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@@ -41,4 +42,12 @@ public interface SmsClient {
 | 
			
		||||
     */
 | 
			
		||||
    List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询指定的短信模板
 | 
			
		||||
     *
 | 
			
		||||
     * @param apiTemplateId 短信 API 的模板编号
 | 
			
		||||
     * @return 短信模板
 | 
			
		||||
     */
 | 
			
		||||
    SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,33 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信模板 Response DTO
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class SmsTemplateRespDTO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 模板编号
 | 
			
		||||
     */
 | 
			
		||||
    private String id;
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信内容
 | 
			
		||||
     */
 | 
			
		||||
    private String content;
 | 
			
		||||
    /**
 | 
			
		||||
     * 审核状态
 | 
			
		||||
     *
 | 
			
		||||
     * 枚举 {@link SmsTemplateAuditStatusEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer auditStatus;
 | 
			
		||||
    /**
 | 
			
		||||
     * 审核未通过的理由
 | 
			
		||||
     */
 | 
			
		||||
    private String auditReason;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -6,6 +6,7 @@ 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.dto.SmsReceiveRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
@@ -77,7 +78,7 @@ public abstract class AbstractSmsClient implements SmsClient {
 | 
			
		||||
            result = doSendSms(logId, mobile, apiTemplateId, templateParams);
 | 
			
		||||
        } catch (Throwable ex) {
 | 
			
		||||
            // 打印异常日志
 | 
			
		||||
            log.error("[send][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
 | 
			
		||||
            log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
 | 
			
		||||
                    logId, mobile, apiTemplateId, templateParams, ex);
 | 
			
		||||
            // 封装返回
 | 
			
		||||
            return SmsCommonResult.error(ex);
 | 
			
		||||
@@ -101,4 +102,21 @@ public abstract class AbstractSmsClient implements SmsClient {
 | 
			
		||||
 | 
			
		||||
    protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId) {
 | 
			
		||||
        // 执行短信发送
 | 
			
		||||
        SmsCommonResult<SmsTemplateRespDTO> result;
 | 
			
		||||
        try {
 | 
			
		||||
            result = doGetSmsTemplate(apiTemplateId);
 | 
			
		||||
        } catch (Throwable ex) {
 | 
			
		||||
            // 打印异常日志
 | 
			
		||||
            log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex);
 | 
			
		||||
            // 封装返回
 | 
			
		||||
            return SmsCommonResult.error(ex);
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,25 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.lang.Assert;
 | 
			
		||||
import cn.hutool.core.util.ReflectUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.dashboard.common.core.KeyValue;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import cn.iocoder.dashboard.util.collection.MapUtils;
 | 
			
		||||
import cn.iocoder.dashboard.util.json.JsonUtils;
 | 
			
		||||
import com.aliyuncs.AcsRequest;
 | 
			
		||||
import com.aliyuncs.AcsResponse;
 | 
			
		||||
import com.aliyuncs.DefaultAcsClient;
 | 
			
		||||
import com.aliyuncs.IAcsClient;
 | 
			
		||||
import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
 | 
			
		||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
 | 
			
		||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
 | 
			
		||||
import com.aliyuncs.exceptions.ClientException;
 | 
			
		||||
import com.aliyuncs.http.MethodType;
 | 
			
		||||
import com.aliyuncs.profile.DefaultProfile;
 | 
			
		||||
import com.aliyuncs.profile.IClientProfile;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonFormat;
 | 
			
		||||
@@ -25,6 +29,8 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 | 
			
		||||
@@ -66,25 +72,13 @@ public class AliyunSmsClient extends AbstractSmsClient {
 | 
			
		||||
                                                        String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
 | 
			
		||||
        // 构建参数
 | 
			
		||||
        SendSmsRequest request = new SendSmsRequest();
 | 
			
		||||
        request.setSysMethod(MethodType.POST);
 | 
			
		||||
        request.setPhoneNumbers(mobile);
 | 
			
		||||
        request.setSignName(properties.getSignature());
 | 
			
		||||
        request.setTemplateCode(apiTemplateId);
 | 
			
		||||
        request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams)));
 | 
			
		||||
        request.setOutId(String.valueOf(sendLogId));
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // 执行发送
 | 
			
		||||
            SendSmsResponse sendResult = acsClient.getAcsResponse(request);
 | 
			
		||||
            // 解析结果
 | 
			
		||||
            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.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
 | 
			
		||||
        }
 | 
			
		||||
        // 执行请求
 | 
			
		||||
        return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String formatResultMsg(ClientException ex) {
 | 
			
		||||
@@ -107,6 +101,48 @@ public class AliyunSmsClient extends AbstractSmsClient {
 | 
			
		||||
        }).collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
 | 
			
		||||
        // 构建参数
 | 
			
		||||
        QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
 | 
			
		||||
        request.setTemplateCode(apiTemplateId);
 | 
			
		||||
        // 执行请求
 | 
			
		||||
        return invoke(request, response -> {
 | 
			
		||||
            SmsTemplateRespDTO data = new SmsTemplateRespDTO();
 | 
			
		||||
            data.setId(response.getTemplateCode()).setContent(response.getTemplateContent());
 | 
			
		||||
            data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason());
 | 
			
		||||
            return data;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
 | 
			
		||||
        switch (templateStatus) {
 | 
			
		||||
            case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
 | 
			
		||||
            case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
 | 
			
		||||
            case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
 | 
			
		||||
            default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> consumer) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射
 | 
			
		||||
            T sendResult = acsClient.getAcsResponse(request);
 | 
			
		||||
            String code = (String) ReflectUtil.getFieldValue(sendResult, "code");
 | 
			
		||||
            String message = (String) ReflectUtil.getFieldValue(sendResult, "message");
 | 
			
		||||
            String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId");
 | 
			
		||||
            // 解析结果
 | 
			
		||||
            R data = null;
 | 
			
		||||
            if (Objects.equals(code, "OK")) { // 请求成功的情况下
 | 
			
		||||
                data = consumer.apply(sendResult);
 | 
			
		||||
            }
 | 
			
		||||
            // 拼接结果
 | 
			
		||||
            return SmsCommonResult.build(code, message, requestId, data, codeMapping);
 | 
			
		||||
        } catch (ClientException ex) {
 | 
			
		||||
            return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信接收状态
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping {
 | 
			
		||||
            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;
 | 
			
		||||
            case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_NOT_EXISTS;
 | 
			
		||||
        }
 | 
			
		||||
        return SMS_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import cn.iocoder.dashboard.common.core.KeyValue;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import cn.iocoder.dashboard.util.json.JsonUtils;
 | 
			
		||||
@@ -114,6 +115,11 @@ public class YunpianSmsClient extends AbstractSmsClient {
 | 
			
		||||
        }).collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信接收状态
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
package cn.iocoder.dashboard.framework.sms.core.enums;
 | 
			
		||||
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信模板的审核状态枚举
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
@Getter
 | 
			
		||||
public enum SmsTemplateAuditStatusEnum {
 | 
			
		||||
 | 
			
		||||
    CHECKING(1),
 | 
			
		||||
    SUCCESS(2),
 | 
			
		||||
    FAIL(3);
 | 
			
		||||
 | 
			
		||||
    private final Integer status;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,8 +3,10 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
 | 
			
		||||
import cn.iocoder.dashboard.common.core.KeyValue;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
 | 
			
		||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 | 
			
		||||
import org.junit.jupiter.api.BeforeAll;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
@@ -15,8 +17,10 @@ import java.util.List;
 | 
			
		||||
 */
 | 
			
		||||
public class AliyunSmsClientIntegrationTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSend() {
 | 
			
		||||
    private static AliyunSmsClient smsClient;
 | 
			
		||||
 | 
			
		||||
    @BeforeAll
 | 
			
		||||
    public static void before() {
 | 
			
		||||
        // 创建配置类
 | 
			
		||||
        SmsChannelProperties properties = new SmsChannelProperties();
 | 
			
		||||
        properties.setId(1L);
 | 
			
		||||
@@ -25,14 +29,25 @@ public class AliyunSmsClientIntegrationTest {
 | 
			
		||||
        properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY"));
 | 
			
		||||
        properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY"));
 | 
			
		||||
        // 创建客户端
 | 
			
		||||
        AliyunSmsClient smsClient = new AliyunSmsClient(properties);
 | 
			
		||||
        smsClient = new AliyunSmsClient(properties);
 | 
			
		||||
        smsClient.init();
 | 
			
		||||
        // 发送短信
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSendSms() {
 | 
			
		||||
        List<KeyValue<String, Object>> templateParams = new ArrayList<>();
 | 
			
		||||
        templateParams.add(new KeyValue<>("code", "1024"));
 | 
			
		||||
//        templateParams.put("operation", "嘿嘿");
 | 
			
		||||
//        SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
 | 
			
		||||
        SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "SMS_207945135", templateParams);
 | 
			
		||||
        SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399",
 | 
			
		||||
                "SMS_207945135", templateParams);
 | 
			
		||||
        System.out.println(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetSmsTemplate() {
 | 
			
		||||
        String apiTemplateId = "SMS_2079451351";
 | 
			
		||||
        SmsCommonResult<SmsTemplateRespDTO> result = smsClient.getSmsTemplate(apiTemplateId);
 | 
			
		||||
        System.out.println(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user