java 发送手机验证码,阿里云

接着上一篇,这次说手机验证码  ,使用的阿里短信支持

1、使用场景

  移动端或者网站登录,注册等等手机号验证

2、步骤

  2.1、前端,填写手机号,点击发送验证码

  2.2、服务器,生成验证码,调用阿里接口发送验证码,保存验证码和对应key(一般为手机号)

  2.3、用户收到短信,前端输入,提交表单

  2.4、服务器接收请求,校验验证码,处理业务

注:阿里短信申请过程不再此处描述

配置文件设置:

alisms:
  accessKeyId: *******************
  accessSecret: **********************
  signName: *****
  templateCode: ***** //如果只有一个模板可以使用
#根据业务不同我将模板参数配置到枚举类中,便于动态使用 # idCardCode: SMS_18*****74 #身份验证验证码 # LoginCode: SMS_18*****73 #登录确认验证码 # LoginExceptionCode: SMS_187****72 #登录异常验证码 # userRegisterCode: SMS_187****71 #用户注册验证码 # updatePwdCode: SMS_187****70 #修改密码验证码 # changeInfoCode: SMS_18*****69 #信息变更验证码

工具类:

package com.*****.util.sendMessage;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import com.*******.vo.SendCodeDO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* @Description:    短信发送工具
* @Author:         Joe
* @CreateDate:     2020/3/21 15:49
*/
@Configuration
public class SendSmsUtil {
    //阿里云keyID
    @Value("${alisms.accessKeyId}")
    private String accessKeyId;
    //阿里云秘钥,与keyID搭配
    @Value("${alisms.accessSecret}")
    private String accessSecret;
    //短信签名-可在短信控制台中找到
    @Value("${alisms.signName}")
    private String signName;
    // 短信模板-可在短信控制台中找到
    @Value("${alisms.templateCode}")
    private String templateCode;
    //短信验证码集合——用于控制有效时间
    private static Map<String, SendCodeDO> codeMap=new ConcurrentHashMap<>();
    //过期时间
    private static final long expiredTime=1000*10*60;

    /************************请求示例********************************************
     http://dysmsapi.aliyuncs.com/?Signature=NAxwl1W9ROkidJfGeZrsKUXw%2BQ4%3D
     &AccessKeyId=testId
     &Action=SendSms
     &Format=XML
     &RegionId=cn-hangzhou
     &SignatureMethod=HMAC-SHA1
     &SignatureNonce=313ef0fb-0393-464f-a6e2-59d9ca2585b1
     &SignatureVersion=1.0
     &Timestamp=2019-01-08T08%3A18%3A18Z
     &Version=2017-05-25
     ***************************************************************************/


    /**
     * PhoneNumbers 手机号
     * TemplateParam 验证码
     * templateCode2 短信模板——根据不同模板发送不同消息
        例如:1、你当前正在登陆,验证码为111111
             2、你正在进行身份验证,验证码为111111
     */
    public String aliSendSms(String PhoneNumbers,String TemplateParam,String templateCode2){
        String result = "";
        //  regionId:API支持的RegionID,如短信API的值为:cn-hangzhou;
        // AccessKey ID和AccessKey Secret是您访问阿里云API的密钥,具有该账户完全的权限.
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);

        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        //请求格式
        request.setMethod(MethodType.POST);
        //请求地址
        request.setDomain("dysmsapi.aliyuncs.com");

        //API 的版本号,格式为 YYYY-MM-DD。取值范围:2017-05-25。
        request.setVersion("2017-05-25");

        //不可改:阿里云系统规定参数——取值:SendSms。
        request.setAction("SendSms");

        request.putQueryParameter("RegionId", "cn-hangzhou");//不需要修改

        //必填:待发送手机号
        request.putQueryParameter("PhoneNumbers", PhoneNumbers);

        // 必填:短信签名-可在短信控制台中找到必须是已添加、并通过审核的短信签名
        request.putQueryParameter("SignName", signName);

        // 必填:短信模板-可在短信控制台中找到;必须是已添加、并通过审核的短信签名;且发送国际/港澳台消息时,请使用国际/港澳台短信模版。
        request.putQueryParameter("TemplateCode", templateCode2);

        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.putQueryParameter("TemplateParam", TemplateParam);

        try {
            //发送请求并获取请求结果
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            String infojson = response.getData();
            //将结果转换为Map
            Gson gson2 = new Gson();
            Map map = gson2.fromJson(infojson, Map.class);
            String codes = map.get("Message").toString();
            System.out.println("codes="+codes);
            //判断返回值是否成功
            if(codes.equals("OK")){
                result="ok";
            }else {
                result="not_ok";
            }
        } catch (ServerException e) {
            //异常信息打印
            e.printStackTrace();
        } catch (ClientException e) {
            //异常信息打印
            e.printStackTrace();
        }
        //输出结果
        System.out.println("result="+result);
        return result;
    }

    /**
     *将验证码保存至集合中
      * @param key
     * @param code
     *@return ()
     *@throws
     *@author yutf
     *@date 2020/5/23
     *
     */
    public void saveMap(String key,String code){
        //保存验证码
        SendCodeDO sendCodeDO=new SendCodeDO();
        sendCodeDO.setCode(code);
        sendCodeDO.setSendTime(System.currentTimeMillis());
        codeMap.put(key,sendCodeDO);
    }

    /**
     *阿里云短信发送——单个模板发送信息
      * @param PhoneNumbers
     * @param TemplateParam
     *@return ({@link java.lang.String})
     *@throws
     *@author yutf
     *@date 2020/5/23
     *
     */
    public String aliSendSms(String PhoneNumbers,String TemplateParam){
        String result = "";
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", PhoneNumbers);
        request.putQueryParameter("SignName", signName);
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", TemplateParam);
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            String infojson = response.getData();
            Gson gson2 = new Gson();
            Map map = gson2.fromJson(infojson, Map.class);
            String codes = map.get("Message").toString();
            System.out.println("codes="+codes);
            if(codes.equals("OK")){
                result="ok";
            }else {
                result="not_ok";
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        System.out.println("result="+result);
        return result;
    }

    /**
     *校验验证码
      * @param key
     * @param code
     *@return ({@link boolean})
     *@throws
     *@author yutf
     *@date 2020/5/23
     *
     */
    public static boolean verifyCode( String key,String code){
        //清理集合中过期的验证码
        cleanEmailMap();
        //如果集合中包含验证码则返回true否则返回false
        if(codeMap.containsKey(key)){
           if(codeMap.get(key).getCode().equals(code)){
               return true;
           }
        }
        return false;
    }

    /**
     *
     清理集合中过期的验证码
     *@return ()
     *@throws
     *@author yutf
     *@date 2020/5/23
     *
     */
    public static void cleanEmailMap() {
        //如果集合不为空
       if(!codeMap.isEmpty()){
           //循环集合——如果当前时间减去验证码创建时间大于过期时间则清除验证码
           for (Map.Entry<String, SendCodeDO> stringSendEmailDOEntry : codeMap.entrySet()) {
               if(((System.currentTimeMillis()-stringSendEmailDOEntry.getValue().getSendTime())>expiredTime)){
                   codeMap.remove(stringSendEmailDOEntry.getKey());
               }
           }
       }
    }

}

应用到的实体

package com.*****.vo;

import lombok.Data;

/**
 * 功能:
 * 〈验证码实体〉
 *
 * @author ytf
 * @create 2020/4/22
 * @since 1.0.0
 */
@Data
public class SendCodeDO {
    private String code;
    private long sendTime;
}

使用示例

 /**
     * 发送验证码——身份验证验证码
     * @param PhoneNumbers 手机号
     * @return
     */
    @ApiOperation(value = "发送验证码——登录;参数——手机号")
    @GetMapping(value = "/sendSms")
    public ResultVo loginCodeSendSms(String PhoneNumbers){
        if(StringUtils.isBlank(PhoneNumbers)){
            return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FAIL,"手机号不能为空");
        }
        //随机生成验证码
        String numeral = String.valueOf(new Random().nextInt(899999) + 100000);
        SmsData smsData = new SmsData(numeral);
     //发送验证码 Gson gson
= new Gson(); String code = gson.toJson(smsData); String information = sendSmsUtil.aliSendSms(PhoneNumbers, code, TypeConstant.ShortMessageType.loginCode.getCode()); String key=PhoneNumbers+TypeConstant.ShortMessageType.loginCode.getCode()+TypeConstant.PlatformType.app.getCode();
    //保存 sendSmsUtil.saveMap(key,numeral);
if(information.equals("ok")){ return ResultVOUtils.success("短信已发送,请注意查收"); } return ResultVOUtils.error(ResultEnum.NOT_NETWORK,"短信发送失败,请联系管理员"); } /** * 验证 * @param PhoneNumbers * @param code * @return */ @ApiOperation(value = "登录:参数——手机号,验证码") @RequestMapping(value = "/loginCode/verifySms",method = RequestMethod.POST) public ResultVo<B01UserAppVO> loginCodeVerifySms(String PhoneNumbers, String code){ if(StringUtils.isBlank(PhoneNumbers)){ throw new JsonException(ResultEnum.PARAM_VERIFY_FAIL,"手机号不能为空"); } if(StringUtils.isBlank(code)){ throw new JsonException(ResultEnum.PARAM_VERIFY_FAIL,"验证码不能为空"); } String key=PhoneNumbers+TypeConstant.ShortMessageType.loginCode.getCode()+TypeConstant.PlatformType.app.getCode();
     //校验
boolean b = sendSmsUtil.verifyCode(key, code); if(b){ // 处理业务逻辑...... } return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FAIL,"验证码错误"); }

枚举类代码

 /**
     * 功能描述: <br>
     * 〈短息你验证码类型编码〉
     #  idCardCode: SMS_187*****74   #身份验证验证码
     #  LoginCode: SMS_187*****73    #登录确认验证码
     #  LoginExceptionCode: SMS_18****672   #登录异常验证码
     #  userRegisterCode: SMS_1*****671   #用户注册验证码
     #  updatePwdCode: SMS_18*****670   #修改密码验证码
     #  changeInfoCode: SMS_187*****69   #信息变更验证码
     * @return:
     * @since: 1.0.0
     * @Author:
     * @Date:
     */
    public enum ShortMessageType {

        idCardCode("SMS_18*****674","身份验证验证码"),
        loginCode("SMS_187****73","登录确认验证码"),
        loginExceptionCode("SMS_1875****2","登录异常验证码"),
        userRegisterCode("SMS_18******671","用户注册验证码"),
        updatePwdCode("SMS_187******70","修改密码验证码"),
        changeInfoCode("SMS_187*****69","信息变更验证码");
        private String code;
        private String msg;

        private ShortMessageType(String code, String msg){
            this.code =code;
            this.msg = msg;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }


    }

猜你喜欢

转载自www.cnblogs.com/yutf/p/13177751.html