基于阿里云平台手机短信验证(用rabbitMq实现消息通知,有核心代码)

前言:

获取AccessKeyID ,AccessKey Secret我就说个大概,大家可以看官方的帮助文档,进行获取,后面的代码部分并没有给出全部的代码,只是为了提供给大家思路,如果有需要,欢迎留言,我私发给他。

一、前期准备

首先注册一个阿里云账号
然后登录,产品分类,选择短信服务
在这里插入图片描述
点击管理控制台
在这里插入图片描述

进入到下面的界面就可以通过新手引导,和开发者指南进行操作了
在这里插入图片描述
国内消息,进去之后可以添加签名和模板
在这里插入图片描述
在这里插入图片描述

输入网址:https://ram.console.aliyun.com/users
创建用户
在这里插入图片描述

授权
在这里插入图片描述
点击你创建好的用户,如下图
在这里插入图片描述
进入之后创建AccessKey,就会找到AccessKeyID和AccessKeySecret
在这里插入图片描述

我们的目的就是得到下面的四个值:

AccessKeyID不要给别人看

AccessKeyID:你自己的accessKeyId
AccessKeySecret:你自己的AccessKeySecret
模板code:模板CODE
签名:签名名称

二、demo
背景:一个用户的微服务user-service,一个手机短信验证微服务sms-service,此时用户输入自己的手机号,会发送过来一个验证码,由于是两个服务我们采取将验证码存在redis里。由于短信接收具有时长不定性,为了提高程序的响应速度,短信发送采用异步的方式,就是说收到消息后发送短信,我们的用户微服务(user-service)我们通过RabbitMq通知短信微服务(sms-service)发送短信。

1、创建一个短信服务

在这里插入图片描述

2、属性抽取

将上面的四个常量抽取到你的yml文件中

application.yml

server:
  port: 8086
spring:
  application:
    name: sms-service
  rabbitmq:
    host: 152.136.203.163
    username: leyou
    password: 你自己的密码
    virtual-host: /v_leyou

leyou:
  sms:
    accessKeyId: # 你自己的accessKeyId
    accessKeySecret:  # 你自己的AccessKeySecret
    signName:  # 签名名称
    verifyCodeTemplate:  # 模板名称CODE
3、注入到属性类中
@ConfigurationProperties(prefix = "leyou.sms")
public class SmsProperties { 
    String accessKeyId;

    String accessKeySecret;

    String signName;

    String verifyCodeTemplate;

     // getter和setter省略
}

prefix的值要和yml中一致
在这里插入图片描述

4、smsUtils (这个官网有模板,复制黏贴就好,然后简单改改)
@Component
@EnableConfigurationProperties(SmsProperties.class)  //使属性类生效
public class SmsUtils {
    @Autowired
    private SmsProperties prop;

    //产品名称:云通信短信API产品,开发者无需替换
    static final String product = "Dysmsapi";
    //产品域名,开发者无需替换
    static final String domain = "dysmsapi.aliyuncs.com";

    static final Logger logger = LoggerFactory.getLogger(SmsUtils.class);

    public SendSmsResponse sendSms(String phone, String code, String signName, String template) throws ClientException {

        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou",
                prop.getAccessKeyId(), prop.getAccessKeySecret());
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象-具体描述见控制台-文档部分内容
        SendSmsRequest request = new SendSmsRequest();
        request.setMethod(MethodType.POST);
        //必填:待发送手机号
        request.setPhoneNumbers(phone);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName(signName);
        //必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(template);
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.setTemplateParam("{\"code\":\"" + code + "\"}");

        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
        //request.setSmsUpExtendCode("90997");

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        request.setOutId("123456");

        //hint 此处可能会抛出异常,注意catch
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

        logger.info("发送短信状态:{}", sendSmsResponse.getCode());
        logger.info("发送短信消息:{}", sendSmsResponse.getMessage());

        return sendSmsResponse;
    }
}
5、SmsListener
@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SmsListener {

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private SmsProperties prop;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.SMS.QUEUE", durable = "true"),
            exchange = @Exchange(value = "LEYOU.SMS.EXCHANGE", ignoreDeclarationExceptions = "true"),
            key={"sms.verify.code"}))
    public void listenSms(Map<String, String> msg) throws ClientException {
        if(CollectionUtils.isEmpty(msg))
        {
            //放弃处理
            return;
        }
        String phone=msg.get("phone");
        String code=msg.get("code");

        if (StringUtils.isBlank(phone)||StringUtils.isBlank(code)){
            return;
        }
        SendSmsResponse resp  =this.smsUtils.sendSms(phone,code,prop.getSignName(),prop.getVerifyCodeTemplate());
    }
}
6、创建一个用户微服务

在这里插入图片描述

7、UserController代码
    /**
     * 生成短信验证码
     * @param phone
     * @return
     */
    @PostMapping("code")
    public ResponseEntity<Void> sendVerifyCode(String phone){
        Boolean aBoolean = this.userService.sendVerifyCode(phone);
        if (!aBoolean){
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity<>(HttpStatus.CREATED);
    }
8、UserService
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 验证码前缀,这个是注册,的以后可能还会有订单
    static final String KEY_PREFIX = "user:code:phone:";

    static final Logger logger = LoggerFactory.getLogger(UserService.class);


    public Boolean sendVerifyCode(String phone) {
        String code= NumberUtils.generateCode(6);
        try {
            HashMap<String, String> msg = new HashMap<>();
            msg.put("phone",phone);
            msg.put("code",code);
            this.amqpTemplate.convertAndSend("LEYOU.SMS.EXCHANGE","sms.verify.code",msg);
            // 将code存入redis 5分钟失效
            this.stringRedisTemplate.opsForValue().set(KEY_PREFIX+phone,code,5, TimeUnit.MINUTES);
            return true;
        } catch (AmqpException e) {
            logger.error("发送短信失败。phone:{},code:{}",phone,code);
            return false;
        }
    }
9、UserMapper
public interface UserMapper extends Mapper<User> {
}

这里需要引用通用mapper 座标

        <!-- 通用Mapper启动器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
        </dependency>
10启动服务,通过postman测试

在这里插入图片描述

收到短信
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章