diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsAliYunClient.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsAliYunClient.java index 745e4ce6a..7b2318fb1 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsAliYunClient.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsAliYunClient.java @@ -8,10 +8,14 @@ import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; +import lombok.Data; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -25,17 +29,48 @@ import java.util.Map; @Component public class SmsAliYunClient implements SmsClient { + private static final Logger LOGGER = LoggerFactory.getLogger(SmsAliYunClient.class); + + private static final String DOMAIN = "dysmsapi.aliyuncs.com"; + private static final String SUCCESS_CODE = "OK"; + private static final String SUCCESS_MESSAGE = "OK"; + /** + * 阿里云短信 - 批量推送最大数 500,支持 1000 + */ + private static final int MAX_BATCH_SIZE = 500; + @Value("${sms.aliYun.accessKeyId?:'default_value'}") private String accessKeyId; @Value("${sms.aliYun.accessSecret?:'default_value'}") private String accessSecret; - private static final String DOMAIN = "dysmsapi.aliyuncs.com"; + @Data + @Accessors(chain = true) + public static class Result { + /** + * 发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。 + */ + private String BizId; + /** + * 请求状态码。 + * + * - OK 蔡成功 + */ + private String Code; + /** + * 状态码的描述。 + */ + private String Message; + /** + * 请求ID。 + */ + private String RequestId; + } @Override public SendResult singleSend(String mobile, String sign, String templateCode, String template, Map templateParams) { - IAcsClient client = getClient(); + // params CommonRequest request = new CommonRequest(); request.setMethod(MethodType.POST); request.setDomain(DOMAIN); @@ -46,39 +81,74 @@ public class SmsAliYunClient implements SmsClient { request.putQueryParameter("TemplateCode", templateCode); request.putQueryParameter("TemplateParam", JSON.toJSONString(templateParams)); - try { - CommonResponse response = client.getCommonResponse(request); - System.out.println(response.getData()); - } catch (ClientException e) { - e.printStackTrace(); - } - return null; + // 发送请求 + return doSend(request); } @Override public SendResult batchSend(List mobileList, String sign, String templateCode, String template, Map templateParams) { + + // 最大发送数为 1000,我们设置为 500 个, 分段发送 + int maxSendSize = MAX_BATCH_SIZE; + int maxSendSizeCount = mobileList.size() % maxSendSize == 0 + ? mobileList.size() / maxSendSize + : mobileList.size() / maxSendSize + 1; + + SendResult sendResult = null; + for (int i = 0; i < maxSendSizeCount; i++) { + // 分批发送 + List batchSendMobile = mobileList + .subList(i * maxSendSize, (i + 1) * maxSendSize); + + // params + CommonRequest request = new CommonRequest(); + request.setMethod(MethodType.POST); + request.setDomain(DOMAIN); + request.setVersion("2017-05-25"); + request.setAction("SendBatchSms"); + request.putQueryParameter("PhoneNumberJson", JSON.toJSONString(batchSendMobile)); + request.putQueryParameter("SignNameJson", JSON.toJSONString(Collections.singletonList(sign))); + request.putQueryParameter("TemplateCode", templateCode); + request.putQueryParameter("TemplateParamJson", JSON.toJSONString(Collections.singletonList(templateParams))); + + // 发送请求 + sendResult = doSend(request); + } + return sendResult; + } + + private SendResult doSend(CommonRequest request) { // 获取 client IAcsClient client = getClient(); - - // params - CommonRequest request = new CommonRequest(); - request.setMethod(MethodType.POST); - request.setDomain(DOMAIN); - request.setVersion("2017-05-25"); - request.setAction("SendBatchSms"); - request.putQueryParameter("PhoneNumberJson", JSON.toJSONString(mobileList)); - request.putQueryParameter("SignNameJson", JSON.toJSONString(Collections.singletonList(sign))); - request.putQueryParameter("TemplateCode", templateCode); - request.putQueryParameter("TemplateParamJson", JSON.toJSONString(Collections.singletonList(templateParams))); - try { CommonResponse response = client.getCommonResponse(request); - System.out.println(response.getData()); + Result result = JSON.parseObject(response.getData(), Result.class); + if (!SUCCESS_CODE.equals(result.getCode())) { + + LOGGER.info("发送验证码失败 params {} res {}", JSON.toJSON(request), JSON.toJSON(result)); + + // 错误发送失败 + return new SendResult() + .setIsSuccess(false) + .setCode(SendResult.ERROR_CODE) + .setMessage(result.getMessage()); + } else { + LOGGER.info("发送验证码失败 params {} res", JSON.toJSON(request), JSON.toJSON(result)); + + // 发送成功 + return new SendResult() + .setIsSuccess(true) + .setCode(SendResult.SUCCESS_CODE) + .setMessage(result.getMessage()); + } } catch (ClientException e) { - e.printStackTrace(); + LOGGER.error("发送验证码异常 {}", ExceptionUtils.getMessage(e)); + return new SendResult() + .setIsSuccess(false) + .setCode(SendResult.ERROR_CODE) + .setMessage(ExceptionUtils.getMessage(e)); } - return null; } /** diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsClient.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsClient.java index 0d888c59a..9ad07b566 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsClient.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsClient.java @@ -14,15 +14,28 @@ import java.util.Map; */ public interface SmsClient { + + @Data @Accessors(chain = true) class SendResult { - private Boolean isSuccess; + public static final int SUCCESS_CODE = 0; + public static final int ERROR_CODE = 1; + public static final String SUCCESS_MESSAGE = "SUCCESS"; + /** + * 错误码 + */ private Integer code; - + /** + * 错误信息 + */ private String message; + /** + * 是否成功 + */ + private Boolean isSuccess; } /** diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsYunPianClient.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsYunPianClient.java index 38c87d60f..e9b56f510 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsYunPianClient.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/client/SmsYunPianClient.java @@ -36,6 +36,7 @@ public class SmsYunPianClient implements SmsClient { protected static final Logger LOGGER = LoggerFactory.getLogger(SmsYunPianClient.class); private static final int SUCCESS_CODE = 0; + private static final String SUCCESS_MESSAGE = "SUCCESS"; /** * 云片短信 - 批量推送最大数 500,支持 1000 @@ -121,13 +122,17 @@ public class SmsYunPianClient implements SmsClient { } @Override - public SendResult batchSend(List mobileList, String sign, String templateCode, String template, Map templateParams) { + public SendResult batchSend(List mobileList, String sign, + String templateCode, String template, + Map templateParams) { // build 模板 template = buildTemplate(sign, template, templateParams); // 最大发送数为 1000,我们设置为 500 个, 分段发送 int maxSendSize = MAX_BATCH_SIZE; - int maxSendSizeCount = mobileList.size() % maxSendSize; + int maxSendSizeCount = mobileList.size() % maxSendSize == 0 + ? mobileList.size() / maxSendSize + : mobileList.size() / maxSendSize + 1; int j = 0; int j2 = mobileList.size(); @@ -163,7 +168,7 @@ public class SmsYunPianClient implements SmsClient { return new SendResult() .setIsSuccess(true) .setCode(SUCCESS_CODE) - .setMessage(null); + .setMessage(SUCCESS_MESSAGE); } /** @@ -181,8 +186,6 @@ public class SmsYunPianClient implements SmsClient { return template; } - LOGGER.debug("模板构建 before -> {}", template); - for (Map.Entry entry : templateParams.entrySet()) { String paramsKey = entry.getKey(); String value = entry.getValue(); @@ -191,7 +194,6 @@ public class SmsYunPianClient implements SmsClient { } template = String.format(SIGN_TEMPLATE, sign, template); - LOGGER.debug("模板构建 after -> {}", template); return template; } @@ -204,8 +206,6 @@ public class SmsYunPianClient implements SmsClient { */ public static String post(String url, Map paramsMap) { - - // TODO: 2019/5/25 Sin 这个地方需要 记录日志 CloseableHttpClient client = HttpClients.createDefault(); String responseText = ""; CloseableHttpResponse response = null; diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSendMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSendMapper.java new file mode 100644 index 000000000..e94de81c1 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSendMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.admin.dao; + +import cn.iocoder.mall.admin.dataobject.SmsSendLogDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + * 短信 + * + * @author Sin + * @time 2019/5/16 6:18 PM + */ +@Repository +public interface SmsSendMapper extends BaseMapper { +} diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsClientLog.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSendLogDO.java similarity index 83% rename from system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsClientLog.java rename to system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSendLogDO.java index 5eb7874ea..3cf2b3326 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsClientLog.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSendLogDO.java @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class SmsClientLog extends BaseDO { +public class SmsSendLogDO extends BaseDO { /** * 编号 @@ -26,6 +26,10 @@ public class SmsClientLog extends BaseDO { * 短信 */ private String template; + /** + * 参数 + */ + private String params; /** * 发送信息 */ diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java index 52834143a..70bce07b1 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java @@ -12,11 +12,14 @@ import cn.iocoder.mall.admin.api.constant.SmsApplyStatusEnum; import cn.iocoder.mall.admin.api.constant.SmsPlatformEnum; import cn.iocoder.mall.admin.api.dto.sms.PageQuerySmsSignDTO; import cn.iocoder.mall.admin.api.dto.sms.PageQuerySmsTemplateDTO; +import cn.iocoder.mall.admin.client.SmsAliYunClient; import cn.iocoder.mall.admin.client.SmsClient; import cn.iocoder.mall.admin.convert.SmsSignConvert; import cn.iocoder.mall.admin.convert.SmsTemplateConvert; +import cn.iocoder.mall.admin.dao.SmsSendMapper; import cn.iocoder.mall.admin.dao.SmsSignMapper; import cn.iocoder.mall.admin.dao.SmsTemplateMapper; +import cn.iocoder.mall.admin.dataobject.SmsSendLogDO; import cn.iocoder.mall.admin.dataobject.SmsSignDO; import cn.iocoder.mall.admin.dataobject.SmsTemplateDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -47,6 +50,8 @@ public class SmsServiceImpl implements SmsService { private SmsSignMapper smsSignMapper; @Autowired private SmsTemplateMapper smsTemplateMapper; + @Autowired + private SmsSendMapper smsSendMapper; @Autowired @Qualifier("smsYunPianClient") @@ -349,8 +354,17 @@ public class SmsServiceImpl implements SmsService { // 获取 client SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); // 发送短信 - smsClient.singleSend(mobile, smsSignDO.getSign(), + SmsClient.SendResult sendResult = smsClient.singleSend(mobile, smsSignDO.getSign(), smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); + + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage(sendResult.getMessage()) + .setCreateTime(new Date()) + ); } @Override @@ -368,15 +382,34 @@ public class SmsServiceImpl implements SmsService { new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); if (smsSignDO == null) { + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage("发送成功!") + .setCreateTime(new Date()) + ); + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } // 获取 client SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); + // 发送短信 - smsClient.batchSend(mobileList, smsSignDO.getSign(), + SmsClient.SendResult sendResult = smsClient.batchSend(mobileList, smsSignDO.getSign(), smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); + + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage(sendResult.getMessage()) + .setCreateTime(new Date()) + ); } /**