浏览代码

接入阿里云

杨杰 6 年之前
父节点
当前提交
a8a6b85cb7

+ 0 - 14
src/main/java/com/llisoft/service/msg/controller/MsgController.java

@@ -1,14 +0,0 @@
-package com.llisoft.service.msg.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import io.swagger.annotations.Api;
-
-@Api(tags="短信接口")
-@RestController
-@RequestMapping("/msg")
-public class MsgController {
-	
-	
-}

+ 0 - 14
src/main/java/com/llisoft/service/msg/service/MsgService.java

@@ -1,14 +0,0 @@
-package com.llisoft.service.msg.service;
-
-import org.springframework.stereotype.Service;
-
-/**
- * 阿里云OSS接口调用
- * https://help.aliyun.com/document_detail/101414.html
- * https://api.aliyun.com/?product=Dysmsapi&lang=JAVA#/
- * @author YangJie [2019年2月18日]
- */
-@Service
-public class MsgService {
-
-}

+ 0 - 23
src/main/java/com/llisoft/service/msg/vo/MsgRequestVo.java

@@ -1,23 +0,0 @@
-package com.llisoft.service.msg.vo;
-
-import javax.validation.constraints.NotBlank;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-@ApiModel("短信请求实体")
-public class MsgRequestVo {
-	
-	@ApiModelProperty("KEY")
-	@NotBlank(message="KEY不能为空")
-	private String key;
-
-	public String getKey() {
-		return key;
-	}
-
-	public void setKey(String key) {
-		this.key = key;
-	}
-	
-}

+ 0 - 20
src/main/java/com/llisoft/service/msg/vo/MsgResponseVo.java

@@ -1,20 +0,0 @@
-package com.llisoft.service.msg.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-@ApiModel("短信返回实体")
-public class MsgResponseVo {
-	
-	@ApiModelProperty("URL")
-	private String url;
-
-	public String getUrl() {
-		return url;
-	}
-
-	public void setUrl(String url) {
-		this.url = url;
-	}
-	
-}

+ 3 - 1
src/main/java/com/llisoft/service/msg/Application.java → src/main/java/com/llisoft/service/sms/Application.java

@@ -1,11 +1,13 @@
-package com.llisoft.service.msg;
+package com.llisoft.service.sms;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.scheduling.annotation.EnableAsync;
 
+@EnableAsync // 启动异步任务
 @EnableEurekaClient // 注册中心客户端 同类注解 @EnableDiscoveryClient
 @SpringBootApplication
 public class Application {

+ 1 - 1
src/main/java/com/llisoft/service/msg/config/ErrorConfig.java → src/main/java/com/llisoft/service/sms/config/ErrorConfig.java

@@ -1,4 +1,4 @@
-package com.llisoft.service.msg.config;
+package com.llisoft.service.sms.config;
 
 import java.util.Objects;
 

+ 1 - 1
src/main/java/com/llisoft/service/msg/config/ExceptionConfig.java → src/main/java/com/llisoft/service/sms/config/ExceptionConfig.java

@@ -1,4 +1,4 @@
-package com.llisoft.service.msg.config;
+package com.llisoft.service.sms.config;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 1 - 1
src/main/java/com/llisoft/service/msg/config/SpringMvcConfig.java → src/main/java/com/llisoft/service/sms/config/SpringMvcConfig.java

@@ -1,4 +1,4 @@
-package com.llisoft.service.msg.config;
+package com.llisoft.service.sms.config;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

+ 1 - 1
src/main/java/com/llisoft/service/msg/config/SwaggerConfig.java → src/main/java/com/llisoft/service/sms/config/SwaggerConfig.java

@@ -1,4 +1,4 @@
-package com.llisoft.service.msg.config;
+package com.llisoft.service.sms.config;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;

+ 34 - 0
src/main/java/com/llisoft/service/sms/controller/SmsController.java

@@ -0,0 +1,34 @@
+package com.llisoft.service.sms.controller;
+
+import javax.validation.Valid;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.llisoft.common.exception.MtaException;
+import com.llisoft.common.vo.ResponseVo;
+import com.llisoft.service.sms.service.SmsService;
+import com.llisoft.service.sms.vo.CodeRequestVo;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(tags="短信接口")
+@RestController
+@RequestMapping("/msg")
+public class SmsController {
+	
+	@Autowired
+	private SmsService smsService;
+	
+	
+	@ApiOperation(value="发送验证码")
+	@PostMapping("/code")
+	public ResponseVo<Boolean> code(@Valid @RequestBody CodeRequestVo vo) throws MtaException{
+		return ResponseVo.success(smsService.sendCode(vo.getPhone()));
+	}
+	
+}

+ 71 - 0
src/main/java/com/llisoft/service/sms/service/AliyunService.java

@@ -0,0 +1,71 @@
+package com.llisoft.service.sms.service;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+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.profile.DefaultProfile;
+
+/**
+ * 阿里云SMS接口调用
+ * https://help.aliyun.com/document_detail/101414.html
+ * https://api.aliyun.com/?product=Dysmsapi&lang=JAVA#/
+ * @author YangJie [2019年2月18日]
+ */
+@Service
+public class AliyunService {
+	
+	private Logger logger = LoggerFactory.getLogger(AliyunService.class);
+	
+	@Value("${sms.accessKeyId}")
+	private String accessKeyId;
+	@Value("${sms.accessKeySecret}")
+	private String accessKeySecret;
+	
+	// API客户端
+	private IAcsClient client;
+	
+	@PostConstruct
+	public void init() { // 初始化
+		DefaultProfile profile = DefaultProfile.getProfile("default", accessKeyId, accessKeySecret);
+		client = new DefaultAcsClient(profile);
+	}
+	
+	
+	/**
+	 * 发送短信
+	 * @param phone
+	 * @param code
+	 */
+	@Async
+	public void sendCode(String phone, String code) {
+		logger.info("阿里云发送验证码: {} : {}", phone, code);
+		CommonRequest request = new CommonRequest();
+        //request.setProtocol(ProtocolType.HTTPS);
+        request.setMethod(MethodType.POST);
+        request.setAction("SendSms");
+        request.setDomain("dysmsapi.aliyuncs.com");
+        request.setVersion("2017-05-25");
+        request.putQueryParameter("PhoneNumbers", phone);
+        request.putQueryParameter("SignName", "短信测试"); // 签名
+        request.putQueryParameter("TemplateCode", "SMS_164266655"); // 模板ID
+        request.putQueryParameter("TemplateParam", "{\"code\":\""+code+"\"}");
+        try {
+            CommonResponse response = client.getCommonResponse(request);
+            logger.info("阿里云短信API返回: {}", response.getData());
+        } catch (Exception e) {
+        	logger.error("阿里云短信API异常", e);
+        }
+	
+	}
+
+}

+ 87 - 0
src/main/java/com/llisoft/service/sms/service/SmsService.java

@@ -0,0 +1,87 @@
+package com.llisoft.service.sms.service;
+
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.llisoft.common.util.RandomUtil;
+import com.llisoft.service.sms.util.RedisUtil;
+
+/**
+ * 短信服务
+ * @author YangJie [2019年4月25日]
+ */
+@Service
+public class SmsService {
+	
+	private Logger logger = LoggerFactory.getLogger(SmsService.class);
+	
+	@Autowired
+	private AliyunService aliyunService;
+	
+	
+	/**
+	 * 发送验证码
+	 * 同手机号 每分钟1条/每小时5条/每天10条
+	 * @param phone
+	 */
+	public boolean sendCode(String phone) {
+		logger.info("发送验证码: {}", phone);
+		// 每分钟1条
+		String key = phone + "_limit_minute";
+		String result = RedisUtil.get(key);
+		if(Objects.nonNull(result)) {
+			logger.warn("每分钟限制1条: {}", phone);
+			return false;
+		}
+		RedisUtil.set(key, "", 1, TimeUnit.MINUTES);
+		// 每小时5条
+		key = phone + "_limit_hour";
+		result = RedisUtil.get(key);
+		if(Objects.nonNull(result)) {
+			int count = Integer.parseInt(result);
+			if(count >= 5) {
+				logger.warn("每小时限制5条: {}", phone);
+				return false;
+			}
+			RedisUtil.set(key, count, 1, TimeUnit.HOURS);
+		}else {
+			RedisUtil.set(key, 1, 1, TimeUnit.HOURS);
+		}
+		// 每天10条
+		key = phone + "_limit_day";
+		result = RedisUtil.get(key);
+		if(Objects.nonNull(result)) {
+			int count = Integer.parseInt(result);
+			if(count >= 10) {
+				logger.warn("每小时限制5条: {}", phone);
+				return false;
+			}
+			RedisUtil.set(key, count, 1, TimeUnit.DAYS);
+		}else {
+			RedisUtil.set(key, 1, 1, TimeUnit.DAYS);
+		}
+		// 发送短信
+		String code = String.valueOf(RandomUtil.getRandomInt(4));
+		RedisUtil.set(phone + "_" + code, "", 10, TimeUnit.MINUTES); // 有效期10分钟
+		aliyunService.sendCode(phone, code); // 第三方发送短信
+		return true;
+	}
+	
+	/**
+	 * 检查验证码
+	 * @param phone
+	 * @param code
+	 * @return
+	 */
+	public boolean checkCode(String phone, String code) {
+		logger.info("检查验证码: {} : {}", phone, code);
+		String result = RedisUtil.get(phone + "_" + code);
+		return Objects.nonNull(result);
+	}
+	
+}

+ 103 - 0
src/main/java/com/llisoft/service/sms/util/RedisUtil.java

@@ -0,0 +1,103 @@
+package com.llisoft.service.sms.util;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import com.llisoft.common.util.JsonUtil;
+
+/**
+ * redis处理
+ * @author YangJie [2018年12月26日]
+ */
+@Component
+public class RedisUtil {
+	
+    private static StringRedisTemplate redisTemplate;
+    
+    @Autowired
+    public RedisUtil(StringRedisTemplate redisTemplate) {
+    	RedisUtil.redisTemplate = redisTemplate;
+    }
+    
+	
+	/**
+	 * 获取
+	 * @param key
+	 * @return
+	 */
+    public static String get(String key) {
+        return Objects.isNull(key) ? null : redisTemplate.opsForValue().get(key);
+    }
+	
+    /**
+     * 获取
+     * @param key
+     * @param clazz 目标对象类型
+     * @return
+     */
+    public static <T> T get(String key, Class<T> clazz) {
+    	String value = get(key);
+        return Objects.isNull(value) ? null : JsonUtil.toObject(value, clazz);
+    }
+    
+    /**
+     * 通过正则获取列表
+     * @param pattern
+     * @return
+     */
+    public static Set<String> gets(String pattern) {
+    	return redisTemplate.keys(pattern);
+    }
+    
+    /**
+     * 获取与 key 对应的对象
+     * @param key
+     * @param clazz 目标对象类型
+     * @return
+     */
+    public static long getExpire(String key) {
+    	return redisTemplate.getExpire(key);
+    }
+    
+    /**
+     * 保存
+     * @param key
+     * @param obj
+     */
+    public static void set(String key, Object obj) {
+    	redisTemplate.opsForValue().set(key, JsonUtil.toJson(obj));
+    }
+    
+    /**
+     * 保存
+     * @param key
+     * @param obj
+     * @param timeout 超时时间
+     * @param unit 时间单位
+     */
+    public static void set(String key, Object obj, long timeout, TimeUnit unit) {
+    	redisTemplate.opsForValue().set(key, JsonUtil.toJson(obj), timeout, unit);
+    }
+    
+    /**
+     * 删除
+     * @param key
+     */
+    public static void delete(String key) {
+    	redisTemplate.delete(key);
+    }
+    
+    /**
+     * 删除
+     * @param key
+     */
+    public static void deletes(String pattern) {
+    	redisTemplate.delete(gets(pattern));
+    }
+
+}

+ 23 - 0
src/main/java/com/llisoft/service/sms/vo/CodeRequestVo.java

@@ -0,0 +1,23 @@
+package com.llisoft.service.sms.vo;
+
+import javax.validation.constraints.NotBlank;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("验证码请求实体")
+public class CodeRequestVo {
+	
+	@ApiModelProperty("号码")
+	@NotBlank(message="号码不能为空")
+	private String phone;
+
+	public String getPhone() {
+		return phone;
+	}
+
+	public void setPhone(String phone) {
+		this.phone = phone;
+	}
+
+}

+ 15 - 6
src/main/resources/application.yml

@@ -1,15 +1,16 @@
 ##服务配置
 server:
-  port: 8003 #监听端口
+  port: 8002 #监听端口
   
 ##自定义配置
 mta: 
   debug: true #是否测试
   
 ##短信配置
-
+sms: 
+  accessKeyId: LTAIRXeqRlTnj9NW
+  accessKeySecret: GtpNjn8VUkvPEFyOAL5oBDXoBcHqZ6
     
-
 ##spring配置
 spring: 
   ##应用配置 #服务名称
@@ -18,7 +19,15 @@ spring:
   boot.admin.client:
     instance.preferIp: true #使用IP注册
     url: http://192.168.0.179:1111 #监控服务地址
-    
+ 
+  ##redis配置
+  redis: 
+    host: 192.168.0.172
+    port: 6379
+    database: 2
+    password: 
+    timeout: 1000
+         
 ##注册中心配置
 eureka:
   instance: 
@@ -31,11 +40,11 @@ eureka:
 
 ##监控配置    
 management:
-  server.port: 18003 #监控端口
+  server.port: 18002 #监控端口
   endpoints.web.exposure.include: "*" #开启所有端点
   endpoint.health.show-details: always #显示健康详情
   
 ##日志配置
 logging: 
   level:
-    com.llisoft.service.file.dao: debug
+    com.llisoft: info

+ 9 - 1
src/test/java/com/llisoft/service/msg/ServiceTest.java → src/test/java/com/llisoft/service/sms/ServiceTest.java

@@ -1,17 +1,25 @@
-package com.llisoft.service.msg;
+package com.llisoft.service.sms;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
+import com.llisoft.service.sms.service.SmsService;
+
 @SpringBootTest
 @RunWith(SpringRunner.class)
 public class ServiceTest {
+	
+	@Autowired
+	private SmsService smsService;
 
 	@Test
 	public void test() throws Exception{
 		long begin = System.currentTimeMillis();
+//		System.out.println(smsService.sendCode("13552635233"));
+		System.out.println(smsService.checkCode("13552635233", "5612"));
 		System.out.println("耗时:"+ (System.currentTimeMillis() - begin));
 	}