基於阿里雲平臺手機短信驗證(用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測試

在這裏插入圖片描述

收到短信
在這裏插入圖片描述

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