SpringBoot+vue 使用阿里云的短信功能发送手机验证码

前言: 小编后端用的是Springboot 前端用的是vue ,小编主要是写后台,前端页面比较简陋,后期还要调优,写的不对处还望多多包涵。

环境: 需要先准备好阿里云的账号和一些必要的参数。详情见我的另一篇博客。

            https://blog.csdn.net/tangthh123/article/details/103769542

阿里云

开发者可以按照阿里云的这个开发者手册开发。

https://help.aliyun.com/document_detail/101300.html?spm=a2c4g.11186623.6.610.5ed850a4DjrhHY

发送短信这个接口如何调用? 这个网址还提供了调试功能,很方便。

https://help.aliyun.com/document_detail/101414.html?spm=a2c4g.11186623.6.624.15b85f30AyGxea

效果图

输入手机号 ,点击获取验证码,调用后台接口每次给手机号码发送验证码,验证码是随机的。

发送到手机上的验证码图片

前端代码

前端使用vue写的,要配置路由,这部分我就先省略了

<template>
  <el-card class="box-card">
    <div slot="header" class="clearfix">
      <span>绑定手机验证码</span>
    </div>
    <el-form>
      <el-form-item>
        <el-input v-model="phoneNumber" placeholder="请输入手机号">
          <el-button slot="append" @click="getVerifyCode" :disabled="disabled">{{btnTitle}}</el-button>
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-input v-model="verifyCode" placeholder="请输入验证码"></el-input>
      </el-form-item>
      <el-button type="primary" @click="bindUserPhone">登录</el-button>
    </el-form>
  </el-card>
</template>

<script>
export default {
  name: "",
  data() {
    return {
      phoneNumber: "",
      verifyCode: "",
      codeStr:"",
      disabled: false,
      btnTitle: "获取验证码",
    };
  },
 methods: {

  bindUserPhone(){
     
         //绑定用户手机验证码
           const bindData = {
             phone: this.phoneNumber,
             verifyNumber : this.verifyCode
           }
            this.$axios.post('/api/boundUserByPhone', bindData).then(res => {
              console.log(res.data.message);
              alert(res.data.message);
            });
     
  },

    //请求发送验证码的方法
    getVerifyCode() {
       // 请求表格数据
   const data = {
    phone: this.phoneNumber
        }
   this.$axios.post('/api/sendMessage', data).then(res => {
        console.log("验证码发送成功");
    });
    }
  }
};

</script>

<style lang="scss" scoped>
.el-input-group__append {
  .el-button {
    padding: 4px;
  }  
}
.el-button.is-disabled, .el-button.is-disabled:focus, .el-button.is-disabled:hover{
  background: none;
}
</style>

后端代码

(1)需要在pom.xml中引用jar包

<!--阿里云短信服务功能-->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>1.1.0</version>
</dependency>

(1).后端代码 我主要是写了俩个接口,sendMessage 这个接口是用来发送短信给手机号码,并且将发送的验证码返回给前端,用来和用户输入的验证码做判断。

需要注意的点:aliYunMessageService.sendSms(phoneNumber, code) 这个方便就是用来封装模板,调用阿里云接口。

(2).boundUserByPhone 这个接口是用户输入验证码以后绑定用户信息的接口,如果没有这个需求的话可以不需要。

接口部分

 /**
     * 使用阿里云发送手机验证码功能
     */
    @PostMapping(value = "/sendMessage")
    public void sendMessageToIphone(@RequestBody AliyunMessageVo vo, HttpSession session) throws Exception {
        //1.准备好请求参数:phoneNumber、TemplateParam
        String phoneNumber = vo.getPhone();
        //随机生成手机验证码
        String code = CheckSumBuilder.getCheckSum();
        //2.调用接口,发短信
        SendSmsResponse response = aliYunMessageService.sendSms(phoneNumber, code);
        Thread.sleep(3000L);
        //查询发送消息接口记录
        if (response.getCode() != null && response.getCode().equals("OK")) {
            QuerySendDetailsResponse querySendDetailsResponse = aliYunMessageService.querySendDetails(response.getBizId(), phoneNumber);
            //对返回结果true 或者false进行一个全局判断
            String responseCode = querySendDetailsResponse.getCode();
            String responseMessage = querySendDetailsResponse.getMessage();
            //OK代表信息发送成功
            if ("OK".equals(responseCode) && "OK".equals(responseMessage)) {
                //将code 保存到session中,并且返回给前端,方便前端用来判断
                session.setAttribute("codeNumber", code);
            }
        }
    }

     /**
     * 根据手机号码绑定用户信息
     *
     * @return
     */
    @PostMapping(value = "/boundUserByPhone")
    public ResultData boundUserByPhone(@RequestBody AliyunMessageVo vo, HttpSession session) {
        BosUserModel userModel = (BosUserModel) session.getAttribute("user");
        vo.setUserModel(userModel);
        //阿里云发送的手机验证码
        String codeNumber = (String) session.getAttribute("codeNumber");
        vo.setNodeNumber(codeNumber);
        return userService.modifyUserModelByPhone(vo);
    }

业务逻辑层

调用阿里云的接口需要传一些参数,参数讲解部分

package com.bos.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.bos.service.AliYunMessageService;
import com.bos.util.AliYunParameterUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author tanghh
 * 阿里云的短信通知发送功能
 * @Date 2019/12/30 16:00
 */
@Service
@Slf4j
public class AliYunMessageServiceImpl implements AliYunMessageService {


    /**
     * @param phoneNumber 手机号
     * @param code        验证码
     * @return
     * @throws ClientException SendSmsResponse
     * @desc :1.发送短信
     */
    @Override
    public SendSmsResponse sendSms(String phoneNumber, String code)  {
        SendSmsResponse sendSmsResponse = null;
        try{
            //1.准备好短信模板变量——验证码code
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", code);
            String TemplateParam = jsonObject.toJSONString();

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

            //3.初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", AliYunParameterUtil.accessKeyId, AliYunParameterUtil.accessSecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", AliYunParameterUtil.PRODUCT, AliYunParameterUtil.DOMAIN);
            IAcsClient acsClient = new DefaultAcsClient(profile);

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

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

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

            //5.hint 此处可能会抛出异常,注意catch
             sendSmsResponse = acsClient.getAcsResponse(request);
        }catch (Exception e){
            log.error("发送阿里云短信失败",e);
        }
        return sendSmsResponse;
    }


    /**
     * @param bizId
     * @param phoneNumber
     * @return
     * @throws ClientException QuerySendDetailsResponse
     * @desc :2.短信发送记录查询接口
     * 用于查询短信发送的状态,是否成功到达终端用户手机
     */
    @Override
    public QuerySendDetailsResponse querySendDetails(String bizId, String phoneNumber) throws ClientException {

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

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", AliYunParameterUtil.accessKeyId, AliYunParameterUtil.accessSecret);
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", AliYunParameterUtil.PRODUCT, AliYunParameterUtil.DOMAIN);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象
        QuerySendDetailsRequest request = new QuerySendDetailsRequest();
        //必填-号码
        request.setPhoneNumber(phoneNumber);
        //可选-流水号
        request.setBizId(bizId);
        //必填-发送日期 支持30天内记录查询,格式yyyyMMdd
        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
        request.setSendDate(ft.format(new Date()));
        //必填-页大小
        request.setPageSize(10L);
        //必填-当前页码从1开始计数
        request.setCurrentPage(1L);

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

        return querySendDetailsResponse;
    }
}
/**
 * 手机验证码登录,绑定用户信息
 * @param vo
 * @return
 */
@Override
public ResultData modifyUserModelByPhone(AliyunMessageVo vo) {
    ResultData resultData = new ResultData();
    try{
        //手机号码
        String phone = vo.getPhone();
        //阿里云发送的手机验证码
        String nodeNumber = vo.getNodeNumber();
        //用户输入的手机验证码
        String verifyNumber = vo.getVerifyNumber();
        //要保证绑定的手机号码是唯一的,如果已有,要提示当前手机号已被注册
        BosUserModel userModel = bosUserJPARepositoty.findBosUserModelByMobile(phone);
        if(userModel!=null){
            //只有阿里云发送的验证码和用户输入的验证码一致的时候,才能绑定到用户信息里面
            if(nodeNumber.equals(verifyNumber)){
                BosUserModel user = vo.getUserModel();
                BosUserModel bosUserModel = bosUserJPARepositoty.findOne(user.getId());
                bosUserModel.setMobile(phone);
                bosUserModel.setIsMobile("1");
                bosUserJPARepositoty.save(bosUserModel);
                resultData.setResult("true");
                resultData.setMessage("绑定手机验证码成功");
            }else{
                resultData.setResult("false");
                resultData.setMessage("验证码错误,请重新输入");
            }
        }else{
            resultData.setResult("false");
            resultData.setMessage("当前手机号码已注册");
        }
    }catch (Exception e){
        resultData.setResult("false");
        resultData.setMessage("绑定手机验证码失败");
        logger.error("绑定手机验证码失败",e);
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
    return resultData;
}

阿里云的参数配置类,参数配置类里面的参数需要替换。

package com.bos.util;

/**
 * @Author tanghh
 * @Date 2019/12/30 15:45
 */
public class AliYunParameterUtil {
    /**
     * 这个需要替换自己的AK(在阿里云的Accesskey管理中寻找)
     */
    public static String accessKeyId = "*****";
    public static String  accessSecret = "*******";

    /**
     * 签名名称(需要替换以及只有审核后才能使用)在阿里云控制台中找到签名管理中的签名名称
     */
    public static String signName ="******";

    /**
     * 模板code (需要替换 以及只有审核后才能使用) 在阿里云控制台中找到模板管理中的模板code
     */
    public static String TemplateCode ="SMS_181236263";

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



    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }
}

其他一些类。

package com.bos.data.model.vo;

import com.bos.data.model.BosUserModel;
import lombok.Data;

/**
 * @Author tanghh
 * @Date 2019/12/30 18:24
 */
@Data
public class AliyunMessageVo {
    /**
     * 电话号码
     */
    private String phone;
    /**
     * 用户信息
     */
    private BosUserModel userModel;
    /**
     * 阿里云发送的手机验证码
     */
    private String nodeNumber;
    /**
     * 用户输入的验证码
     */
    private String verifyNumber;

}

生成验证码的类

package com.bos.aliyun;

import java.util.Random;

/**
 * @Author tanghh
 * 验证码生成器
 * @Date 2019/12/30 16:07
 */
public class CheckSumBuilder {

    /**
     * @param length 字符串长度
     * @param type   类型 (0: 仅数字; 2:仅字符; 别的数字:数字和字符)
     * @return String  随机串
     * @desc :1.随机产生字符串
     */
    public static String getRandomStr(int length, int type) {
        String str = "";
        int beginChar = 'a';
        int endChar = 'z';

        // 只有数字
        if (type == 0) {
            beginChar = 'z' + 1;
            endChar = 'z' + 10;
        }
        // 只有小写字母
        else if (type == 2) {
            beginChar = 'a';
            endChar = 'z';
        }
        // 有数字和字母
        else {
            beginChar = 'a';
            endChar = 'z' + 10;
        }

        // 生成随机类
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int tmp = (beginChar + random.nextInt(endChar - beginChar));
            // 大于'z'的是数字
            if (tmp > 'z') {
                tmp = '0' + (tmp - 'z');
            }
            str += (char) tmp;
        }

        return str;
    }

    /**
     * @return String  6位数字验证码
     * @desc :2.获取6位数字验证码
     */
    public static String getCheckSum() {
        return getRandomStr(6, 0);
    }
}

以上就是这次调用阿里云短信接口的全部代码,如果觉得对你有帮助的话,欢迎评论哦,共同进步。

发布了46 篇原创文章 · 获赞 42 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/tangthh123/article/details/103781524
今日推荐