WANG 6 年 前
コミット
ede239e9f0

+ 53 - 67
examcloud-exchange-inner-api-provider/src/main/java/cn/com/qmth/examcloud/exchange/inner/api/provider/SmsCloudServiceProvider.java

@@ -1,12 +1,21 @@
 package cn.com.qmth.examcloud.exchange.inner.api.provider;
 
-import cn.com.qmth.examcloud.commons.exception.StatusException;
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.Valid;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
 import cn.com.qmth.examcloud.exchange.inner.api.SmsCloudService;
-import cn.com.qmth.examcloud.exchange.inner.api.request.CaptureFailedAlarmReq;
 import cn.com.qmth.examcloud.exchange.inner.api.request.CheckSmsCodeReq;
 import cn.com.qmth.examcloud.exchange.inner.api.request.SendSmsCodeReq;
 import cn.com.qmth.examcloud.exchange.inner.api.request.SendSmsReq;
-import cn.com.qmth.examcloud.exchange.inner.api.response.CheckIdentifyingCodeResp;
+import cn.com.qmth.examcloud.exchange.inner.api.response.CheckSmsCodeResp;
 import cn.com.qmth.examcloud.exchange.inner.api.response.SendSmsCodeResp;
 import cn.com.qmth.examcloud.exchange.inner.api.response.SendSmsResp;
 import cn.com.qmth.examcloud.exchange.inner.service.SmsService;
@@ -14,17 +23,8 @@ import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.SmsAssemblyCacheBean;
 import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import cn.com.qmth.examcloud.web.support.WithoutStackTrace;
 import io.swagger.annotations.ApiParam;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.validation.Valid;
-import java.util.List;
-import java.util.Map;
 
 /**
  * 短信发送
@@ -33,67 +33,53 @@ import java.util.Map;
 @RequestMapping("${$rmp.cloud.exchange.inner}" + "/sms")
 public class SmsCloudServiceProvider extends ControllerSupport implements SmsCloudService {
 
-    private static final long serialVersionUID = -1497756895732370672L;
-
-    @Autowired
-    private SmsService smsService;
+	private static final long serialVersionUID = -1497756895732370672L;
 
-    @Override
-    @RequestMapping(method = RequestMethod.POST, value = "/sendSms")
-    public SendSmsResp sendSms(@RequestBody @Valid @ApiParam(required = true) SendSmsReq req) {
-        String smsAssemblyCode = req.getSmsAssemblyCode();
-        List<String> phoneList = req.getPhoneList();
-        Map<String, String> params = req.getParams();
+	@Autowired
+	private SmsService smsService;
 
-        //获取短信配置信息
-        SmsAssemblyCacheBean assemblyCacheBean = CacheHelper.getSmsAssembly(smsAssemblyCode);
+	@Override
+	@RequestMapping(method = RequestMethod.POST, value = "sendSms")
+	public SendSmsResp sendSms(@RequestBody @Valid @ApiParam(required = true) SendSmsReq req) {
+		String smsAssemblyCode = req.getSmsAssemblyCode();
+		List<String> phoneList = req.getPhoneList();
+		Map<String, String> params = req.getParams();
 
-        boolean virtualEnable = PropertyHolder.getBoolean("sms.virtual.enable",
-                false);
+		// 获取短信配置信息
+		SmsAssemblyCacheBean assemblyCacheBean = CacheHelper.getSmsAssembly(smsAssemblyCode);
 
-        if (!virtualEnable) {
-            try {
-                smsService.sendSms(assemblyCacheBean, phoneList, params);
-            } catch (Exception e) {
-                // ignore
-            }
-        }
+		boolean virtualEnable = PropertyHolder.getBoolean("sms.virtual.enable", false);
 
-        SendSmsResp resp = new SendSmsResp();
-        return resp;
-    }
+		if (!virtualEnable) {
+			try {
+				smsService.sendSms(assemblyCacheBean, phoneList, params);
+			} catch (Exception e) {
+				// ignore
+			}
+		}
 
-    @Override
-    @RequestMapping(method = RequestMethod.POST, value = "/sendIdentifyingCode")
-    public SendSmsCodeResp sendSmsCode(@RequestBody @Valid @ApiParam(required = true) SendSmsCodeReq req) {
+		SendSmsResp resp = new SendSmsResp();
+		return resp;
+	}
 
-        SendSmsCodeResp sendSmsResp = new SendSmsCodeResp();
-        try {
-            smsService.sendSmsSecurityCode(req.getPhone(), req.getCode());
-            sendSmsResp.setSuccess(true);
-            sendSmsResp.setReturnMsg("发送成功");
-        } catch (StatusException exception) {
-            exception.printStackTrace();
-            sendSmsResp.setSuccess(false);
-            sendSmsResp.setReturnMsg(exception.getDesc());
-        }
-        return sendSmsResp;
-    }
+	@Override
+	@WithoutStackTrace
+	@RequestMapping(method = RequestMethod.POST, value = "sendSmsCode")
+	public SendSmsCodeResp sendSmsCode(
+			@RequestBody @Valid @ApiParam(required = true) SendSmsCodeReq req) {
+		smsService.sendSmsCode(req.getPhone(), req.getCode());
+		SendSmsCodeResp sendSmsResp = new SendSmsCodeResp();
+		return sendSmsResp;
+	}
 
-    @Override
-    @RequestMapping(method = RequestMethod.POST, value = "/checkIdentifyingCode")
-    public CheckIdentifyingCodeResp checkSmsCode(@RequestBody @Valid @ApiParam(required = true) CheckSmsCodeReq req) {
-        CheckIdentifyingCodeResp resp = new CheckIdentifyingCodeResp();
-        try {
-            smsService.validateSmsSecurityCode(req.getPhone(), req.getCode());
-            resp.setSuccess(true);
-            resp.setReturnMsg("校验成功");
-        } catch (StatusException exception) {
-            exception.printStackTrace();
-            resp.setSuccess(false);
-            resp.setReturnMsg(exception.getDesc());
-        }
-        return resp;
-    }
+	@Override
+	@WithoutStackTrace
+	@RequestMapping(method = RequestMethod.POST, value = "checkSmsCode")
+	public CheckSmsCodeResp checkSmsCode(
+			@RequestBody @Valid @ApiParam(required = true) CheckSmsCodeReq req) {
+		smsService.validateSmsCode(req.getPhone(), req.getCode());
+		CheckSmsCodeResp resp = new CheckSmsCodeResp();
+		return resp;
+	}
 
 }

+ 0 - 42
examcloud-exchange-inner-service/src/main/java/cn/com/qmth/examcloud/exchange/inner/service/SendSmsService.java

@@ -1,42 +0,0 @@
-package cn.com.qmth.examcloud.exchange.inner.service;
-
-import cn.com.qmth.examcloud.exchange.inner.service.bean.CaptureFailedAlarmInfo;
-import cn.com.qmth.examcloud.exchange.inner.service.bean.SendSmsInfo;
-
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
-
-public interface SendSmsService {
-
-	/**
-	 * 发送验证码
-	 * @param phone	手机号码
-	 * @param sign	签名
-	 * @param templateCode	模板code		eg:SMS_138073780
-	 * @param message		短信内容
-	 * @return
-	 * @throws Exception
-	 */
-	public void sendIdentifyingCode(SendSmsInfo sendSmsInfo);
-	
-	/**
-	 * 校验验证码是否正确
-	 * @param phone		手机号码
-	 * @param key		验证码
-	 */
-	public boolean checkIdentifyingCode(String phone,String code);
-	
-	/**
-	 * 查询短信发送详情
-	 * @param bizId
-	 * @return
-	 * @throws Exception
-	 */
-	public QuerySendDetailsResponse querySendDetails(String bizId,String phone);
-	
-	/**
-	 * 处理抓拍失败照片警报
-	 * @param captureFailedAlarmReq
-	 */
-	public void captureFailedAlarm(CaptureFailedAlarmInfo captureFailedAlarmInfo) throws Exception;
-	
-}

+ 2 - 2
examcloud-exchange-inner-service/src/main/java/cn/com/qmth/examcloud/exchange/inner/service/SmsService.java

@@ -26,7 +26,7 @@ public interface SmsService {
      * @param phone 手机号
      * @param code 验证码
      */
-    void sendSmsSecurityCode(String phone, String code);
+    void sendSmsCode(String phone, String code);
 
     /**
      * 校验短信验证码
@@ -34,5 +34,5 @@ public interface SmsService {
      * @param phone 手机号
      * @param code 验证码
      */
-    void validateSmsSecurityCode(String phone, String code);
+    void validateSmsCode(String phone, String code);
 }

+ 0 - 273
examcloud-exchange-inner-service/src/main/java/cn/com/qmth/examcloud/exchange/inner/service/impl/AliyunSmsServiceImpl.java

@@ -1,273 +0,0 @@
-package cn.com.qmth.examcloud.exchange.inner.service.impl;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
-import cn.com.qmth.examcloud.commons.util.DateUtil;
-import cn.com.qmth.examcloud.commons.util.JsonUtil;
-import cn.com.qmth.examcloud.commons.util.UUID;
-import cn.com.qmth.examcloud.exchange.inner.service.SmsService;
-import cn.com.qmth.examcloud.exchange.inner.service.bean.ShortMessageInfo;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.SmsAssemblyCacheBean;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import cn.com.qmth.examcloud.web.redis.RedisClient;
-import com.aliyuncs.CommonRequest;
-import com.aliyuncs.CommonResponse;
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.http.MethodType;
-import com.aliyuncs.http.ProtocolType;
-import com.aliyuncs.profile.DefaultProfile;
-import com.google.common.collect.Maps;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import org.apache.tomcat.util.buf.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * {@link StatusException} 状态码范围:101XXX<br>
- * <p>
- * 阿里云短信服务
- *
- * @author WANGWEI
- * @date 2019年3月27日
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
- */
-@Service
-public class AliyunSmsServiceImpl implements SmsService {
-
-    @Autowired
-    RedisClient redisClient;
-    /**
-     * controller 统一业务日志对象
-     */
-    protected ExamCloudLog log = ExamCloudLogFactory.getLog(this.getClass());
-
-    @Override
-    public void sendSms(SmsAssemblyCacheBean smsAssembly, List<String> phoneList,
-                        Map<String, String> params) {
-
-        execute(smsAssembly, "SendSms", phoneList, params);
-    }
-
-    @Override
-    public void sendSmsSecurityCode(String phone, String code) {
-        {
-
-            boolean virtualEnable = PropertyHolder
-                    .getBoolean("sms.securityCode.virtual.enable", false);
-
-            if (virtualEnable) {
-                return;
-            }
-
-            String key = "$_SMS:" + phone;
-            ShortMessageInfo sm = redisClient.get(key, ShortMessageInfo.class);
-            if (null != sm) {
-                Date creationTime = sm.getCreationTime();
-                boolean sameDay = DateUtil.isSameDay(creationTime, new Date());
-                if (!sameDay) {
-                    sm = null;
-                }
-            }
-
-            Date now = new Date();
-
-            if (null == sm) {
-                sm = new ShortMessageInfo();
-                sm.setCreationTime(now);
-                sm.setPhone(phone);
-                sm.setTimes(0);
-            } else {
-                List<Date> sendTimeList = sm.getSendTimeList();
-
-                if (10 <= sendTimeList.size()) {
-                    throw new StatusException("102000", "一天内发送次数超过10次");
-                } else if (5 <= sendTimeList.size()) {
-                    Date d = sendTimeList.get(sendTimeList.size() - 5);
-                    if (now.getTime() - d.getTime() < 1000 * 60 * 60) {
-                        throw new StatusException("102000", "一小时内发送次数超过5次");
-                    }
-                } else {
-                    Date d = sendTimeList.get(sendTimeList.size() - 1);
-                    if (now.getTime() - d.getTime() < 1000 * 60) {
-                        throw new StatusException("102000", "一分钟内发送次数超过1次");
-                    }
-                }
-            }
-            //获取短信配置信息
-            SmsAssemblyCacheBean assemblyCacheBean = CacheHelper.getSmsAssembly(YZM_SMS_ASSEMBLY_CODE);
-            Map<String, String> params = Maps.newHashMap();
-            params.put("code", code);
-            this.sendSms(assemblyCacheBean, Arrays.asList(new String[]{phone}), params);
-
-            sm.getSendTimeList().add(now);
-            sm.setTimes(sm.getSendTimeList().size());
-            sm.setLastMessage(code);
-
-            redisClient.set(key, sm, 60 * 60 * 24);
-        }
-    }
-
-    @Override
-    public void validateSmsSecurityCode(String phone, String code) {
-        {
-
-            boolean virtualEnable = PropertyHolder
-                    .getBoolean("sms.securityCode.virtual.enable", false);
-
-            if (virtualEnable) {
-                String virtualCode = PropertyHolder
-                        .getString("sms.securityCode.virtual.code", "5220");
-                if (!virtualCode.equals(code)) {
-                    throw new StatusException("102008", "验证码错误");
-                } else {
-                    return;
-                }
-            }
-
-            String key = "$_SMS:" + phone;
-            ShortMessageInfo sm = redisClient.get(key, ShortMessageInfo.class);
-
-            if (null == sm) {
-                throw new StatusException("102001", "未发送验证码");
-            }
-            List<Date> sendTimeList = sm.getSendTimeList();
-            Date date = sendTimeList.get(sendTimeList.size() - 1);
-            Date now = new Date();
-
-            if (now.getTime() - date.getTime() > 1000 * 60 * 5) {
-                throw new StatusException("102002", "验证码过期");
-            }
-
-            if (!sm.getLastMessage().equals(code)) {
-                throw new StatusException("102003", "验证码错误");
-            } else {
-                sm.setLastMessage(UUID.randomUUID());
-                redisClient.set(key, sm);
-            }
-        }
-    }
-
-    /**
-     * 执行
-     *
-     * @param smsAssembly
-     * @param action
-     * @param phoneList
-     * @param templateParams 短信模板参数
-     * @author WANGWEI
-     */
-    private void execute(SmsAssemblyCacheBean smsAssembly, String action, List<String> phoneList,
-                         Map<String, String> templateParams) {
-        String accessKeyId = PropertyHolder.getString("aliyun.sms.accessKeyId");
-        String accessSecret = PropertyHolder.getString("aliyun.sms.accessKeySecret");
-        String signName = smsAssembly.getExt1();
-        String templateCode = smsAssembly.getExt2();
-
-        DefaultProfile profile = DefaultProfile.getProfile("default", accessKeyId, accessSecret);
-        IAcsClient client = new DefaultAcsClient(profile);
-
-        CommonRequest request = new CommonRequest();
-        request.setProtocol(ProtocolType.HTTPS);
-        request.setMethod(MethodType.POST);
-        request.setDomain("dysmsapi.aliyuncs.com");
-        request.setVersion("2017-05-25");
-        request.setAction(action);
-        String phoneNumbers = StringUtils.join(phoneList, ',');
-        request.putQueryParameter("PhoneNumbers", phoneNumbers);
-        request.putQueryParameter("SignName", signName);
-        request.putQueryParameter("TemplateCode", templateCode);
-        request.putQueryParameter("TemplateParam", JsonUtil.toJson(templateParams));
-        try {
-            CommonResponse response = client.getCommonResponse(request);
-            String data = response.getData();
-            JsonParser jp = new JsonParser();
-            JsonObject jsonObj = jp.parse(data).getAsJsonObject();
-            String code = jsonObj.get("Code").getAsString();
-
-            if (!code.equals("OK")) {
-                log.error("aliyun sms response: " + JsonUtil.toJson(response));
-                throw new StatusException("101001", "短信发送失败");
-            }
-
-        } catch (StatusException e) {
-            throw e;
-        } catch (Exception e) {
-            log.error("fail to send SMS", e);
-        }
-    }
-
-    public static void main(String[] args) {
-        List<UserInfo> userList = new ArrayList<>();
-        userList.add(new UserInfo(3,"33",4));
-        userList.add(new UserInfo(1,"1111",6));
-        userList.add(new UserInfo(5,"555",0));
-        userList.add(new UserInfo(2,"32",8));
-        System.out.println("group by 之前:");
-        userList.forEach(u->{
-            System.out.println("源:u.id="+u.getId()+",u.name="+u.getName()+",u.num="+u.getNum());
-        });
-        System.out.println("group by 之后,且使用HashMap:");
-        Map<String, List<UserInfo>> newUserList = userList.stream().collect(Collectors.groupingBy(UserInfo::getName));
-        newUserList.keySet().forEach(key->{
-            List<UserInfo> userInfos = newUserList.get(key);
-            userInfos.forEach(u->{
-                System.out.println("HashMapLu.id="+u.getId()+",u.name="+u.getName()+",u.num="+u.getNum());
-            });
-        });
-        System.out.println("group by 之后,改为使用LinkedHashMap:");
-        LinkedHashMap<String, List<UserInfo>> newUserList2 = userList.stream().collect(Collectors.groupingBy(UserInfo::getName, LinkedHashMap::new, Collectors.toList()));
-        newUserList2.keySet().forEach(key->{
-            List<UserInfo> userInfos = newUserList2.get(key);
-            userInfos.forEach(u->{
-                System.out.println("LinkedHashMap:u.id="+u.getId()+",u.name="+u.getName()+",u.num="+u.getNum());
-            });
-        });
-    }
-}
-
-class UserInfo {
-    private int num;
-    private int id;
-    private String name;
-
-    public UserInfo(int id, String name,int num) {
-        this.num=num;
-        this.id = id;
-        this.name = name;
-    }
-
-    public UserInfo(int id) {
-        this.id = id;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public int getNum() {
-        return num;
-    }
-
-    public void setNum(int num) {
-        this.num = num;
-    }
-}

+ 0 - 216
examcloud-exchange-inner-service/src/main/java/cn/com/qmth/examcloud/exchange/inner/service/impl/SendSmsServiceImpl.java

@@ -1,216 +0,0 @@
-package cn.com.qmth.examcloud.exchange.inner.service.impl;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.exceptions.ServerException;
-import com.aliyuncs.profile.DefaultProfile;
-import com.aliyuncs.profile.IClientProfile;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.exchange.inner.service.SendSmsService;
-import cn.com.qmth.examcloud.exchange.inner.service.bean.CaptureFailedAlarmInfo;
-import cn.com.qmth.examcloud.exchange.inner.service.bean.SendSmsInfo;
-import cn.com.qmth.examcloud.exchange.inner.service.bean.SmsCodeRedisInfo;
-import cn.com.qmth.examcloud.web.redis.RedisClient;
-
-@Service("sendSmsService")
-public class SendSmsServiceImpl implements SendSmsService {
-	
-	@Autowired
-	private RedisClient redisClient;
-
-	//redis中短信验证码key的前缀
-	private static final String CODE_REDIS_KEY_PREFIXS = "SMSCODE_";
-	
-	//验证码默认有效时间
-	private static final int DEFAULT_DFFECTIVETIME = 120;
-	
-	//短信发送默认间隔时间
-	private static final int DEFAULT_INTERVALSECONDS = 90;
-	
-	// 产品名称:云通信短信API产品,开发者无需替换
-	private static final String product = "Dysmsapi";
-
-	// 产品域名,开发者无需替换
-	private static final String domain = "dysmsapi.aliyuncs.com";
-
-	@Value("${aliyun.sms.accessKeyId}")
-	private String accessKeyId;
-	
-	@Value("${aliyun.sms.accessKeySecret}")
-	private String accessKeySecret;
-	
-	@Override
-	public void sendIdentifyingCode(SendSmsInfo sendSmsInfo) {
-		if(sendSmsInfo.getEffectiveTime() == null || sendSmsInfo.getEffectiveTime() == 0){
-			sendSmsInfo.setEffectiveTime(DEFAULT_DFFECTIVETIME);
-		}
-		if(sendSmsInfo.getIntervalSeconds() == null|| sendSmsInfo.getIntervalSeconds() == 0){
-			sendSmsInfo.setIntervalSeconds(DEFAULT_INTERVALSECONDS);
-		}
-		SmsCodeRedisInfo smsCodeRedisInfo = redisClient.get(CODE_REDIS_KEY_PREFIXS+sendSmsInfo.getPhone(),SmsCodeRedisInfo.class);
-		if(smsCodeRedisInfo != null){
-			long createTime = smsCodeRedisInfo.getCreateTime();
-			if((System.currentTimeMillis()-createTime)<sendSmsInfo.getIntervalSeconds()*60*1000){
-				throw new StatusException("sendIdentifyingCode-1","同一个手机号码,"+sendSmsInfo.getIntervalSeconds()+"秒内允许请求一次");
-			}
-		}
-		
-		// 可自助调整超时时间
-		System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
-		System.setProperty("sun.net.client.defaultReadTimeout", "10000");
-
-		// 初始化acsClient,暂不支持region化
-		IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,accessKeySecret);
-		try {
-			DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-		} catch (ClientException e) {
-			throw new StatusException("sendIdentifyingCode-1", "DefaultProfile.addEndpoint failed");
-		}
-		IAcsClient acsClient = new DefaultAcsClient(profile);
-
-		// 组装请求对象-具体描述见控制台-文档部分内容
-		SendSmsRequest request = new SendSmsRequest();
-		// 必填:待发送手机号
-		request.setPhoneNumbers(sendSmsInfo.getPhone());
-		// 必填:短信签名-可在短信控制台中找到
-		request.setSignName(sendSmsInfo.getSign());
-		// 必填:短信模板-可在短信控制台中找到
-		request.setTemplateCode(sendSmsInfo.getTemplateCode());
-		// 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
-		
-		request.setTemplateParam("{\"code\":\""+sendSmsInfo.getCode()+"\"}");
-
-		// 选填-上行短信扩展码(无特殊需求用户请忽略此字段)
-		// request.setSmsUpExtendCode("90997");
-
-		// 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-		request.setOutId("yourOutId");
-
-		// hint 此处可能会抛出异常,注意catch
-		try {
-			SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
-			if("ok".equalsIgnoreCase(sendSmsResponse.getCode())){
-				setCodeInfoToRedis(sendSmsInfo);
-			}else{
-				throw new StatusException("sendIdentifyingCode-2", "code:"+sendSmsResponse.getCode()+",message:"+sendSmsResponse.getMessage());
-			}
-		} catch (ServerException e) {
-			throw new StatusException("sendIdentifyingCode-3", "send sms failed");
-		} catch (ClientException e) {
-			throw new StatusException("sendIdentifyingCode-3", "send sms failed");
-		}
-	}
-	
-	/**
-	 * 将短信验证码信息放入redis
-	 * @param sendSmsInfo
-	 */
-	private void setCodeInfoToRedis(SendSmsInfo sendSmsInfo){
-		String redisKey = CODE_REDIS_KEY_PREFIXS+sendSmsInfo.getPhone();
-		long currentTime = System.currentTimeMillis();
-		
-		SmsCodeRedisInfo smsCodeRedisInfo = new SmsCodeRedisInfo();
-		smsCodeRedisInfo.setCode(sendSmsInfo.getCode());
-		smsCodeRedisInfo.setCreateTime(currentTime);
-		redisClient.set(redisKey, smsCodeRedisInfo, sendSmsInfo.getEffectiveTime());
-	}
-	
-	@Override
-	public QuerySendDetailsResponse querySendDetails(String bizId,String phone){
-
-		// 可自助调整超时时间
-		System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
-		System.setProperty("sun.net.client.defaultReadTimeout", "10000");
-
-		// 初始化acsClient,暂不支持region化
-		IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,
-				accessKeySecret);
-		try {
-			DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-		} catch (ClientException e) {
-			e.printStackTrace();
-		}
-		IAcsClient acsClient = new DefaultAcsClient(profile);
-
-		// 组装请求对象
-		QuerySendDetailsRequest request = new QuerySendDetailsRequest();
-		// 必填-号码
-		request.setPhoneNumber(phone);
-		// 可选-流水号
-		request.setBizId(bizId);
-		// 必填-发送日期 支持30天内记录查询,格式yyyyMMdd
-		SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
-		request.setSendDate(ft.format(new Date()));
-		// 必填-页大小
-		request.setPageSize(10L);
-		// 必填-当前页码从1开始计数
-		request.setCurrentPage(1L);
-
-		// hint 此处可能会抛出异常,注意catch
-		QuerySendDetailsResponse querySendDetailsResponse = null;
-		try {
-			querySendDetailsResponse = acsClient.getAcsResponse(request);
-		} catch (ServerException e) {
-			e.printStackTrace();
-		} catch (ClientException e) {
-			e.printStackTrace();
-		}
-
-		return querySendDetailsResponse;
-	}
-
-	@Override
-	public boolean checkIdentifyingCode(String phone, String code) {
-		SmsCodeRedisInfo smsCodeRedisInfo = redisClient.get(CODE_REDIS_KEY_PREFIXS+phone, SmsCodeRedisInfo.class);
-		if(smsCodeRedisInfo!=null){
-			if(code.equals(smsCodeRedisInfo.getCode()+"")){
-				//校验成功,删除验证码
-				redisClient.delete(CODE_REDIS_KEY_PREFIXS+phone);
-				return true;
-			}
-		}
-		return false;
-	}
-
-	@Override
-	public void captureFailedAlarm(CaptureFailedAlarmInfo captureFailedAlarmInfo) throws Exception {
-		// 可自助调整超时时间
-		System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
-		System.setProperty("sun.net.client.defaultReadTimeout", "10000");
-
-		// 初始化acsClient,暂不支持region化
-		IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,accessKeySecret);
-		DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-		IAcsClient acsClient = new DefaultAcsClient(profile);
-
-		// 组装请求对象-具体描述见控制台-文档部分内容
-		SendSmsRequest request = new SendSmsRequest();
-		// 必填:待发送手机号
-		request.setPhoneNumbers(captureFailedAlarmInfo.getPhone());
-		// 必填:短信签名-可在短信控制台中找到
-		request.setSignName(captureFailedAlarmInfo.getSign());
-		// 必填:短信模板-可在短信控制台中找到
-		request.setTemplateCode(captureFailedAlarmInfo.getTemplateCode());
-		// 可选:模板中的变量
-		request.setTemplateParam(captureFailedAlarmInfo.getTemplateParam());
-		// 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-		request.setOutId("yourOutId");
-
-		// hint 此处可能会抛出异常,注意catch
-		acsClient.getAcsResponse(request);
-	}
-	
-}

+ 210 - 0
examcloud-exchange-inner-service/src/main/java/cn/com/qmth/examcloud/exchange/inner/service/impl/SmsServiceImpl.java

@@ -0,0 +1,210 @@
+package cn.com.qmth.examcloud.exchange.inner.service.impl;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tomcat.util.buf.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.aliyuncs.CommonRequest;
+import com.aliyuncs.CommonResponse;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.http.ProtocolType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.google.common.collect.Maps;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
+import cn.com.qmth.examcloud.commons.util.DateUtil;
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
+import cn.com.qmth.examcloud.commons.util.UUID;
+import cn.com.qmth.examcloud.exchange.inner.service.SmsService;
+import cn.com.qmth.examcloud.exchange.inner.service.bean.ShortMessageInfo;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
+import cn.com.qmth.examcloud.support.cache.bean.SmsAssemblyCacheBean;
+import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+import cn.com.qmth.examcloud.web.redis.RedisClient;
+
+/**
+ * {@link StatusException} 状态码范围:101XXX<br>
+ * <p>
+ * 阿里云短信服务
+ *
+ * @author WANGWEI
+ * @date 2019年3月27日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+@Service
+public class SmsServiceImpl implements SmsService {
+
+	@Autowired
+	RedisClient redisClient;
+
+	protected ExamCloudLog log = ExamCloudLogFactory.getLog(this.getClass());
+
+	@Override
+	public void sendSms(SmsAssemblyCacheBean smsAssembly, List<String> phoneList,
+			Map<String, String> params) {
+
+		execute(smsAssembly, "SendSms", phoneList, params);
+	}
+
+	@Override
+	public void sendSmsCode(String phone, String code) {
+		{
+
+			boolean virtualEnable = PropertyHolder.getBoolean("sms.securityCode.virtual.enable",
+					false);
+
+			if (virtualEnable) {
+				return;
+			}
+
+			String key = "$_SMS:" + phone;
+			ShortMessageInfo sm = redisClient.get(key, ShortMessageInfo.class);
+			if (null != sm) {
+				Date creationTime = sm.getCreationTime();
+				boolean sameDay = DateUtil.isSameDay(creationTime, new Date());
+				if (!sameDay) {
+					sm = null;
+				}
+			}
+
+			Date now = new Date();
+
+			if (null == sm) {
+				sm = new ShortMessageInfo();
+				sm.setCreationTime(now);
+				sm.setPhone(phone);
+				sm.setTimes(0);
+			} else {
+				List<Date> sendTimeList = sm.getSendTimeList();
+
+				if (10 <= sendTimeList.size()) {
+					throw new StatusException("102000", "一天内发送次数超过10次");
+				} else if (5 <= sendTimeList.size()) {
+					Date d = sendTimeList.get(sendTimeList.size() - 5);
+					if (now.getTime() - d.getTime() < 1000 * 60 * 60) {
+						throw new StatusException("102000", "一小时内发送次数超过5次");
+					}
+				} else {
+					Date d = sendTimeList.get(sendTimeList.size() - 1);
+					if (now.getTime() - d.getTime() < 1000 * 60) {
+						throw new StatusException("102000", "一分钟内发送次数超过1次");
+					}
+				}
+			}
+			// 获取短信配置信息
+			SmsAssemblyCacheBean assemblyCacheBean = CacheHelper
+					.getSmsAssembly(YZM_SMS_ASSEMBLY_CODE);
+			Map<String, String> params = Maps.newHashMap();
+			params.put("code", code);
+			this.sendSms(assemblyCacheBean, Arrays.asList(new String[]{phone}), params);
+
+			sm.getSendTimeList().add(now);
+			sm.setTimes(sm.getSendTimeList().size());
+			sm.setLastMessage(code);
+
+			redisClient.set(key, sm, 60 * 60 * 24);
+		}
+	}
+
+	@Override
+	public void validateSmsCode(String phone, String code) {
+		{
+
+			boolean virtualEnable = PropertyHolder.getBoolean("sms.securityCode.virtual.enable",
+					false);
+
+			if (virtualEnable) {
+				String virtualCode = PropertyHolder.getString("sms.securityCode.virtual.code",
+						"5220");
+				if (!virtualCode.equals(code)) {
+					throw new StatusException("102008", "验证码错误");
+				} else {
+					return;
+				}
+			}
+
+			String key = "$_SMS:" + phone;
+			ShortMessageInfo sm = redisClient.get(key, ShortMessageInfo.class);
+
+			if (null == sm) {
+				throw new StatusException("102001", "未发送验证码");
+			}
+			List<Date> sendTimeList = sm.getSendTimeList();
+			Date date = sendTimeList.get(sendTimeList.size() - 1);
+			Date now = new Date();
+
+			if (now.getTime() - date.getTime() > 1000 * 60 * 5) {
+				throw new StatusException("102002", "验证码过期");
+			}
+
+			if (!sm.getLastMessage().equals(code)) {
+				throw new StatusException("102003", "验证码错误");
+			} else {
+				sm.setLastMessage(UUID.randomUUID());
+				redisClient.set(key, sm);
+			}
+		}
+	}
+
+	/**
+	 * 执行
+	 *
+	 * @param smsAssembly
+	 * @param action
+	 * @param phoneList
+	 * @param templateParams
+	 *            短信模板参数
+	 * @author WANGWEI
+	 */
+	private void execute(SmsAssemblyCacheBean smsAssembly, String action, List<String> phoneList,
+			Map<String, String> templateParams) {
+		String accessKeyId = PropertyHolder.getString("aliyun.sms.accessKeyId");
+		String accessSecret = PropertyHolder.getString("aliyun.sms.accessKeySecret");
+		String signName = smsAssembly.getExt1();
+		String templateCode = smsAssembly.getExt2();
+
+		DefaultProfile profile = DefaultProfile.getProfile("default", accessKeyId, accessSecret);
+		IAcsClient client = new DefaultAcsClient(profile);
+
+		CommonRequest request = new CommonRequest();
+		request.setProtocol(ProtocolType.HTTPS);
+		request.setMethod(MethodType.POST);
+		request.setDomain("dysmsapi.aliyuncs.com");
+		request.setVersion("2017-05-25");
+		request.setAction(action);
+		String phoneNumbers = StringUtils.join(phoneList, ',');
+		request.putQueryParameter("PhoneNumbers", phoneNumbers);
+		request.putQueryParameter("SignName", signName);
+		request.putQueryParameter("TemplateCode", templateCode);
+		request.putQueryParameter("TemplateParam", JsonUtil.toJson(templateParams));
+		try {
+			CommonResponse response = client.getCommonResponse(request);
+			String data = response.getData();
+			JsonParser jp = new JsonParser();
+			JsonObject jsonObj = jp.parse(data).getAsJsonObject();
+			String code = jsonObj.get("Code").getAsString();
+
+			if (!code.equals("OK")) {
+				log.error("aliyun sms response: " + JsonUtil.toJson(response));
+				throw new StatusException("101001", "短信发送失败");
+			}
+
+		} catch (StatusException e) {
+			throw e;
+		} catch (Exception e) {
+			log.error("fail to send SMS", e);
+		}
+	}
+
+}