短信API——短信验证码

简介

  • 短信服务(Short Message Service、SMS)是指通过调用短信发送API,将指定短信内容发送给指定手机用户。

阿里云短信服务

发送短信(发送验证码)

  • 需要以下配置
    • 在阿里云管理后台右上角,账号 - AccessKey管理中查看accessKeyIdaccessKeySecret
    • 自己配置的短信模板ID(如:SMS_45680123)
    • 模板变量(如果模板中存在变量,如${code})
  • 使用maven
<!-- aliyun短信 -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.1</version>
</dependency>
  • 工具类示例
@Slf4j
public class SmsU {
    public static void main(String[] args) {
        SmsU.sendMessage("15812345678");
    }

    /*********************************************  需要修改的部分start  *************************************************/

    /**
     * 需要替换为自己的ACCESS_KEY_ID
     */
    private static final String ACCESS_KEY_ID = "";

    /**
     * 需要替换为自己的ACCESS_KEY_SECRET
     */
    private static final String ACCESS_KEY_SECRET = "";

    /**
     * 这里要修改为自己的短信签名
     */
    private static final String SIGN_NAME = "";

    /**
     * 修改为自己的模板CODE
     */
    private static final String TEMPLATE_CODE = "";

    /**
     * 模板中的变量名称,例如模板中为${code},此处就填写code
     */
    private static final String TEMPLATE_PARAM = "code";

    /*********************************************  需要修改的部分end  *************************************************/

    private static final Pattern PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
    /**
     * 下面是一些默认的配置,无需修改
     * REGION_ID 服务器大区   不建议修改
     * SYS_DOMAIN API地址   不可修改
     * SYS_VERSION 系统版本 不可修改
     * SYS_ACTION API接口名必须为SendSms 不可修改
     */
    private static final String REGION_ID = "cn-hangzhou";
    private static final String SYS_DOMAIN = "dysmsapi.aliyuncs.com";
    private static final String SYS_VERSION = "2017-05-25";
    private static final String SYS_ACTION = "SendSms";
    private static IAcsClient client = null;
    private static CommonRequest request = null;

    static {
        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        client = new DefaultAcsClient(profile);
        request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(SYS_DOMAIN);
        request.setSysVersion(SYS_VERSION);
        request.setSysAction(SYS_ACTION);
        request.putQueryParameter("RegionId", REGION_ID);
        request.putQueryParameter("SignName", SIGN_NAME);
        request.putQueryParameter("TemplateCode", TEMPLATE_CODE);
    }

    private SmsU() {}

    /**
     * 发送短信
     * @param phoneNumber 手机号码
     * @return code
     */
    public static Result sendMessage(String phoneNumber) {
        if (!isPhoneNumber(phoneNumber)) {
            return Result.failure("手机号格式不正确");
        }

        // 获取六位随机数. 基于Hutool
        String code = RandomUtil.randomString("0123456789", 6);
        // 初始化用户自定义参数
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        // 在短信内容中嵌入随机数
        request.putQueryParameter("TemplateParam", "{\"" + TEMPLATE_PARAM + "\":\"" + code + "\"}");

        // 发送的业务逻辑
        try {
            // {"Message":"账户余额不足","RequestId":"415E9BF0-6904-5920-933A-F27B920E2644","Code":"isv.AMOUNT_NOT_ENOUGH"}
            // {"Message":"触发分钟级流控Permits:1","RequestId":"9D7F3798-1CA1-5110-9056-1ECB14A91097","Code":"isv.BUSINESS_LIMIT_CONTROL"}
            // {"Message":"OK","RequestId":"2E6BD8A4-D1A3-5A25-A237-2AB702893632","Code":"OK","BizId":"303700784907161870^0"}
            CommonResponse response = client.getCommonResponse(request);
            if(response.getHttpStatus() != 200 || !"OK".equals(JSONUtil.parseObj(response.getData()).get("Message"))) {
                log.error("发送短信失败 {} {} {}", phoneNumber, response.getHttpStatus(), response.getData());
                return Result.failure("发送短信失败");
            }
        } catch (Exception e) {
            log.error("发送短信出错 {}", phoneNumber, e);
            return Result.failure("发送短信出错");
        }
        return Result.success(code);
    }

    public static boolean isPhoneNumber(String phoneNumber) {
        Matcher m = PATTERN.matcher(phoneNumber);
        return m.matches();
    }
}
  • 工具类(基于Spring)
@Slf4j
public class SmsU {
    private static volatile SmsU INSTANCE;
    private static final Pattern PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
    /**
     * 下面是一些默认的配置,无需修改
     * REGION_ID 服务器大区   不建议修改
     * SYS_DOMAIN API地址   不可修改
     * SYS_VERSION 系统版本 不可修改
     * SYS_ACTION API接口名必须为SendSms 不可修改
     */
    private static final String REGION_ID = "cn-hangzhou";
    private static final String SYS_DOMAIN = "dysmsapi.aliyuncs.com";
    private static final String SYS_VERSION = "2017-05-25";
    private static final String SYS_ACTION = "SendSms";
    private IAcsClient client = null;
    private CommonRequest request = null;

    private SmsU() {
    }

    public static SmsU getInstance() {
        if (INSTANCE == null) {
            synchronized (SmsU.class) {
                if(INSTANCE == null) {
                    Environment environment = SpringU.getBean(Environment.class);
                    String accessKeyId = environment.getProperty("aezo-app-common.sms.aliyun.access-key-id");
                    String accessKeySecret = environment.getProperty("aezo-app-common.sms.aliyun.access-key-secret");
                    DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, accessKeyId, accessKeySecret);
                    INSTANCE = new SmsU();
                    INSTANCE.client = new DefaultAcsClient(profile);
                    INSTANCE.request = new CommonRequest();
                    INSTANCE.request.setSysMethod(MethodType.POST);
                    INSTANCE.request.setSysDomain(SYS_DOMAIN);
                    INSTANCE.request.setSysVersion(SYS_VERSION);
                    INSTANCE.request.setSysAction(SYS_ACTION);
                    INSTANCE.request.putQueryParameter("RegionId", REGION_ID);

                }
            }
        }
        return INSTANCE;
    }

    /**
     * 发送短信
     * @param phoneNumber 手机号码
     * @return code
     */
    public static String sendMessage(String phoneNumber) {
        // 获取六位随机数
        String randomCode = RandomUtil.randomString("0123456789", 6);
        return sendMessage(phoneNumber, randomCode);
    }

    /**
     * 发送短信
     * @param phoneNumber 手机号码
     * @param randomCode 验证码
     * @return code
     */
    public static String sendMessage(String phoneNumber, String randomCode) {
        Environment environment = SpringU.getBean(Environment.class);
        String signName = environment.getProperty("aezo-app-common.sms.aliyun.sign-name");
        String templateCode = environment.getProperty("aezo-app-common.sms.aliyun.template-code");
        String templateParam = environment.getProperty("aezo-app-common.sms.aliyun.template-param");
        return sendMessage(phoneNumber, randomCode, signName, templateCode, templateParam);
    }

    /**
     * 发送短信
     * @param phoneNumber 手机号码
     * @param randomCode 验证码
     * @param signName 短信签名
     * @param templateCode 模板CODE
     * @param templateParam 模板中的变量名称,例如模板中为${code},此处就填写code
     * @return code
     */
    public static String sendMessage(String phoneNumber, String randomCode, String signName, String templateCode, String templateParam) {
        if (!isPhoneNumber(phoneNumber)) {
            throw new BizException("手机号格式不正确");
        }
        SmsU instance = getInstance();

        instance.request.putQueryParameter("PhoneNumbers", phoneNumber);
        instance.request.putQueryParameter("SignName", signName);
        instance.request.putQueryParameter("TemplateCode", templateCode);
        instance.request.putQueryParameter("TemplateParam", "{\"" + templateParam + "\":\"" + randomCode + "\"}");

        // 发送的业务逻辑
        try {
            // {"Message":"账户余额不足","RequestId":"415E9BF0-6904-5920-933A-F27B920E2644","Code":"isv.AMOUNT_NOT_ENOUGH"}
            // {"Message":"触发分钟级流控Permits:1","RequestId":"9D7F3798-1CA1-5110-9056-1ECB14A91097","Code":"isv.BUSINESS_LIMIT_CONTROL"}
            // {"Message":"OK","RequestId":"2E6BD8A4-D1A3-5A25-A237-2AB702893632","Code":"OK","BizId":"303700784907161870^0"}
            CommonResponse response = instance.client.getCommonResponse(instance.request);
            if(response.getHttpStatus() != 200 || !"OK".equals(JSONUtil.parseObj(response.getData()).get("Message"))) {
                log.error("发送短信失败 {} {} {}", phoneNumber, response.getHttpStatus(), response.getData());
                throw new BizException("发送短信失败");
            }
            log.info("发送短信成功 {} {}", phoneNumber, randomCode);
        } catch (Exception e) {
            log.error("发送短信出错 {}", phoneNumber, e);
            throw new BizException("发送短信出错", e);
        }
        return randomCode;
    }

    public static boolean isPhoneNumber(String phoneNumber) {
        Matcher m = PATTERN.matcher(phoneNumber);
        return m.matches();
    }
}
  • 其中模板中的${code}即为随机生成的验证码,将此验证码发送到用户手机,并将此验证码和其过期时间一起保存到session中供业务验证
posted @ 2017-10-08 17:30  月壹墨  阅读(1039)  评论(0编辑  收藏  举报