REQ-2411: 发送短信, 限制发送重复内容
This commit is contained in:
parent
f3508208e2
commit
507aee4112
@ -2,6 +2,7 @@ package cn.axzo.msg.center.domain.entity;
|
||||
|
||||
import cn.axzo.msg.center.domain.persistence.BaseOwnEntity;
|
||||
import cn.axzo.trade.datasecurity.core.annotation.CryptField;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@ -129,4 +130,8 @@ public class MNSMessage extends BaseOwnEntity<MNSMessage> {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package cn.axzo.msg.center.domain.entity;
|
||||
|
||||
import cn.axzo.msg.center.domain.enums.YesNoEnum;
|
||||
import cn.axzo.msg.center.domain.persistence.BaseOwnEntity;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@ -79,6 +80,11 @@ public class MNSMessageTemplate extends BaseOwnEntity<MNSMessageTemplate> {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
|
||||
public boolean hasParam() {
|
||||
return YesNoEnum.YES.getCode().equals(hasParam);
|
||||
}
|
||||
|
||||
@ -184,8 +184,11 @@ public class AliYunSmsClientImpl implements AliYunSmsClient {
|
||||
String message = responseBody.getMessage();
|
||||
boolean isRateLimited = message != null && message.contains("触发") && message.contains("流控");
|
||||
log.warn("AliyunSmsService#checkResponse is fail, error message : {}", message);
|
||||
if (!isRateLimited)
|
||||
if (isRateLimited) {
|
||||
throw new RateLimitException(ReturnCodeEnum.SYSTEM_ERROR, message);
|
||||
} else {
|
||||
throw new BizException(ReturnCodeEnum.SYSTEM_ERROR, message);
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package cn.axzo.msg.center.notices.integration.client.impl;
|
||||
|
||||
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
|
||||
import cn.axzo.msg.center.notices.common.exception.BizException;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public class RateLimitException extends BizException {
|
||||
|
||||
public RateLimitException(ReturnCodeEnum returnCode, String message) {
|
||||
super(returnCode, message);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.notices.manager.api.dto.request;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -48,4 +49,14 @@ public class MnsRequestDto {
|
||||
*/
|
||||
private String expansion;
|
||||
|
||||
private Object internalObj;
|
||||
|
||||
public <T> T getInternalObj(Class<T> clazz) {
|
||||
return clazz.isInstance(internalObj) ? clazz.cast(internalObj) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ public class MNSNoticesApiImpl implements MNSNoticesApi {
|
||||
BeanUtils.copyProperties(request, mnsRequestDto);
|
||||
log.info("request value={},mnsRequestDto value={}", JSONUtil.toJsonStr(request),JSONUtil.toJsonStr(mnsRequestDto));
|
||||
try {
|
||||
mnsRequestDto.setInternalObj(MnsType.BIZ);
|
||||
messageService.sendMessage(mnsRequestDto);
|
||||
return CommonResponse.success();
|
||||
} catch (Exception e) {
|
||||
|
||||
@ -1,17 +1,37 @@
|
||||
package cn.axzo.msg.center.notices.service.impl;
|
||||
|
||||
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
|
||||
import cn.axzo.msg.center.dal.MNSMessageAppDao;
|
||||
import cn.axzo.msg.center.domain.entity.*;
|
||||
import cn.axzo.msg.center.domain.entity.MNSBatchMessageRequest;
|
||||
import cn.axzo.msg.center.domain.entity.MNSChannelMessageTemplate;
|
||||
import cn.axzo.msg.center.domain.entity.MNSMessage;
|
||||
import cn.axzo.msg.center.domain.entity.MNSMessageApp;
|
||||
import cn.axzo.msg.center.domain.entity.MNSMessageChannel;
|
||||
import cn.axzo.msg.center.domain.entity.MNSMessageRedo;
|
||||
import cn.axzo.msg.center.domain.entity.MNSMessageTemplate;
|
||||
import cn.axzo.msg.center.domain.enums.YesNoEnum;
|
||||
import cn.axzo.msg.center.notices.common.annotation.ApiRequestLog;
|
||||
import cn.axzo.msg.center.notices.common.constans.CommonConstants;
|
||||
import cn.axzo.msg.center.notices.common.domain.BatchMessageSendContext;
|
||||
import cn.axzo.msg.center.notices.common.domain.MessageContext;
|
||||
import cn.axzo.msg.center.notices.common.enums.*;
|
||||
import cn.axzo.msg.center.notices.common.enums.AvailableStatusEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.BatchMessageRequestStatusEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.BatchSendTypeEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.MessageStatusEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.MessageTypeEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.NotifyTypeEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.RetryingFlagEnum;
|
||||
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
|
||||
import cn.axzo.msg.center.notices.common.exception.BizException;
|
||||
import cn.axzo.msg.center.notices.common.utils.DateUtils;
|
||||
import cn.axzo.msg.center.notices.integration.client.DingDingClient;
|
||||
import cn.axzo.msg.center.notices.manager.api.*;
|
||||
import cn.axzo.msg.center.notices.integration.client.impl.RateLimitException;
|
||||
import cn.axzo.msg.center.notices.manager.api.BatchMessageRequestManger;
|
||||
import cn.axzo.msg.center.notices.manager.api.MessageChannelRouter;
|
||||
import cn.axzo.msg.center.notices.manager.api.MessageManager;
|
||||
import cn.axzo.msg.center.notices.manager.api.MessageTemplateManager;
|
||||
import cn.axzo.msg.center.notices.manager.api.RetryStrategy;
|
||||
import cn.axzo.msg.center.notices.manager.api.SmsSendManager;
|
||||
import cn.axzo.msg.center.notices.manager.api.dto.request.MessageSendRequestDto;
|
||||
import cn.axzo.msg.center.notices.manager.api.dto.request.MnsRequestDto;
|
||||
import cn.axzo.msg.center.notices.manager.api.dto.request.SendBatchMessageRequestDto;
|
||||
@ -30,7 +50,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
@ -38,8 +57,12 @@ import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@ -84,6 +107,9 @@ public class MessageServiceImpl implements MessageService, EnvironmentAware {
|
||||
@Resource(name = "userCellphoneProperties")
|
||||
private UserCellphoneProperties userCellphoneProperties;
|
||||
|
||||
@Resource
|
||||
private MnsLimiter mnsLimiter;
|
||||
|
||||
@Value("${prod.profile.string:master}")
|
||||
private String prodProfileString;
|
||||
|
||||
@ -109,6 +135,8 @@ public class MessageServiceImpl implements MessageService, EnvironmentAware {
|
||||
boolean isLegalPhone = PhoneUtil.isPhone(request.getPhoneNo());
|
||||
BizException.error(isLegalPhone, ReturnCodeEnum.INVALID_PARAMETER, "非法的手机号:" + request.getPhoneNo());
|
||||
|
||||
mnsLimiter.maybeLimitSend(request);
|
||||
|
||||
// 查询并校验
|
||||
MNSMessageTemplate messageTemplate = messageTemplateManager.queryAndCheckInnerTemplate(request.getTemplateNo());
|
||||
|
||||
@ -147,12 +175,19 @@ public class MessageServiceImpl implements MessageService, EnvironmentAware {
|
||||
dto.setRequestChannelNo(message.getMessageOrderNo());
|
||||
SendSmsCommonResponseDto response = smsSendManagerComposite.sendMessage(dto);
|
||||
messageManager.updateToProcessing(response.getBizId(), response.getRequestId(), message.getId());
|
||||
mnsLimiter.setSendSuccess(request);
|
||||
} catch (RateLimitException e) {
|
||||
messageManager.updateToFail(message.getId());
|
||||
mnsLimiter.setSendFail(request, e);
|
||||
// don't rethrow rate limit exception to let client retry
|
||||
} catch (BizException e) {
|
||||
messageManager.updateToFail(message.getId());
|
||||
mnsLimiter.setSendFail(request, e);
|
||||
throw e;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
dingDingClient.notifySingleMessage(request.getTemplateNo(), request.getRequestNo(), e.getMessage());
|
||||
mnsLimiter.setSendFail(request, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -206,7 +241,15 @@ public class MessageServiceImpl implements MessageService, EnvironmentAware {
|
||||
message.setChannelName(CommonConstants.MOCK_CHANNEL);
|
||||
message.updateById();
|
||||
|
||||
String messageContent = parse(template.getTemplateContent(), request.getParams());
|
||||
String messageContent;
|
||||
try {
|
||||
messageContent = PlaceholderResolver.tryResolve(template.getTemplateContent(), request.getParams());
|
||||
} catch (Exception e) {
|
||||
log.warn("fail to resolve template content, fallback to old method. request={}, template={}, message={}",
|
||||
request, template, message, e);
|
||||
//fallback
|
||||
messageContent = parse(template.getTemplateContent(), request.getParams());
|
||||
}
|
||||
dingDingClient.notifyMockMessage(request.getPhoneNo(), template.getTitle(), messageContent);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,172 @@
|
||||
package cn.axzo.msg.center.notices.service.impl;
|
||||
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
|
||||
import cn.axzo.msg.center.notices.manager.api.dto.request.MnsRequestDto;
|
||||
import com.google.common.hash.Hasher;
|
||||
import com.google.common.hash.Hashing;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MnsLimiter {
|
||||
|
||||
private final MnsProperties props;
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
/**
|
||||
* 基于固定窗口, 限制重复内容的发送次数
|
||||
*/
|
||||
void maybeLimitSend(MnsRequestDto request) {
|
||||
if (!props.shouldLimit(request.getTemplateNo())) {
|
||||
return;
|
||||
}
|
||||
// key中包含了固定窗口因子
|
||||
String key = buildTimeAwareKey(request);
|
||||
String countStr = stringRedisTemplate.opsForValue().get(key);
|
||||
if (StringUtils.isBlank(countStr)) {
|
||||
return;
|
||||
}
|
||||
long alreadySendCount = Long.parseLong(countStr);
|
||||
|
||||
MnsType msnType = request.getInternalObj(MnsType.class);
|
||||
if (msnType == null) msnType = MnsType.BIZ;
|
||||
|
||||
long limitCount;
|
||||
String error;
|
||||
if (msnType == MnsType.BIZ) {
|
||||
limitCount = props.getBizLimitPerDay();
|
||||
error = String.format("业务短信: 每天发送给同一个手机号的重复内容不能超过 %s 条。 请勿重试发送!!", limitCount);
|
||||
} else {
|
||||
limitCount = props.getVerifyCodeLimitPerWindow();
|
||||
error = String.format("验证码短信: 每 %s 分钟发送给同一个手机号的重复内容不能超过 %s 条。 请勿重试发送!!",
|
||||
props.getVerifyCodeLimitWindowMinutes(), limitCount);
|
||||
}
|
||||
if (alreadySendCount + 1 > limitCount) {
|
||||
log.warn("{}, request={}", error, request);
|
||||
throw new ServiceException(ReturnCodeEnum.FAIL.getCode(), error);
|
||||
}
|
||||
}
|
||||
|
||||
void setSendSuccess(MnsRequestDto request) {
|
||||
if (!props.shouldLimit(request.getTemplateNo())) {
|
||||
return;
|
||||
}
|
||||
// key中包含了固定窗口因子
|
||||
String key = buildTimeAwareKey(request);
|
||||
stringRedisTemplate.opsForValue().increment(key);
|
||||
// 这里设置过期时间只是为了删除对应的key, 和限制逻辑本身没有太大的关系
|
||||
long expireMinutes = getTimeAwareExpireTimeMinutes(request);
|
||||
// 延迟删除
|
||||
stringRedisTemplate.expire(key, expireMinutes + 1, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
void setSendFail(MnsRequestDto request, Exception e) {
|
||||
// NOP
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取key过期时间
|
||||
*/
|
||||
private long getTimeAwareExpireTimeMinutes(MnsRequestDto request) {
|
||||
MnsType msnType = request.getInternalObj(MnsType.class);
|
||||
if (msnType == null) {
|
||||
msnType = MnsType.BIZ;
|
||||
}
|
||||
return msnType == MnsType.BIZ
|
||||
? TimeUnit.DAYS.toMinutes(1)
|
||||
: props.getVerifyCodeLimitWindowMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建包含时间元素的缓存key, key中包含了固定窗口因子. 固定窗口: 限制发送重复的内容
|
||||
*/
|
||||
private String buildTimeAwareKey(MnsRequestDto request) {
|
||||
MnsType msnType = request.getInternalObj(MnsType.class);
|
||||
if (msnType == null) {
|
||||
msnType = MnsType.BIZ;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("msg-center:mns_limit");
|
||||
Consumer<String> appender = value -> {
|
||||
if (StringUtils.isNotBlank(value))
|
||||
buf.append(":").append(value);
|
||||
};
|
||||
// 通过templateNo和params就可以判断出发送的内容是不是一样的
|
||||
appender.accept(msnType.name());
|
||||
appender.accept(request.getTemplateNo());
|
||||
appender.accept(request.getPhoneNo());
|
||||
appender.accept(buildTimeAwareSegment(request));
|
||||
appender.accept(hashParams(request.getParams()));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String buildTimeAwareSegment(MnsRequestDto request) {
|
||||
MnsType mnsType = request.getInternalObj(MnsType.class);
|
||||
if (mnsType == null) {
|
||||
mnsType = MnsType.BIZ;
|
||||
}
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
|
||||
int windowMinutes = props.getVerifyCodeLimitWindowMinutes();
|
||||
return mnsType == MnsType.BIZ
|
||||
? sdf.format(now)
|
||||
: String.format("%s-%d-%d",
|
||||
sdf.format(now), windowMinutes, getVerifySegmentIndex(now, windowMinutes));
|
||||
}
|
||||
|
||||
public static int getVerifySegmentIndex(Date now, int windowMinutes) {
|
||||
DateTime dateTime = new DateTime(now, DateTimeZone.forID("Asia/Shanghai"));
|
||||
// Calculate the total number of intervals in a day
|
||||
int intervalsPerDay = 24 * 60 / windowMinutes;
|
||||
// Get the current time in minutes
|
||||
int currentMinutes = dateTime.getHourOfDay() * 60 + dateTime.getMinuteOfHour();
|
||||
// Find the index of the interval that the current time falls into
|
||||
int intervalIndex = currentMinutes / windowMinutes;
|
||||
// Ensure the index is within the range of the array
|
||||
if (intervalIndex >= intervalsPerDay) {
|
||||
intervalIndex = intervalsPerDay - 1;
|
||||
}
|
||||
return intervalIndex;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private static String hashParams(Map<String, Object> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
Hasher hasher = Hashing.murmur3_128().newHasher();
|
||||
Consumer<Object> appender = value -> {
|
||||
if (value != null) {
|
||||
hasher.putString(String.valueOf(value), StandardCharsets.UTF_8);
|
||||
}
|
||||
};
|
||||
for (Map.Entry<String, Object> e : new TreeMap<>(params).entrySet()) {
|
||||
if (e.getKey() == null || e.getValue() == null) {
|
||||
continue;
|
||||
}
|
||||
appender.accept(e.getKey());
|
||||
appender.accept(e.getValue());
|
||||
}
|
||||
return hasher.hash().toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.axzo.msg.center.notices.service.impl;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@RefreshScope
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "user.cellphone")
|
||||
public class MnsProperties {
|
||||
|
||||
/**
|
||||
* 是否开启重复发送限制
|
||||
*/
|
||||
private boolean sendLimitOn = true;
|
||||
|
||||
/**
|
||||
* 不验证重复发送的内部模板编码
|
||||
*/
|
||||
private String limitWhitelist;
|
||||
|
||||
/**
|
||||
* 业务上每天发送重复内容的次数限制
|
||||
*/
|
||||
private long bizLimitPerDay = 20;
|
||||
|
||||
/**
|
||||
* 验证码15分钟内发送的内容都是一样的
|
||||
*/
|
||||
private int verifyCodeLimitWindowMinutes = 15;
|
||||
|
||||
/**
|
||||
* 验证码每15分钟可以重复发送的次数
|
||||
*/
|
||||
private long verifyCodeLimitPerWindow = 20;
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean shouldLimit(String templateNo) {
|
||||
return sendLimitOn && !isInLimitWhitelist(templateNo);
|
||||
}
|
||||
|
||||
private boolean isInLimitWhitelist(String templateNo) {
|
||||
return StringUtils.isNotBlank(limitWhitelist)
|
||||
&& limitWhitelist.contains(templateNo);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package cn.axzo.msg.center.notices.service.impl;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public enum MnsType {
|
||||
/**
|
||||
* 业务短信
|
||||
*/
|
||||
BIZ,
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
VERIFY_CODE
|
||||
}
|
||||
@ -10,6 +10,7 @@ import cn.axzo.msg.center.notices.common.properties.SmsProperties;
|
||||
import cn.axzo.msg.center.notices.manager.api.dto.request.MnsRequestDto;
|
||||
import cn.axzo.msg.center.notices.service.api.MessageService;
|
||||
import cn.axzo.msg.center.notices.service.gateway.SmsGateway;
|
||||
import cn.axzo.msg.center.notices.service.impl.MnsType;
|
||||
import cn.axzo.msg.center.notices.service.request.CaptchaParam;
|
||||
import cn.axzo.msg.center.notices.service.request.SendCodeV2Req;
|
||||
import cn.axzo.msg.center.notices.service.response.SmsCodeInfoRes;
|
||||
@ -31,7 +32,13 @@ import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author zhangPeng
|
||||
@ -68,7 +75,7 @@ public class SmsManager extends BaseManager implements SmsGateway {
|
||||
* @return
|
||||
*/
|
||||
public int sendSmsCode(SendCodeV2Req req) {
|
||||
sendMnsCode(req.getPhone(), req.getParam(), req.getAppCode(),req.getTemplateNo());
|
||||
sendMnsCode(req.getPhone(), req.getParam(), req.getAppCode(),req.getTemplateNo(), req.getCode());
|
||||
log.info("发送验证码 手机号{} -- 参数 {} -- 应用程序code {} -- 模板编号templateCode {}", req.getPhone(), req.getParam(), req.getAppCode(),req.getTemplateNo());
|
||||
return req.getCode();
|
||||
}
|
||||
@ -176,7 +183,7 @@ public class SmsManager extends BaseManager implements SmsGateway {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMnsCode(String phoneNumber, Map<String, Object> param, String appCode,String templateNo) {
|
||||
public void sendMnsCode(String phoneNumber, Map<String, Object> param, String appCode, String templateNo, Integer code) {
|
||||
if (!isSendMnsCode) {
|
||||
return;
|
||||
}
|
||||
@ -186,6 +193,10 @@ public class SmsManager extends BaseManager implements SmsGateway {
|
||||
request.setTemplateNo(templateNo);
|
||||
request.setParams(param);
|
||||
request.setRequestNo(UUID.randomUUID().toString());
|
||||
request.setInternalObj(MnsType.VERIFY_CODE);
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("code", code);
|
||||
request.setParams(params);
|
||||
messageService.sendMessage(request);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user