页面预览
绑定手机号

未绑定手机号

已绑定手机号

第01章-短信发送
1、云市场-短信API
1.1、开通三网106短信
在阿里云云市场搜索“短信”,一般都可用,选择一个即可,例如如下:点击“立即购买”开通
这里开通的是【短信验证码- 快速报备签名】

1.2、获取开发参数
登录云市场控制台,在已购买的服务中可以查看到所有购买成功的API商品情况,下图红框中的就是AppKey/AppSecret,AppCode的信息。

1.3、API方式使用云市场服务
将工具类放入service-yun微服务的utils包中:资料:资料>短信发送>工具类
参考如下例子,复制代码在test目录进行测试

2、发送短息
2.1、Controller
创建FrontSmsController- package com.atguigu.syt.yun.controller.front;
- @Api(tags = "短信接口")
- @RestController
- @RequestMapping("/front/yun/sms")
- public class FrontSmsController {
- @Resource
- private SmsService smsService;
- @Resource
- private RedisTemplate redisTemplate;
- @ApiOperation("发送短信")
- @ApiImplicitParam(name = "phone",value = "手机号")
- @PostMapping("/send/{phone}")
- public Result send(@PathVariable String phone) {
- //生成验证码
- int minutes = 5; //验证码5分钟有效
- String code = RandomUtil.getFourBitRandom();
- //创建短信发送对象
- SmsVo smsVo = new SmsVo();
- smsVo.setPhone(phone);
- smsVo.setTemplateCode("CST_qozfh101");
- Map<String,Object> paramsMap = new HashMap<String, Object>(){{
- put("code", code);
- put("expire_at", 5);
- }};
- smsVo.setParam(paramsMap);
- //发送短信
- smsService.send(smsVo);
- //验证码存入redis
- redisTemplate.opsForValue().set("code:" + phone, code, minutes, TimeUnit.MINUTES);
- return Result.ok().message("短信发送成功");
- }
- }
复制代码 2.2、Service
接口:SmsService- package com.atguigu.syt.yun.service;
- public interface SmsService {
- /**
- * 发送短信
- * @param smsVo
- */
- void send(SmsVo smsVo);
- }
复制代码 实现:SmsServiceImpl- package com.atguigu.syt.yun.service.impl;
- @Service
- @Slf4j
- public class SmsServiceImpl implements SmsService {
- @Override
- public void send(SmsVo smsVo) {
- String host = "https://dfsns.market.alicloudapi.com";
- String path = "/data/send_sms";
- String method = "POST";
- String appcode = "你的appcode";
- Map<String, String> headers = new HashMap<>();
- //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
- headers.put("Authorization", "APPCODE " + appcode);
- //根据API的要求,定义相对应的Content-Type
- headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
- Map<String, String> querys = new HashMap<>();
- Map<String, String> bodys = new HashMap<>();
- StringBuffer contentBuffer = new StringBuffer();
- smsVo.getParam().entrySet().forEach( item -> {
- contentBuffer.append(item.getKey()).append(":").append(item.getValue()).append(",");
- });
- String content = contentBuffer.substring(0, contentBuffer.length() - 1);
- bodys.put("content", content);
- bodys.put("phone_number", smsVo.getPhone());
- bodys.put("template_id", smsVo.getTemplateCode());
- try {
- /**
- * 重要提示如下:
- * HttpUtils请从
- * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
- * 下载
- *
- * 相应的依赖请参照
- * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
- */
- HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
- //获取response的body
- String data = EntityUtils.toString(response.getEntity());
- HashMap<String, String> resultMap = JSONObject.parseObject(data, HashMap.class);
- String status = resultMap.get("status");
- if(!"OK".equals(status)){
- String reason = resultMap.get("reason");
- log.error("短信发送失败:status = " + status + ", reason = " + reason);
- throw new GuiguException(ResultCodeEnum.FAIL.getCode(), "短信发送失败");
- }
- } catch (Exception e) {
- log.error(ExceptionUtils.getStackTrace(e));
- throw new GuiguException(ResultCodeEnum.FAIL.getCode(), "短信发送失败");
- }
- }
- }
复制代码 3、绑定手机号
3.1、Controller
service-user微服务FrontUserInfoController中添加接口方法- @ApiOperation("绑定手机号")
- @ApiImplicitParams({
- @ApiImplicitParam(name = "phone",value = "手机号", required = true),
- @ApiImplicitParam(name = "code",value = "验证码", required = true)})
- @PostMapping("/auth/bindPhone/{phone}/{code}")
- public Result bindPhone(@PathVariable String phone, @PathVariable String code, HttpServletRequest request, HttpServletResponse response) {
- Long userId = authContextHolder.checkAuth(request, resposne);
- userInfoService.bindPhone(userId, phone, code);
- return Result.ok().message("绑定成功");
- }
复制代码 3.2、Service
接口:UserInfoService- /**
- * 绑定当前用户的手机号
- * @param userId
- * @param phone
- * @param code
- */
- void bindPhone(Long userId, String phone, String code);
复制代码 实现:UserInfoServiceImpl- @Resource
- private RedisTemplate redisTemplate;
- @Override
- public void bindPhone(Long userId, String phone, String code) {
- //校验参数
- if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) {
- throw new GuiguException(ResultCodeEnum.PARAM_ERROR);
- }
- //校验验证码
- String phoneCode = (String)redisTemplate.opsForValue().get("code:" + phone);
- if(!code.equals(phoneCode)) {
- throw new GuiguException(ResultCodeEnum.CODE_ERROR);
- }
- //根据手机号查找会员
- LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
- //手机号没有被其他人绑定过
- queryWrapper.eq(UserInfo::getPhone, phone).ne(UserInfo::getId, userId);
- UserInfo userInfo = baseMapper.selectOne(queryWrapper);
- //手机号已存在
- if(userInfo != null) {
- throw new GuiguException(ResultCodeEnum.REGISTER_MOBILE_ERROR);
- }
- //设置绑定手机号
- userInfo = new UserInfo();
- userInfo.setId(userId);
- userInfo.setPhone(phone);
- baseMapper.updateById(userInfo);
- }
复制代码 4、前端整合
4.1、api
创建sms.js- import request from '~/utils/request'
- export default {
- sendCode(phone) {
- return request({
- url: `/front/yun/sms/send/${phone}`,
- method: `post`
- })
- }
- }
复制代码 在userInfo.js中添加方法- bindPhone(phone, code) {
- return request({
- url: `/front/user/userInfo/auth/bindPhone/${phone}/${code}`,
- method: `post`
- })
- },
复制代码 4.2、页面组件
复制页面到项目pages目录中
资料:资料>手机号绑定页面
第02章-引入MQ
预约或取消预约成功后我们要 更新预约数 以及 发送短信提醒,为了实现用户下单和取消订单的快速响应,这部分逻辑我们就交给MQ完成。
1、引入RabbitMQ
1.1、安装RabbitMQ
- #拉取镜像
- docker pull rabbitmq:3.8-management
- #创建容器启动
- docker run -d --restart=always -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:3.8-management
复制代码 1.2、访问管理后台
http://192.168.100.101:15672
登录:guest / guest
1.3、创建rabbit-utils模块
在common模块中创建rabbit-utils模块
1.4、引入依赖
在rabbit-utils中引入依赖- <dependencies>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-amqp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- </dependencies>
复制代码 1.5、创建RabbitService类
添加sendMessage方法- package com.atguigu.syt.rabbit;
- @Service
- @Slf4j
- public class RabbitService {
- @Resource
- private RabbitTemplate rabbitTemplate;
-
- /**
- * 发送消息
- * @param exchange 交换机
- * @param routingKey 路由
- * @param message 消息
- */
- public boolean sendMessage(String exchange, String routingKey, Object message) {
- log.info("发送消息...........");
- rabbitTemplate.convertAndSend(exchange, routingKey, message);
- return true;
- }
- }
复制代码 1.6、配置MQ消息转换器
- package com.atguigu.syt.rabbit.config;
- @Configuration
- public class MQConfig {
- @Bean
- public MessageConverter messageConverter(){
- //配置json字符串转换器,默认使用SimpleMessageConverter
- return new Jackson2JsonMessageConverter();
- }
- }
复制代码 1.7、添加常量类
- package com.atguigu.syt.rabbit.config;
- public class MQConst {
- /**
- * 预约/取消订单
- */
- public static final String EXCHANGE_DIRECT_ORDER = "exchange.direct.order";
- public static final String ROUTING_ORDER = "routing.order";
- public static final String QUEUE_ORDER = "queue.order";
- /**
- * 短信
- */
- public static final String EXCHANGE_DIRECT_SMS = "exchange.direct.sms";
- public static final String ROUTING_SMS = "routing.sms";
- public static final String QUEUE_SMS = "queue.sms";
- }
复制代码 2、service-yun中发送短信
2.1、引入依赖
- <dependency>
- <groupId>com.atguigu</groupId>
- <artifactId>rabbit-utils</artifactId>
- <version>1.0</version>
- </dependency>
复制代码 2.2、添加MQ配置
- spring:
- rabbitmq:
- host: 192.168.100.101
- port: 5672
- username: guest
- password: guest
复制代码 2.3、封装MQ监听器
在监听器中发送短信:- package com.atguigu.syt.yun.receiver;
- @Component
- @Slf4j
- public class SmsReceiver {
- @Resource
- private SmsService smsService;
- /**
- * 监听MQ中的消息
- * @param smsVo
- */
- @RabbitListener(bindings = @QueueBinding(
- value = @Queue(value = MQConst.QUEUE_SMS, durable = "true"), //消息队列,并持久化
- exchange = @Exchange(value = MQConst.EXCHANGE_DIRECT_SMS), //交换机
- key = {MQConst.ROUTING_SMS} //路由
- ))
- public void receive(SmsVo smsVo){
- log.info("SmsReceiver 监听器监听到消息......");
- smsService.send(smsVo);
- }
- }
复制代码 3、service-hosp中更新排班数量
3.1、引入依赖
- <dependency>
- <groupId>com.atguigu</groupId>
- <artifactId>rabbit-utils</artifactId>
- <version>1.0</version>
- </dependency>
复制代码 3.2、添加MQ配置
- spring:
- rabbitmq:
- host: 192.168.100.101
- port: 5672
- username: guest
- password: guest
复制代码 3.3、封装MQ监听器
在监听器中更新排班数量:- package com.atguigu.syt.hosp.receiver;
- @Component
- @Slf4j
- public class HospReceiver {
- @Resource
- private ScheduleService scheduleService;
- /**
- * 监听MQ中的消息
- * @param orderMqVo
- */
- @RabbitListener(bindings = @QueueBinding(
- value = @Queue(value = MQConst.QUEUE_ORDER, durable = "true"), //消息队列,并持久化
- exchange = @Exchange(value = MQConst.EXCHANGE_DIRECT_ORDER), //交换机
- key = {MQConst.ROUTING_ORDER} //路由
- ))
- public void receive(OrderMqVo orderMqVo){
- //修改排班信息
- log.info("HospReceiver 监听器监听到消息......");
- scheduleService.updateByOrderMqVo(orderMqVo);
- }
- }
复制代码 接口:ScheduleService- /**
- * 更新排班数量
- * @param orderMqVo
- */
- void updateByOrderMqVo(OrderMqVo orderMqVo);
复制代码 实现:ScheduleServiceImpl- @Override
- public void updateByOrderMqVo(OrderMqVo orderMqVo) {
- //下单成功更新预约数
- ObjectId objectId = new ObjectId(orderMqVo.getScheduleId());
- //id是objectId
- Schedule schedule = scheduleRepository.findById(objectId).get();
- //id是string
- // Schedule schedule = scheduleRepository.findById(orderMqVo.getScheduleId()).get();
- schedule.setReservedNumber(orderMqVo.getReservedNumber());
- schedule.setAvailableNumber(orderMqVo.getAvailableNumber());
- //主键一致就是更新
- scheduleRepository.save(schedule);
- }
复制代码 4、完善service-orde订单接口
4.1、引入依赖
- <dependency>
- <groupId>com.atguigu</groupId>
- <artifactId>rabbit-utils</artifactId>
- <version>1.0</version>
- </dependency>
复制代码 4.2、添加MQ配置
- spring:
- rabbitmq:
- host: 192.168.100.101
- port: 5672
- username: guest
- password: guest
复制代码 4.3、修改下单方法
OrderInfoServiceImpl类:- @Resource
- private RabbitService rabbitService;
复制代码 submitOrder方法中添加发送消息的业务逻辑:- //使用这两个数据更新平台端的最新的排班数量
- Integer reservedNumber = data.getInteger("reservedNumber");
- Integer availableNumber = data.getInteger("availableNumber");
- //目的1:更新mongodb数据库中的排班数量
- //组装数据同步消息对象
- OrderMqVo orderMqVo = new OrderMqVo();
- orderMqVo.setAvailableNumber(availableNumber);
- orderMqVo.setReservedNumber(reservedNumber);
- orderMqVo.setScheduleId(scheduleId);
- //发消息
- rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_ORDER, MQConst.ROUTING_ORDER, orderMqVo);
- //目的2:给就诊人发短信
- //组装短信消息对象
- SmsVo smsVo = new SmsVo();
- smsVo.setPhone(orderInfo.getPatientPhone());
- //亲爱的用户:您已预约%{hosname}%{hosdepname}%{date}就诊
- //请您于%{time}至%{address}取号,
- //您的就诊号码是%{number},请您及时就诊
- smsVo.setTemplateCode("和客服申请模板编号");
- Map<String,Object> paramsSms = new HashMap<String, Object>(){{
- put("hosname", orderInfo.getHosname());
- put("hosdepname", orderInfo.getDepname());
- put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
- put("time", orderInfo.getFetchTime());
- put("address", orderInfo.getFetchAddress());
- put("number", orderInfo.getNumber());
- }};
- smsVo.setParam(paramsSms);
- //向MQ发消息
- rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);
复制代码 4.4、修改取消订单方法
cancelOrder方法中添加发送消息的业务逻辑:- //获取返回数据
- JSONObject jsonObject = jsonResult.getJSONObject("data");
- Integer reservedNumber = jsonObject.getInteger("reservedNumber");
- Integer availableNumber = jsonObject.getInteger("availableNumber");
- //目的1:更新mongodb数据库中的排班数量
- //组装数据同步消息对象
- OrderMqVo orderMqVo = new OrderMqVo();
- orderMqVo.setAvailableNumber(availableNumber);
- orderMqVo.setReservedNumber(reservedNumber);
- orderMqVo.setScheduleId(orderInfo.getScheduleId());
- //发消息
- rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_ORDER, MQConst.ROUTING_ORDER, orderMqVo);
- //目的2:给就诊人发短信
- //组装短信消息对象
- SmsVo smsVo = new SmsVo();
- smsVo.setPhone(orderInfo.getPatientPhone());
- //亲爱的用户:您已取消%{hosname}%{hosdepname}%{date}就诊
- smsVo.setTemplateCode("和客服申请模板编号");
- Map<String,Object> paramsSms = new HashMap<String, Object>(){{
- put("hosname", orderInfo.getHosname());
- put("hosdepname", orderInfo.getDepname());
- put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
- }};
- smsVo.setParam(paramsSms);
- //向MQ发消息
- rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);
复制代码 5、就诊人提醒
5.1、添加定时任务
在service-order微服务中添加定时任务:创建ScheduledTask类
cron表达式参考:https://qqe2.com/cron- package com.atguigu.syt.order.schedule;
- @Component
- @EnableScheduling //开启定时任务
- @Slf4j
- public class ScheduledTask {
- /**
- * 测试
- * (cron="秒 分 时 日 月 周")
- * *:每隔一秒执行
- * 0/3:从第0秒开始,每隔3秒执行一次
- * 1-3: 从第1秒开始执行,到第3秒结束执行
- * 1,2,3:第1、2、3秒执行
- * ?:不指定,若指定日期,则不指定周,反之同理
- */
- @Scheduled(cron="0/3 * * * * ?")
- public void task1() {
- log.info("task1 执行");
- }
- }
复制代码 5.2、添加就诊人提醒定时任务
- @Resource
- private OrderInfoService orderInfoService;
- @Scheduled(cron = "0 0 18 * * ?")
- public void patientAdviceTask(){
- log.info("执行定时任务");
- orderInfoService.patientAdvice();
- }
复制代码 5.3、Service
需求:就诊前一天晚六点向用户发送就医提醒短信
接口:OrderInfoService- /**
- * 就诊人提醒
- */
- void patientAdvice();
复制代码 实现:OrderInfoServiceImpl- @Override
- public void patientAdvice() {
- //查询明天的预约信息
- LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
- //明天
- String tomorrow = new DateTime().plusDays(1).toString("yyyy-MM-dd");
- queryWrapper.eq(OrderInfo::getReserveDate, tomorrow);
- //未取消
- queryWrapper.ne(OrderInfo::getOrderStatus, OrderStatusEnum.CANCLE.getStatus());
- List<OrderInfo> orderInfoList = baseMapper.selectList(queryWrapper);
- for (OrderInfo orderInfo : orderInfoList) {
- //短信对象
- SmsVo smsVo = new SmsVo();
- smsVo.setPhone(orderInfo.getPatientPhone());
- //就诊提醒:您已预约%{hosname}%{depname}的号源,就诊时间:%{date},就诊人%{name},请您合理安排出行时间
- smsVo.setTemplateCode("和客服申请模板编号");
- Map<String,Object> paramsSms = new HashMap<String, Object>(){{
- put("hosname", orderInfo.getHosname());
- put("hosdepname", orderInfo.getDepname());
- put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
- put("name", orderInfo.getPatientName());
- }};
- smsVo.setParam(paramsSms);
- //发消息
- rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);
- }
- }
复制代码 源码:https://gitee.com/dengyaojava/guigu-syt-parent
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |