## 整合阿里云短信服务 用途:注册的时候发送手机验证码 ### 一、开通阿里云短信服务步骤 #### 1.1 登录阿里云 进入控制台,在控制台界面下找到云通信-短信服务  #### 1.2 开通短信服务 点击短信服务进入开通页面,选择同意协议,开通服务 #### 1.3 申请模板管理 需要申请:签名管理与模板管理,先在短信服务管理界面下找到国内消息  模板:就是在你手机上显示的内容是什么,可以在这里进行定义  申请模板,点击添加模板  添加模板内容 选择验证码,模板名称一般要起的有意义,模板内容可以参考常用模板库  填写完毕后,提交申请,一般会秒通过审核 #### 1.4 申请签名管理 点击签名管理  添加签名 注意签名名称要写的具有实际意义,签名来源必须选择一个。如果域名没有备案,请先进行备案。  提交申请  最后,短信服务是付费的,根据资费情况充值一定金额来使用 #### 1.5 创建操作阿里云OSS许可证 阿里云颁发ID与秘钥 如果要使用OSS对象存储,开通OSS许可证,首先需要创建Bucket     #### 1.6 创建 Access Key     ### 二、代码实现 #### 2.1 创建Springboot项目 创建项目结构:包括service,mapper,controller模块,并引入依赖 ~~~xml <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.3.3</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.72</version> </dependency> ~~~ #### 2.2 编写Controller 阿里云的4位或者6位的验证码,并不是由阿里云生成的,而是由程序编写的,阿里云只是做一个传递的过程。 Controller类 ~~~java package cn.hxzy.controller; import cn.hxzy.common.R; import cn.hxzy.service.MsmService; import cn.hxzy.utils.RandomUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/msm") @CrossOrigin public class MsmController { @Autowired private MsmService msmService; @Autowired private RedisTemplate<String,String> redisTemplate; //发送短信的方法 @GetMapping("/send/{phone}") public R sendMsm(@PathVariable String phone){ //1 从redis获取验证码,如果获取到直接返回 String code = redisTemplate.opsForValue().get(phone); if(!StringUtils.isEmpty(code)) { return R.ok().code(Integer.parseInt(code)); } //2 如果redis获取 不到,进行阿里云发送 //生成随机值,传递阿里云进行发送 code = RandomUtil.getFourBitRandom(); Map<String,Object> param = new HashMap<>(); param.put("code",code); //调用service发送短信的方法 boolean isSend = msmService.send(param,phone); if(isSend) { //发送成功,把发送成功验证码放到redis里面 //设置有效时间 redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES); return R.ok(); } else { return R.error().message("短信发送失败"); } } } ~~~ #### 2.3 引入工具类 ~~~java package cn.hxzy.utils; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Random; /** * 获取随机数 */ public class RandomUtil { private static final Random random = new Random(); private static final DecimalFormat fourdf = new DecimalFormat("0000"); private static final DecimalFormat sixdf = new DecimalFormat("000000"); public static String getFourBitRandom() { return fourdf.format(random.nextInt(10000)); } public static String getSixBitRandom() { return sixdf.format(random.nextInt(1000000)); } /** * 给定数组,抽取n个数据 * @param list * @param n * @return */ public static ArrayList getRandom(List list, int n) { Random random = new Random(); HashMap<Object, Object> hashMap = new HashMap<Object, Object>(); // 生成随机数字并存入HashMap for (int i = 0; i < list.size(); i++) { int number = random.nextInt(100) + 1; hashMap.put(number, i); } // 从HashMap导入数组 Object[] robjs = hashMap.values().toArray(); ArrayList r = new ArrayList(); // 遍历数组并打印数据 for (int i = 0; i < n; i++) { r.add(list.get((int) robjs[i])); System.out.print(list.get((int) robjs[i]) + "\t"); } System.out.print("\n"); return r; } } ~~~ 统一返回类型 返回对象 ~~~java package cn.hxzy.common; import lombok.Data; import java.util.HashMap; import java.util.Map; @Data public class R { private Boolean success; private Integer code; private String message; private Map<String, Object> data = new HashMap<String, Object>(); //把构造方法私有 private R() {} //成功的静态方法 public static R ok(){ R r=new R(); r.setSuccess(true); r.setCode(ResultCode.SUCCESS); r.setMessage("成功"); return r; } //失败的静态方法 public static R error(){ R r=new R(); r.setSuccess(false); r.setCode(ResultCode.ERROR); r.setMessage("失败"); return r; } //使用下面四个方法,方面以后使用链式编程 // R.ok().success(true) // r.message("ok).data("item",list) public R success(Boolean success){ this.setSuccess(success); return this; } public R message(String message){ this.setMessage(message); return this; } public R code(Integer code){ this.setCode(code); return this; } public R data(String key, Object value){ this.data.put(key, value); return this; } public R data(Map<String, Object> map){ this.setData(map); return this; } } ~~~ 接口 ~~~java package cn.hxzy.common; public interface ResultCode { Integer SUCCESS=20000; Integer ERROR=20001; } ~~~ redis ~~~java package cn.hxzy.config.redis; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean("redis") @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); //自定义Jackson序列化配置 Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); jsonRedisSerializer.setObjectMapper(objectMapper); //key使用String的序列化方式 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); //hash的key也是用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); //value的key使用jackson的序列化方式 template.setValueSerializer(jsonRedisSerializer); //hash的value也是用jackson的序列化方式 template.setHashValueSerializer(jsonRedisSerializer); template.afterPropertiesSet(); return template; } } ~~~ #### 2.5 application.yml设置连接redis ~~~yaml spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 redis: database: 0 host: 127.0.0.1 port: 6379 ~~~ #### 2.6 编写接口与实现类 Service接口 ~~~java package cn.hxzy.service; import java.util.Map; public interface MsmService { //发送短信的方法 Boolean send(Map<String, Object> param, String phone); } ~~~ ServiceImpl实现类 ~~~java package cn.hxzy.service.impl; import cn.hxzy.service.MsmService; import com.alibaba.fastjson.JSONObject; 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; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Map; @Service public class MsmServiceImpl implements MsmService { //发送短信 @Override public Boolean send(Map<String, Object> param, String phone) { //判断手机号是否为空 if(StringUtils.isEmpty(phone)) return false; DefaultProfile profile = DefaultProfile.getProfile("default", "LTAI5tJHEr4rgFyg5SJL3Ub1", "yqeXTZfzd1mT6BI2Mss2HdAxDKyORY"); 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("SendSms"); //设置发送相关的参数 request.putQueryParameter("PhoneNumbers",phone); //手机号 request.putQueryParameter("SignName","探维世纪官方网站"); //申请阿里云 签名名称 request.putQueryParameter("TemplateCode","SMS_236045641"); //申请阿里云 模板code request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param)); //验证码数据,转换json数据传递 try { //最终发送 CommonResponse response = client.getCommonResponse(request); boolean success = response.getHttpResponse().isSuccess(); return success; }catch(Exception e) { e.printStackTrace(); return false; } } } ~~~