阿里云sms短信服务
阿里云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短信服务相关推荐
- 一小时学会使用SpringBoot整合阿里云SMS短信服务
1. 登录阿里云进入控制台 进入阿里云控制台,https://home.console.aliyun.com/在个人头像位置点击进入AccessKey管理: 2. 创建用户和用户组 创建用户组 添加完 ...
- 阿里云SMS短信服务的使用
短信服务是每个商家和企业都会去使用的,用户会收到106开头的号码的短信的内容,多用于用户传递验证码.系统通知等. 下面记录一下使用阿里云短信服务的经验和心得 ~ 以下忽略申请流程,直接接入短息服务.. ...
- 对接阿里云sms短信服务发送验证码
1.购买阿里云短信服务 2.申请签名 3.申请短信模板 4.获取密钥 5.maven依赖 <dependency><groupId>com.aliyun</groupId ...
- 解忧云SMS短信服务平台系统 短信发送系统源码 全解密随时可以二开无后门
解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文件路径 .env ...
- Java 对接 阿里云 的短信服务完成短信的发送与查询
一.开通阿里云短信服务,为开发时需要用到的信息做准备 1.注册或者使用自己的支付宝账号登录阿里云官网 2.搜索并找到短信服务,进行开通(开通是不要钱的,发送短信的时候才需要钱) 3.注册自己的短信签名 ...
- 【阿里云】短信服务 无认证 测试版本 附带短信发送工具类
一.注册阿里云账号并登录阿里云(阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台) 二.找到云短信服务 直接搜索短信,并进入到短信控制台 三.正文 1.绑定测试手机号 测试版存在限制 发送手机 ...
- 使用阿里云的短信服务发送短信
原文地址使用阿里云的短信服务发送短信 在给客户开发一个信息发送功能的时候,需要涉及到短信的发送,短信发送一般不同的厂商提供的接口不同,处理方式也不太一样,之前用的一个厂商的,提供了一个封装类就很容易发 ...
- 使用阿里云的短信服务进行登录实现登录拦截的功能(前后端分离) ---- (Session存储验证码用户信息)
使用阿里云的短信服务进行登录&实现登录拦截的功能(Session存储 开通短信服务 获取AccessKey 搭建前端环境 搭建后端环境 实体类 Dao层 业务层 控制层 配置类 工具类 开通短 ...
- 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版
简介: 全网首发 解忧云SMS短信服务平台系统 短信发送系统 全解密完美版 经过一系列修复现在程序已经可以完全使用. 并且是全解密随时可以二开.无后门. 一些bug已经完全修复 安装教程 数据库配置文 ...
最新文章
- 基于android的家庭财务通 .apk,毕业论文(设计)基于Android的家庭财务管家的设计与实现.doc...
- mysql 浏览器插件_Chrome浏览器BlazeMeter插件安装图解
- 什么是网络推广浅析网站在优化时该如何让蜘蛛自觉爬行网站?
- 多目标跟踪笔记二:Efficient Algorithms for Finding the K Best Paths Through a Trellis
- Python 切片的简单讲解
- Vue中ref的用法:获取DOM 父获取子数据 父使用子方法 子调用父方法
- Async Await
- 大数据对社交媒体的影响_数据如何影响媒体,广告和娱乐职业
- try catch finally 中包含return的几种情况,及返回结果
- 安装windows服务提示输入用户名和密码
- 【SQL练习题】1. 多列数据求最大值
- 2019-12-17 TCP报头结构
- 【第1章】初识MySQL
- 《21天学通Java(第7版)》—— 1.10 练习
- 免费股票量化交易软件有哪些?
- BP神经网络代码示例
- 服务器装系统不识别硬盘分区,安装系统无法识别分区解决方法
- 不拽术语,如何通俗地讲解机器学习?
- OpenGL--摄像机
- jq ajax简单使用方法
热门文章
- 一只青蛙一次可以跳上1级台阶也可以跳上2级求该青蛙跳上一个n级的台阶总共有多少种跳法
- BAT等互联网公司薪资分享
- MPB:浙大王谦组-​​菌酶一体化重组酵母工程菌的设计与构建
- Win10下运行红色警戒2
- 如何在1到100的整数数组中找到缺失的数字
- kali虚拟机VMBox安装
- Python 爬楼梯问题--有n阶台阶,上楼可以一步上1阶,2阶,3阶,计算共有多少种不同的走法?
- 七彩虹 iGame G-ONE Plus 27寸游戏一体机 评测
- python足球联赛赛程_足球联赛赛程表工作表
- 扎拉赞恩 服务器 微信群,魔兽8.0剧透 回归的扎拉赞恩与沃金的骨灰