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,8 +60,12 @@ public class SmsResult implements Serializable { | ||
| 60 | 60 | ||
| 61 | public static SmsResult success(SmsSendFailureTypeEnum sendFailureType, | 61 | public static SmsResult success(SmsSendFailureTypeEnum sendFailureType, |
| 62 | String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { | 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 | public static SmsResult error(Throwable ex) { | 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,14 +2,20 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | import cn.hutool.core.date.DateUtil; | 4 | import cn.hutool.core.date.DateUtil; |
| 5 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | import cn.iocoder.dashboard.framework.sms.core.SmsResult; | 6 | import cn.iocoder.dashboard.framework.sms.core.SmsResult; |
| 6 | import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail; | 7 | import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail; |
| 7 | import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; | 8 | import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; |
| 9 | +import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum; | ||
| 8 | import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; | 10 | import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; |
| 9 | import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; | 11 | import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; |
| 10 | import cn.iocoder.dashboard.util.json.JsonUtils; | 12 | import cn.iocoder.dashboard.util.json.JsonUtils; |
| 11 | import com.aliyuncs.DefaultAcsClient; | 13 | import com.aliyuncs.DefaultAcsClient; |
| 12 | import com.aliyuncs.IAcsClient; | 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 | import com.aliyuncs.profile.DefaultProfile; | 19 | import com.aliyuncs.profile.DefaultProfile; |
| 14 | import com.aliyuncs.profile.IClientProfile; | 20 | import com.aliyuncs.profile.IClientProfile; |
| 15 | import com.fasterxml.jackson.core.type.TypeReference; | 21 | import com.fasterxml.jackson.core.type.TypeReference; |
| @@ -36,8 +42,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -36,8 +42,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 36 | private static final String DOMAIN = "dysmsapi.aliyuncs.com"; | 42 | private static final String DOMAIN = "dysmsapi.aliyuncs.com"; |
| 37 | private static final String ENDPOINT = "cn-hangzhou"; | 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,29 +60,44 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 56 | 60 | ||
| 57 | @Override | 61 | @Override |
| 58 | protected SmsResult doSend(Long sendLogId, String mobile, String apiTemplateId, Map<String, Object> templateParams) throws Exception { | 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,10 +106,11 @@ public class YunpianSmsClient extends AbstractSmsClient { | ||
| 106 | private static SmsSendFailureTypeEnum parseSendFailureType(Result<SmsSingleSend> sendResult) { | 106 | private static SmsSendFailureTypeEnum parseSendFailureType(Result<SmsSingleSend> sendResult) { |
| 107 | Integer code = sendResult.getCode(); | 107 | Integer code = sendResult.getCode(); |
| 108 | switch (code) { | 108 | switch (code) { |
| 109 | + case OK: return null; | ||
| 109 | case ARGUMENT_MISSING: return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR; | 110 | case ARGUMENT_MISSING: return SmsSendFailureTypeEnum.SMS_API_PARAM_ERROR; |
| 110 | case BAD_ARGUMENT_FORMAT: return SmsSendFailureTypeEnum.SMS_TEMPLATE_PARAM_ERROR; | 111 | case BAD_ARGUMENT_FORMAT: return SmsSendFailureTypeEnum.SMS_TEMPLATE_PARAM_ERROR; |
| 111 | case TPL_NOT_FOUND: return SmsSendFailureTypeEnum.SMS_TEMPLATE_NOT_EXISTS; | 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 | return SmsSendFailureTypeEnum.SMS_UNKNOWN; | 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,16 +14,19 @@ public enum SmsSendFailureTypeEnum { | ||
| 14 | 14 | ||
| 15 | // ========== 渠道相关(100 开头) ========== | 15 | // ========== 渠道相关(100 开头) ========== |
| 16 | SMS_CHANNEL_CLIENT_NOT_EXISTS(100, "短信渠道的客户端不存在"), | 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 | // ========== 模板相关(200 开头) ========== | 20 | // ========== 模板相关(200 开头) ========== |
| 19 | SMS_TEMPLATE_NOT_EXISTS(200, "短信模板不存在"), | 21 | SMS_TEMPLATE_NOT_EXISTS(200, "短信模板不存在"), |
| 20 | SMS_TEMPLATE_DISABLE(201, "短信模板被禁用"), // 例如说,我们在管理后台禁用了 | 22 | SMS_TEMPLATE_DISABLE(201, "短信模板被禁用"), // 例如说,我们在管理后台禁用了 |
| 21 | - SMS_TMPLATE_INVALID(202, "短信模板不可用"), // 例如说,短信模板正在审核中 | 23 | + SMS_TEMPLATE_INVALID(202, "短信模板不可用"), // 例如说,短信模板正在审核中 |
| 22 | SMS_TEMPLATE_PARAM_ERROR(203, "模板参数不正确"), | 24 | SMS_TEMPLATE_PARAM_ERROR(203, "模板参数不正确"), |
| 23 | 25 | ||
| 24 | // ========== 其它相关(900 开头) ========== | 26 | // ========== 其它相关(900 开头) ========== |
| 25 | SMS_API_PARAM_ERROR(900, "请求参数缺失"), | 27 | SMS_API_PARAM_ERROR(900, "请求参数缺失"), |
| 26 | 28 | ||
| 29 | + SMS_SEND_LIMIT_CONTROL(997, "业务限流"), // 将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 | ||
| 27 | SMS_SEND_EXCEPTION(998, "发送异常"), | 30 | SMS_SEND_EXCEPTION(998, "发送异常"), |
| 28 | SMS_UNKNOWN(999, "未知错误,需要解析") | 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 | +} |