阿里云sms短信服务

  • 阿里云短信介绍
    • 开通阿里云短信服务
    • 添加签名管理与模板管理
    • 获取用户AccessKey
  • 搭建server-msm模块
    • 导入Maven依赖
    • application.yml
    • 启动类
    • 配置网关
  • 封装注册短信验证码接口
    • 配置工具类
    • 随机数工具类
    • service接口和实现类
    • controller
  • common模块
    • pom
    • 全局统一返回结果类Result
    • 统一返回结果状态信息类ResultCodeEnum
    • RedisConfig
    • Swagger2Config
  • swagger测试

项目地址: https://gitee.com/zysheep/springcloudalibaba

阿里云短信介绍

开通阿里云短信服务

添加签名管理与模板管理


获取用户AccessKey



搭建server-msm模块

导入Maven依赖

<dependencies><dependency><groupId>cn.zysheep</groupId><artifactId>common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.16</version></dependency></dependencies>

application.yml

server:port: 9992spring:cloud:nacos:discovery:server-addr: localhost:8848application:name: server-msmjackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8redis:host: localhostport: 6379database: 0timeout: 180000lettuce:pool:max-active: 20max-wait: 1max-idle: 5min-idle: 0aliyun:sms:regionId: defaultaccessKeyId: LT6I0Y5633pX89qC  #阿里云accessKeyIdsecret: jX8D04Dm12I3gGKj345FYSzu0fq8mT #阿里云secret

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class ServerMsmApplication {public static void main(String[] args) {SpringApplication.run(ServerMsmApplication.class,args);}
}

配置网关

在server-gateway网关服务中配置

server:port: 9999spring:application:name: service-gateway# nacos服务地址cloud:nacos:discovery:server-addr: localhost:8848gateway:#使用服务发现路由discovery:locator:enabled: trueroutes:#设置路由id- id: service-consumer  #路由的ID,没有固定规则但要求唯一,简易配合服务名#设置路由的uriuri: lb://service-consumer  #匹配后提供服务的路由地址,lb后跟提供服务的微服务的名,不要写错#设置路由断言,代理servicerId为service-cosumer的/api/路径predicates:- Path=/*/consumer/**  #断言,路径相匹配的进行路由- id: service-provider  #路由的ID,没有固定规则但要求唯一,简易配合服务名#设置路由的uriuri: lb://service-provider  #匹配后提供服务的路由地址,lb后跟提供服务的微服务的名,不要写错#设置路由断言,代理servicerId为service-cosumer的/api/路径predicates:- Path=/*/provider/**  #断言,路径相匹配的进行路由- id: server-msmuri: lb://server-msmpredicates:- Path=/*/msm/**

封装注册短信验证码接口

配置工具类

@Component
public class ConstantPropertiesUtils implements InitializingBean {@Value("${aliyun.sms.regionId}")private String regionId;@Value("${aliyun.sms.accessKeyId}")private String accessKeyId;@Value("${aliyun.sms.secret}")private String secret;public static String REGION_Id;public static String ACCESS_KEY_ID;public static String SECRECT;@Overridepublic void afterPropertiesSet() throws Exception {REGION_Id=regionId;ACCESS_KEY_ID=accessKeyId;SECRECT=secret;}
}

随机数工具类

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>();// 生成随机数字并存入HashMapfor (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;}
}

service接口和实现类

public interface MsmService {//发送手机验证码boolean send(String phone, String code);
}
@Service
public class MsmServiceImpl implements MsmService {@Overridepublic boolean send(String phone, String code) {//判断手机号是否为空if(StringUtils.isEmpty(phone)) {return false;}//整合阿里云短信服务//设置相关参数DefaultProfile profile = DefaultProfile.getProfile(ConstantPropertiesUtils.REGION_Id,ConstantPropertiesUtils.ACCESS_KEY_ID,ConstantPropertiesUtils.SECRECT);IAcsClient client = new DefaultAcsClient(profile);CommonRequest request = new CommonRequest();request.setSysMethod(MethodType.POST);request.setSysDomain("dysmsapi.aliyuncs.com");request.setSysVersion("2017-05-25");request.setSysAction("SendSms");//手机号 属性值不能修改request.putQueryParameter("PhoneNumbers", phone);//签名名称request.putQueryParameter("SignName", "博客验证码");//模板coderequest.putQueryParameter("TemplateCode", "SMS_200690615");//验证码  使用json格式   {"code":"123456"}Map<String,Object> param = new HashMap();param.put("code",code);request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));//调用方法进行短信发送try {CommonResponse response = client.getCommonResponse(request);System.out.println(response.getData());// 是否发送成功return response.getHttpResponse().isSuccess();} catch (ServerException e) {e.printStackTrace();} catch (ClientException e) {e.printStackTrace();}return false;}
}

controller

@Api(tags = "短信服务")
@RestController
@RequestMapping("/api/msm")
public class MsmApiController {@Autowiredprivate MsmService msmService;@Autowiredprivate RedisTemplate<String,String> redisTemplate;@ApiOperation("发送短信")//发送手机验证码@GetMapping("send/{phone}")public Result sendCode(@PathVariable String phone) {//从redis获取验证码,如果获取获取到,返回ok// key 手机号  value 验证码String code = redisTemplate.opsForValue().get(phone);if(!StringUtils.isEmpty(code)) {return Result.ok();}//如果从redis获取不到,// 生成验证码,code = RandomUtil.getSixBitRandom();//调用service方法,通过整合短信服务进行发送boolean isSend = msmService.send(phone,code);//生成验证码放到redis里面,设置有效时间if(isSend) {/** set(phone,code,2, TimeUnit.MINUTES);* phone : 手机号* code : 验证码* 2 : 过期时间* TimeUnit.MINUTES: 时间单位 分钟* */redisTemplate.opsForValue().set(phone,code,2, TimeUnit.MINUTES);return Result.ok();} else {return Result.fail().message("发送短信失败");}}
}

common模块

pom

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- spring2.X集成redis所需common-pool2--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.29</version></dependency><!-- Swagger2 Begin --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version></dependency><!-- Swagger2 End --></dependencies>

全局统一返回结果类Result

/*** 全局统一返回结果类*/
@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {@ApiModelProperty(value = "返回码")private Integer code;@ApiModelProperty(value = "返回消息")private String message;@ApiModelProperty(value = "返回数据")private T data;public Result(){}protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}public static <T> Result<T> build(Integer code, String message) {Result<T> result = build(null);result.setCode(code);result.setMessage(message);return result;}public static<T> Result<T> ok(){return Result.ok(null);}/*** 操作成功* @param data* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public static<T> Result<T> fail(){return Result.fail(null);}/*** 操作失败* @param data* @param <T>* @return*/public static<T> Result<T> fail(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.FAIL);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}public boolean isOk() {if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {return true;}return false;}
}

统一返回结果状态信息类ResultCodeEnum

/*** 统一返回结果状态信息类*/
@Getter
public enum ResultCodeEnum {SUCCESS(200,"成功"),FAIL(201, "失败"),PARAM_ERROR( 202, "参数不正确"),SERVICE_ERROR(203, "服务异常"),DATA_ERROR(204, "数据异常"),DATA_UPDATE_ERROR(205, "数据版本异常"),LOGIN_AUTH(208, "未登陆"),PERMISSION(209, "没有权限"),CODE_ERROR(210, "验证码错误"),
//    LOGIN_MOBLE_ERROR(211, "账号不正确"),LOGIN_DISABLED_ERROR(212, "改用户已被禁用"),REGISTER_MOBLE_ERROR(213, "手机号已被使用"),LOGIN_AURH(214, "需要登录"),LOGIN_ACL(215, "没有权限"),URL_ENCODE_ERROR( 216, "URL编码失败"),ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),//LOGIN_ERROR( 23005, "登录失败"),PAY_RUN(220, "支付中"),CANCEL_ORDER_FAIL(225, "取消订单失败"),CANCEL_ORDER_NO(225, "不能取消预约"),HOSCODE_EXIST(230, "医院编号已经存在"),NUMBER_NO(240, "可预约号不足"),TIME_NO(250, "当前时间不可以预约"),SIGN_ERROR(300, "签名错误"),HOSPITAL_OPEN(310, "医院未开通,暂时不能访问"),HOSPITAL_LOCK(320, "医院被锁定,暂时不能访问"),;private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}
}

RedisConfig

@Configuration
@EnableCaching
public class RedisConfig {/*** 自定义key规则* @return*/@Beanpublic KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, Method method, Object... params) {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};}/*** 设置RedisTemplate规则* @param redisConnectionFactory* @return*/@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);//序列号key valueredisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}/*** 设置CacheManager缓存规则* @param factory* @return*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}}

Swagger2Config

@Configuration
@EnableSwagger2
public class Swagger2Config {@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("cn.zysheep")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("iToken API 文档").description("iToken API 网关接口,http://www.zysheep.cn").termsOfServiceUrl("http://www.zysheep.cn").version("1.0.0").build();}
}

swagger测试

访问http://localhost:9992/swagger-ui.html

测试

查看redis中是否存入手机号对应的验证码

阿里云sms短信服务相关推荐

  1. 一小时学会使用SpringBoot整合阿里云SMS短信服务

    1. 登录阿里云进入控制台 进入阿里云控制台,https://home.console.aliyun.com/在个人头像位置点击进入AccessKey管理: 2. 创建用户和用户组 创建用户组 添加完 ...

  2. 阿里云SMS短信服务的使用

    短信服务是每个商家和企业都会去使用的,用户会收到106开头的号码的短信的内容,多用于用户传递验证码.系统通知等. 下面记录一下使用阿里云短信服务的经验和心得 ~ 以下忽略申请流程,直接接入短息服务.. ...

  3. 对接阿里云sms短信服务发送验证码

    1.购买阿里云短信服务 2.申请签名 3.申请短信模板 4.获取密钥 5.maven依赖 <dependency><groupId>com.aliyun</groupId ...

  4. 解忧云SMS短信服务平台系统 短信发送系统源码 全解密随时可以二开无后门

    解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文件路径 .env ...

  5. Java 对接 阿里云 的短信服务完成短信的发送与查询

    一.开通阿里云短信服务,为开发时需要用到的信息做准备 1.注册或者使用自己的支付宝账号登录阿里云官网 2.搜索并找到短信服务,进行开通(开通是不要钱的,发送短信的时候才需要钱) 3.注册自己的短信签名 ...

  6. 【阿里云】短信服务 无认证 测试版本 附带短信发送工具类

    一.注册阿里云账号并登录阿里云(阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台) 二.找到云短信服务 直接搜索短信,并进入到短信控制台 三.正文 1.绑定测试手机号 测试版存在限制 发送手机 ...

  7. 使用阿里云的短信服务发送短信

    原文地址使用阿里云的短信服务发送短信 在给客户开发一个信息发送功能的时候,需要涉及到短信的发送,短信发送一般不同的厂商提供的接口不同,处理方式也不太一样,之前用的一个厂商的,提供了一个封装类就很容易发 ...

  8. 使用阿里云的短信服务进行登录实现登录拦截的功能(前后端分离) ---- (Session存储验证码用户信息)

    使用阿里云的短信服务进行登录&实现登录拦截的功能(Session存储 开通短信服务 获取AccessKey 搭建前端环境 搭建后端环境 实体类 Dao层 业务层 控制层 配置类 工具类 开通短 ...

  9. 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版

    简介: 全网首发 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文 ...

最新文章

  1. 基于android的家庭财务通 .apk,毕业论文(设计)基于Android的家庭财务管家的设计与实现.doc...
  2. mysql 浏览器插件_Chrome浏览器BlazeMeter插件安装图解
  3. 什么是网络推广浅析网站在优化时该如何让蜘蛛自觉爬行网站?
  4. 多目标跟踪笔记二:Efficient Algorithms for Finding the K Best Paths Through a Trellis
  5. Python 切片的简单讲解
  6. Vue中ref的用法:获取DOM 父获取子数据 父使用子方法 子调用父方法
  7. Async Await
  8. 大数据对社交媒体的影响_数据如何影响媒体,广告和娱乐职业
  9. try catch finally 中包含return的几种情况,及返回结果
  10. 安装windows服务提示输入用户名和密码
  11. 【SQL练习题】1. 多列数据求最大值
  12. 2019-12-17 TCP报头结构
  13. 【第1章】初识MySQL
  14. 《21天学通Java(第7版)》—— 1.10 练习
  15. 免费股票量化交易软件有哪些?
  16. BP神经网络代码示例
  17. 服务器装系统不识别硬盘分区,安装系统无法识别分区解决方法
  18. 不拽术语,如何通俗地讲解机器学习?
  19. OpenGL--摄像机
  20. jq ajax简单使用方法

热门文章

  1. 一只青蛙一次可以跳上1级台阶也可以跳上2级求该青蛙跳上一个n级的台阶总共有多少种跳法
  2. BAT等互联网公司薪资分享
  3. MPB:浙大王谦组-​​菌酶一体化重组酵母工程菌的设计与构建
  4. Win10下运行红色警戒2
  5. 如何在1到100的整数数组中找到缺失的数字
  6. kali虚拟机VMBox安装
  7. Python 爬楼梯问题--有n阶台阶,上楼可以一步上1阶,2阶,3阶,计算共有多少种不同的走法?
  8. 七彩虹 iGame G-ONE Plus 27寸游戏一体机 评测
  9. python足球联赛赛程_足球联赛赛程表工作表
  10. 扎拉赞恩 服务器 微信群,魔兽8.0剧透 回归的扎拉赞恩与沃金的骨灰