Commit 60911c9f56058ced79a55af6a8cbfa29a7fdf0bf
1 parent
52b51254
阿里云短信的调试
Showing
5 changed files
with
91 additions
and
27 deletions
src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java
| ... | ... | @@ -60,8 +60,12 @@ public class SmsResult implements Serializable { |
| 60 | 60 | |
| 61 | 61 | public static SmsResult success(SmsSendFailureTypeEnum sendFailureType, |
| 62 | 62 | String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { |
| 63 | - return new SmsResult().setSuccess(true).setSendFailureType(sendFailureType.getType()).setSendFailureMsg(sendFailureType.getMsg()) | |
| 64 | - .setApiSendCode(apiSendCode).setApiSendMsg(apiSendMsg).setApiRequestId(apiRequestId).setApiSerialNo(apiSerialNo); | |
| 63 | + SmsResult result = new SmsResult().setSuccess(true).setApiSendCode(apiSendCode).setApiSendMsg(apiSendMsg) | |
| 64 | + .setApiRequestId(apiRequestId).setApiSerialNo(apiSerialNo); | |
| 65 | + if (sendFailureType != null) { | |
| 66 | + result.setSendFailureType(sendFailureType.getType()).setSendFailureMsg(sendFailureType.getMsg()); | |
| 67 | + } | |
| 68 | + return result; | |
| 65 | 69 | } |
| 66 | 70 | |
| 67 | 71 | public static SmsResult error(Throwable ex) { | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java
| ... | ... | @@ -2,14 +2,20 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | 4 | import cn.hutool.core.date.DateUtil; |
| 5 | +import cn.hutool.core.util.StrUtil; | |
| 5 | 6 | import cn.iocoder.dashboard.framework.sms.core.SmsResult; |
| 6 | 7 | import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail; |
| 7 | 8 | import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; |
| 9 | +import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum; | |
| 8 | 10 | import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; |
| 9 | 11 | import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; |
| 10 | 12 | import cn.iocoder.dashboard.util.json.JsonUtils; |
| 11 | 13 | import com.aliyuncs.DefaultAcsClient; |
| 12 | 14 | import com.aliyuncs.IAcsClient; |
| 15 | +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; | |
| 16 | +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; | |
| 17 | +import com.aliyuncs.exceptions.ClientException; | |
| 18 | +import com.aliyuncs.http.MethodType; | |
| 13 | 19 | import com.aliyuncs.profile.DefaultProfile; |
| 14 | 20 | import com.aliyuncs.profile.IClientProfile; |
| 15 | 21 | import com.fasterxml.jackson.core.type.TypeReference; |
| ... | ... | @@ -36,8 +42,6 @@ public class AliyunSmsClient extends AbstractSmsClient { |
| 36 | 42 | private static final String DOMAIN = "dysmsapi.aliyuncs.com"; |
| 37 | 43 | private static final String ENDPOINT = "cn-hangzhou"; |
| 38 | 44 | |
| 39 | - private static final String OK = "OK"; | |
| 40 | - | |
| 41 | 45 | /** |
| 42 | 46 | * 阿里云客户端 |
| 43 | 47 | */ |
| ... | ... | @@ -56,29 +60,44 @@ public class AliyunSmsClient extends AbstractSmsClient { |
| 56 | 60 | |
| 57 | 61 | @Override |
| 58 | 62 | protected SmsResult doSend(Long sendLogId, String mobile, String apiTemplateId, Map<String, Object> templateParams) throws Exception { |
| 59 | - return null; | |
| 63 | + // 构建参数 | |
| 64 | + SendSmsRequest request = new SendSmsRequest(); | |
| 65 | + request.setSysMethod(MethodType.POST); | |
| 66 | + request.setPhoneNumbers(mobile); | |
| 67 | + request.setSignName(properties.getSignature()); | |
| 68 | + request.setTemplateCode(apiTemplateId); | |
| 69 | + request.setTemplateParam(JsonUtils.toJsonString(templateParams)); | |
| 70 | + request.setOutId(String.valueOf(sendLogId)); | |
| 71 | + | |
| 72 | + try { | |
| 73 | + // 执行发送 | |
| 74 | + SendSmsResponse sendResult = acsClient.getAcsResponse(request); | |
| 75 | + // 解析结果 | |
| 76 | + return SmsResult.success(parseSendFailureType(sendResult.getCode()), // 将 API 短信平台,解析成统一的错误码 | |
| 77 | + sendResult.getCode(), sendResult.getMessage(), sendResult.getRequestId(), sendResult.getBizId()); | |
| 78 | + } catch (ClientException ex) { | |
| 79 | + return SmsResult.success(parseSendFailureType(ex.getErrCode()), // 将 API 短信平台,解析成统一的错误码 | |
| 80 | + ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null); | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + private static SmsSendFailureTypeEnum parseSendFailureType(String code) { | |
| 85 | + switch (code) { | |
| 86 | + case "OK": return null; | |
| 87 | + case "MissingAccessKeyId": return SmsSendFailureTypeEnum.SMS_CHANNEL_API_KEY_MISSING; | |
| 88 | + case "isp.RAM_PERMISSION_DENY": return SmsSendFailureTypeEnum.SMS_CHANNEL_PERMISSION_DENY; | |
| 89 | + case "isv.INVALID_PARAMETERS": return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR; | |
| 90 | + case "isv.BUSINESS_LIMIT_CONTROL": return SmsSendFailureTypeEnum.SMS_SEND_LIMIT_CONTROL; | |
| 91 | + } | |
| 92 | + return SmsSendFailureTypeEnum.SMS_UNKNOWN; | |
| 60 | 93 | } |
| 61 | 94 | |
| 62 | -// @Override | |
| 63 | -// public SmsResult doSend(String templateApiId, SmsBody smsBody, String targetPhone) throws Exception { | |
| 64 | -// SendSmsRequest request = new SendSmsRequest(); | |
| 65 | -// request.setSysMethod(MethodType.POST); | |
| 66 | -// request.setPhoneNumbers(targetPhone); | |
| 67 | -// request.setSignName(properties.getSignature()); | |
| 68 | -// request.setTemplateCode(templateApiId); | |
| 69 | -// request.setTemplateParam(smsBody.getParamsStr()); | |
| 70 | -// SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); | |
| 71 | -// | |
| 72 | -// boolean success = OK.equals(sendSmsResponse.getCode()); | |
| 73 | -// if (!success) { | |
| 74 | -// log.debug("send fail[code={}, message={}]", sendSmsResponse.getCode(), sendSmsResponse.getMessage()); | |
| 75 | -// } | |
| 76 | -// return new SmsResult() | |
| 77 | -// .setSuccess(success) | |
| 78 | -// .setMessage(sendSmsResponse.getMessage()) | |
| 79 | -// .setCode(sendSmsResponse.getCode()) | |
| 80 | -// .setApiId(sendSmsResponse.getBizId()); | |
| 81 | -// } | |
| 95 | + private static String formatResultMsg(ClientException ex) { | |
| 96 | + if (StrUtil.isEmpty(ex.getErrorDescription())) { | |
| 97 | + return ex.getMessage(); | |
| 98 | + } | |
| 99 | + return ex.getErrMsg() + " => " + ex.getErrorDescription(); | |
| 100 | + } | |
| 82 | 101 | |
| 83 | 102 | /** |
| 84 | 103 | * [{ | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java
| ... | ... | @@ -106,10 +106,11 @@ public class YunpianSmsClient extends AbstractSmsClient { |
| 106 | 106 | private static SmsSendFailureTypeEnum parseSendFailureType(Result<SmsSingleSend> sendResult) { |
| 107 | 107 | Integer code = sendResult.getCode(); |
| 108 | 108 | switch (code) { |
| 109 | + case OK: return null; | |
| 109 | 110 | case ARGUMENT_MISSING: return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR; |
| 110 | 111 | case BAD_ARGUMENT_FORMAT: return SmsSendFailureTypeEnum.SMS_TEMPLATE_PARAM_ERROR; |
| 111 | 112 | case TPL_NOT_FOUND: return SmsSendFailureTypeEnum.SMS_TEMPLATE_NOT_EXISTS; |
| 112 | - case TPL_NOT_VALID: return SmsSendFailureTypeEnum.SMS_TMPLATE_INVALID; | |
| 113 | + case TPL_NOT_VALID: return SmsSendFailureTypeEnum.SMS_TEMPLATE_INVALID; | |
| 113 | 114 | } |
| 114 | 115 | return SmsSendFailureTypeEnum.SMS_UNKNOWN; |
| 115 | 116 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsSendFailureTypeEnum.java
| ... | ... | @@ -14,16 +14,19 @@ public enum SmsSendFailureTypeEnum { |
| 14 | 14 | |
| 15 | 15 | // ========== 渠道相关(100 开头) ========== |
| 16 | 16 | SMS_CHANNEL_CLIENT_NOT_EXISTS(100, "短信渠道的客户端不存在"), |
| 17 | + SMS_CHANNEL_API_KEY_MISSING(101, "API Key 不存在"), | |
| 18 | + SMS_CHANNEL_PERMISSION_DENY(102, "没有发送短信的权限"), | |
| 17 | 19 | |
| 18 | 20 | // ========== 模板相关(200 开头) ========== |
| 19 | 21 | SMS_TEMPLATE_NOT_EXISTS(200, "短信模板不存在"), |
| 20 | 22 | SMS_TEMPLATE_DISABLE(201, "短信模板被禁用"), // 例如说,我们在管理后台禁用了 |
| 21 | - SMS_TMPLATE_INVALID(202, "短信模板不可用"), // 例如说,短信模板正在审核中 | |
| 23 | + SMS_TEMPLATE_INVALID(202, "短信模板不可用"), // 例如说,短信模板正在审核中 | |
| 22 | 24 | SMS_TEMPLATE_PARAM_ERROR(203, "模板参数不正确"), |
| 23 | 25 | |
| 24 | 26 | // ========== 其它相关(900 开头) ========== |
| 25 | 27 | SMS_API_PARAM_ERROR(900, "请求参数缺失"), |
| 26 | 28 | |
| 29 | + SMS_SEND_LIMIT_CONTROL(997, "业务限流"), // 将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 | |
| 27 | 30 | SMS_SEND_EXCEPTION(998, "发送异常"), |
| 28 | 31 | SMS_UNKNOWN(999, "未知错误,需要解析") |
| 29 | 32 | ; | ... | ... |
src/test-integration/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.SmsResult; | |
| 4 | +import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; | |
| 5 | +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; | |
| 6 | +import org.junit.jupiter.api.Test; | |
| 7 | + | |
| 8 | +import java.util.HashMap; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * {@link AliyunSmsClient} 的集成测试 | |
| 13 | + */ | |
| 14 | +public class AliyunSmsClientTest { | |
| 15 | + | |
| 16 | + @Test | |
| 17 | + public void testSend() { | |
| 18 | + // 创建配置类 | |
| 19 | + SmsChannelProperties properties = new SmsChannelProperties(); | |
| 20 | + properties.setId(1L); | |
| 21 | + properties.setSignature("Ballcat"); | |
| 22 | + properties.setCode(SmsChannelEnum.ALIYUN.getCode()); | |
| 23 | + properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY")); | |
| 24 | + properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY")); | |
| 25 | + // 创建客户端 | |
| 26 | + AliyunSmsClient smsClient = new AliyunSmsClient(properties); | |
| 27 | + smsClient.init(); | |
| 28 | + // 发送短信 | |
| 29 | + Map<String, Object> templateParams = new HashMap<>(); | |
| 30 | + templateParams.put("code", "1024"); | |
| 31 | +// templateParams.put("operation", "嘿嘿"); | |
| 32 | +// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); | |
| 33 | + SmsResult result = smsClient.send(1L, "15601691399", "SMS_207945135", templateParams); | |
| 34 | + System.out.println(result); | |
| 35 | + } | |
| 36 | + | |
| 37 | +} | ... | ... |